Update SPIR-V Tools to 1a7f71afb

Changes:
    1a7f71afb clean: constexpr-ify and unify anon namespace use (#4991)
    8ea3ae6be Split EliminateDeadInputComponents into safe and unsafe versions. (#4984)
    a8647f59c Use Python3 for presubmit (#4986)
    68e8327f2 Instrument: Change output buffer offset definitions (#4961)
    996d4c021 spirv-val: Multiple interface var with same SC (#4969)
    aae7d4132 Fix macos kokoro builds (#4985)
    525bc3806 Add pass to eliminate dead output components (#4982)
    54d4e77fa spirv-opt: Add const folding for CompositeInsert (#4943)
    a5e766b2b spirv-val: Add VUID label for 07703 (#4980)
    d35a78db5 Switch SPIRV-Tools to use spirv.hpp11 internally (#4981)
    c8e1588cf Add passes to eliminate dead output stores (#4970)
    a52de681d Prevent eliminating case constructs in block merging (#4976)
    4563d9093 Only validate full layout in Vulkan environments (#4972)
    9f3a4afae spirv-val: Label new Vulkan OpPtrAccessChain VUs (#4975)
    b49a2caa7 Revert "test" (#4974)
    da215f10c test
    7326b967a Prevent null pointer from being dereferenced (#4971)
    0ebf83057 spirv-val: Add OpPtrAccessChain Base checks (#4965)
    eb113f0fd spirv-val: Improve PR 4831 error message (#4968)
    ecd5b9c16 spirv-val: Add remaining Component decoration validation (#4966)
    b53d3a6be Start SPIRV-Tools v2022.5
    eb0a36633 Finalize SPIRV-Tools v2022.4
    4a6290b56 Update CHANGES
    a9291988d Roll external/spirv-headers/ 4bd8fc0c8..85a1ed200 (4 commits)
    a25a9d0b5 Roll external/re2/ 5723bb895..d2836d1b1 (11 commits)
    59043d177 Roll external/googletest/ 548b13dc3..d9bb8412d (78 commits)
    95ae2da35 Roll external/effcee/ ddf5e2bb9..35912e1b7 (1 commit)
    a3350c0ff Update SPIRV-Headers revision (#4962)
    1cecf9170 Support Narrow Types in BitCast Folding Rule (#4941)
    a6e6454ef spirv-val: Add SPV_ARM_core_builtins validation (#4958)
    4dbc66380 spirv-val: Use ostringstream in id validation tests (#4956)
    07d361b67 spirv-val: Add an option to use friendly names or not (#4951)
    3ec6b3698 spirv-val: Consistently quote ids in messages (#4950)
    e1a8b5d60 build: Fix BUILD.gn build error (#4948)
    49230a230 spirv-opt: Remove unused folding rule (#4942)
    b53d7a8af spirv-val: Add initial SPV_EXT_mesh_shader validation (#4924)
    265b455c9 Fix CreatDebugInlinedAt to not invoke def_use_mgr (#4939)
    ddbee48f8 spirv-opt: Fix stacked CompositeExtract constant folds (#4932)
    f98473cee Remove `spvOpcodeTerminatesExecution` (#4931)
    21146c1b4 Fix builtin validator for unimplemented opcodes. (#4940)
    aeb1c64d4 spirv-val: Make it legal to use arrays of ray queries (#4938)
    11d0d1622 Cleanup code for 272e4b3d0 (#4934)
    91c29a197 spirv-val: Fix comment for checking extended alignments (#4937)
    0c4ce11b4 spirv-val: Update VUID from 1.3.228 Vulkan spec (#4936)
    5f4ce362a spirv-val: Label VUID 07290 (#4927)
    8422d8a44 spirv-val: Label ShaderRecordBufferKHR VUID (#4926)
    c3f844aec spirv-val: Test file suffix consistency (#4925)
    272e4b3d0 Fix missing and incorrect DebugValues (#4929)
    49deada73 Also consider EmitMeshTasksEXT terminator in spirv-opt. (#4930)
    fb27bbf30 Fix DebugInlinedAt Line operand (#4928)
    f5b27b651 spirv-diff: Allow no SpecId (#4904)
    59cf5b134 spirv-val: consider OpEmitMeshTasksEXT a terminator instruction (#4923)
    934a05978 spirv-val: Label Builtin Array Test VUIDs (#4921)
    5f45f793a Support building on OpenBSD (#4912)
    529955e03 Improve time to build dominators (#4916)
    8eb850983 build: cmake: Add support for GNU/Hurd (#4895)
    4386afb05 spirv-opt: Remove unused fold spec const code (#4906)
    4c456f7da Implement tool changes for SPV_EXT_mesh_shader. (#4915)
    33113abf4 Instrument: Add OpNames to generated functions and variables (#4873)
    b5d1040b9 Fix ADCE to mark scope and inlined_at of line instructions as live. (#4910)
    d51dc53d2 Improve algorithm to reorder blocks in a function (#4911)
    fca39d5cb spirv-val: Better message for using OpTypeBool in input/output (#4901)
    66bdbacc9 spirv-val: Use lookup table for Decoration string (#4903)
    f76431cba spirv-val: Add SPV_KHR_ray_tracing storage class (#4868)
    a98f05d02 tests: Make InstrumentPass tests use SinglePassRunAndMatch<> and stateful pattern matching (#4897)
    b41e3e131 Disable DebugInfoMgr during the entire CompactIds pass (#4905)
    3c1a14b2b spirv-val: SBT Index for OpExecuteCallableKHR (#4900)
    0073a1fa3 spirv-val: Remove ImageWrite Texel todo (#4899)
    71b2aee6c Add structs to eliminate dead input components (#4894)
    1728c1d40 spirv-opt: fix copy-propagate-arrays index opti on structs. (#4891)
    9abacb34a Fix ADCE to not eliminate top level DebugInfo instructions (#4889)
    3a8a961cf Fix array copy propagation (#4890)
    afbb52b13 Start SPIRV-Tools v2022.4
    409e11679 Finalize SPIRV-Tools v2022.3
    0a43a84e0 Fix shuffle feeding shuffle with undef literal (#4883)
    0ebcdc4d1 Allow spirv-opt print-all to show pretty IDs (#4888)
    ed3b9c83b Local access chain convert: check for negative indexes (#4884)
    f20e8d05f spirv-val: Add SPV_KHR_ray_tracing instructions (#4871)
    5e61ea209 Update CHANGES (#4886)
    b362d2b7d spirv-diff: Fix asserts in ComparePreambleInstructions() (#4872)
    08c542d34 spirv-val: Label VUID 06997 (#4881)

Commands:
    ./third_party/update-spirvtools.sh

Bug: chromium:1207012
Bug: b/123642959
Change-Id: I62460105fcda972e2e503b778a8e1b1bbbe1977c
diff --git a/third_party/SPIRV-Tools/BUILD.bazel b/third_party/SPIRV-Tools/BUILD.bazel
index 35dfd66..0af7700 100644
--- a/third_party/SPIRV-Tools/BUILD.bazel
+++ b/third_party/SPIRV-Tools/BUILD.bazel
@@ -137,7 +137,7 @@
     copts = COMMON_COPTS,
     includes = ["source"],
     deps = [
-        "@spirv_headers//:spirv_c_headers",
+        "@spirv_headers//:spirv_cpp11_headers",
     ],
 )
 
@@ -162,7 +162,7 @@
     deps = [
         ":generated_headers",
         ":spirv_tools_headers",
-        "@spirv_headers//:spirv_c_headers",
+        "@spirv_headers//:spirv_cpp11_headers",
         "@spirv_headers//:spirv_common_headers",
     ],
 )
diff --git a/third_party/SPIRV-Tools/BUILD.gn b/third_party/SPIRV-Tools/BUILD.gn
index ca0fd91..2194bc5 100644
--- a/third_party/SPIRV-Tools/BUILD.gn
+++ b/third_party/SPIRV-Tools/BUILD.gn
@@ -72,6 +72,8 @@
       rebase_path(cldebuginfo100_insts_file, root_build_dir),
       "--operand-kinds-output",
       rebase_path(operand_kinds_file, root_build_dir),
+      "--output-language",
+      "c++"
     ]
   }
 }
@@ -104,6 +106,8 @@
       rebase_path(extension_enum_file, root_build_dir),
       "--enum-string-mapping-output",
       rebase_path(extension_map_file, root_build_dir),
+      "--output-language",
+      "c++"
     ]
     inputs = [
       core_json_file,
@@ -145,6 +149,8 @@
       rebase_path(glsl_json_file, root_build_dir),
       "--glsl-insts-output",
       rebase_path(glsl_insts_file, root_build_dir),
+      "--output-language",
+      "c++"
     ]
     inputs = [
       core_json_file,
@@ -529,11 +535,13 @@
     "source/val/validate_memory.cpp",
     "source/val/validate_memory_semantics.cpp",
     "source/val/validate_memory_semantics.h",
+    "source/val/validate_mesh_shading.cpp",
     "source/val/validate_misc.cpp",
     "source/val/validate_mode_setting.cpp",
     "source/val/validate_non_uniform.cpp",
     "source/val/validate_primitives.cpp",
     "source/val/validate_ray_query.cpp",
+    "source/val/validate_ray_tracing.cpp",
     "source/val/validate_scopes.cpp",
     "source/val/validate_scopes.h",
     "source/val/validate_small_type_uses.cpp",
@@ -563,6 +571,8 @@
     "source/opt/aggressive_dead_code_elim_pass.h",
     "source/opt/amd_ext_to_khr.cpp",
     "source/opt/amd_ext_to_khr.h",
+    "source/opt/analyze_live_input_pass.cpp",
+    "source/opt/analyze_live_input_pass.h",
     "source/opt/basic_block.cpp",
     "source/opt/basic_block.h",
     "source/opt/block_merge_pass.cpp",
@@ -629,6 +639,8 @@
     "source/opt/eliminate_dead_input_components_pass.h",
     "source/opt/eliminate_dead_members_pass.cpp",
     "source/opt/eliminate_dead_members_pass.h",
+    "source/opt/eliminate_dead_output_stores_pass.cpp",
+    "source/opt/eliminate_dead_output_stores_pass.h",
     "source/opt/empty_pass.h",
     "source/opt/feature_manager.cpp",
     "source/opt/feature_manager.h",
@@ -682,6 +694,8 @@
     "source/opt/iterator.h",
     "source/opt/licm_pass.cpp",
     "source/opt/licm_pass.h",
+    "source/opt/liveness.cpp",
+    "source/opt/liveness.h",
     "source/opt/local_access_chain_convert_pass.cpp",
     "source/opt/local_access_chain_convert_pass.h",
     "source/opt/local_redundancy_elimination.cpp",
diff --git a/third_party/SPIRV-Tools/CHANGES b/third_party/SPIRV-Tools/CHANGES
index f5e91cb..384805c 100644
--- a/third_party/SPIRV-Tools/CHANGES
+++ b/third_party/SPIRV-Tools/CHANGES
@@ -1,18 +1,55 @@
 Revision history for SPIRV-Tools
 
-v2022.3-dev 2022-05-31
+v2022.5-dev 2022-10-12
+   - Start v2022.5-dev
+
+v2022.4 2022-10-12
+  - General
+    - Support Narrow Types in BitCast Folding Rule (#4941)
+    - spirv-diff: Allow no SpecId (#4904)
+    - build: cmake: Add support for GNU/Hurd (#4895)
+    - Implement tool changes for SPV_EXT_mesh_shader. (#4915)
+  - Validator
+    - spirv-val: Add SPV_ARM_core_builtins validation (#4958)
+    - spirv-val: Add an option to use friendly names or not (#4951)
+    - spirv-val: Consistently quote ids in messages (#4950)
+    - spirv-val: Add initial SPV_EXT_mesh_shader validation (#4924)
+    - spirv-val: Make it legal to use arrays of ray queries (#4938)
+    - spirv-val: Better message for using OpTypeBool in input/output (#4901)
+    - spirv-val: Add SPV_KHR_ray_tracing storage class (#4868)
+  - Optimizer
+    - spirv-opt: Fix stacked CompositeExtract constant folds (#4932)
+    - Improve time to build dominators (#4916)
+    - Fix ADCE to mark scope and inlined_at of line instructions as live. (#4910)
+    - Improve algorithm to reorder blocks in a function (#4911)
+    - Add structs to eliminate dead input components (#4894)
+    - spirv-opt: fix copy-propagate-arrays index opti on structs. (#4891)
+    - Fix ADCE to not eliminate top level DebugInfo instructions (#4889)
+    - Fix array copy propagation (#4890)
+
+v2022.3 2022-08-08
   - General
     - Add SPV_KHR_fragment_shader_barycentric support (#4805)
     - Add support for SPV_KHR_subgroup_rotate (#4786)
+    - use exec_tools instead of tools for better RBE compatibility (#4837)
+    - Write binary files to stdout in binary on windows. (#4834)
+    - Allow spirv-opt print-all to show pretty IDs (#4888)
+  - Validator
+    - spirv-val: Add PerVertexKHR (#4807)
+    - spirv-opt : Add FixFuncCallArgumentsPass (#4775)
+    - spirv-val: Add CullMaskKHR support (#4792)
+    - Require ColMajor or RowMajor for matrices (#4878)
+    - spirv-val: Add SPV_KHR_ray_query (#4848)
+    - spirv-val: Add SPV_KHR_ray_tracing instructions (#4871)
+    - Implement SPV_NV_bindless_texture related changes (#4847)
+    - spirv-val: Add OpConvertUToAccelerationStructureKHR (#4838)
+    - spirv-val: Add support for SPV_AMD_shader_early_and_late_fragment_tests (#4812)
   - Optimizer
     - Fold multiply and subtraction into FMA with negation (#4808)
     - Add more folding for composite instructions (#4802)
     - spirv-opt: add pass for interface variable scalar replacement (#4779)
     - Don't try to unroll loop with step count 0. (#4769)
-  - Validator
-    - spirv-val: Add PerVertexKHR (#4807)
-    - spirv-opt : Add FixFuncCallArgumentsPass (#4775)
-    - spirv-val: Add CullMaskKHR support (#4792)
+    - spirv-opt: SPV_NV_bindless_texture related changes (#4870)
   - Linker
     - linker: Recalculate interface variables (#4784)
 
diff --git a/third_party/SPIRV-Tools/CMakeLists.txt b/third_party/SPIRV-Tools/CMakeLists.txt
index 76b87d8..7815a29 100644
--- a/third_party/SPIRV-Tools/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/CMakeLists.txt
@@ -56,8 +56,12 @@
   set(SPIRV_TIMER_ENABLED ${SPIRV_ALLOW_TIMERS})
 elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
   add_definitions(-DSPIRV_FREEBSD)
+elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD")
+  add_definitions(-DSPIRV_OPENBSD)
 elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
   add_definitions(-DSPIRV_FUCHSIA)
+elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "GNU")
+  add_definitions(-DSPIRV_GNU)
 else()
   message(FATAL_ERROR "Your platform '${CMAKE_SYSTEM_NAME}' is not supported!")
 endif()
@@ -196,7 +200,7 @@
     if(NOT "${SPIRV_PERF}" STREQUAL "")
       target_compile_options(${TARGET} PRIVATE -fno-omit-frame-pointer)
     endif()
-    if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+    if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
       set(SPIRV_USE_SANITIZER "" CACHE STRING
         "Use the clang sanitizer [address|memory|thread|...]")
       if(NOT "${SPIRV_USE_SANITIZER}" STREQUAL "")
diff --git a/third_party/SPIRV-Tools/DEPS b/third_party/SPIRV-Tools/DEPS
index 78c9dd3..a134582 100644
--- a/third_party/SPIRV-Tools/DEPS
+++ b/third_party/SPIRV-Tools/DEPS
@@ -3,10 +3,10 @@
 vars = {
   'github': 'https://github.com',
 
-  'effcee_revision': 'ddf5e2bb92957dc8a12c5392f8495333d6844133',
-  'googletest_revision': '548b13dc3c02b93f60eeff9a0cc6e11c1ea722ca',
-  're2_revision': '5723bb8950318135ed9cf4fc76bed988a087f536',
-  'spirv_headers_revision': 'b2a156e1c0434bc8c99aaebba1c7be98be7ac580',
+  'effcee_revision': '35912e1b7778ec2ddcff7e7188177761539e59e0',
+  'googletest_revision': 'd9bb8412d60b993365abb53f00b6dad9b2c01b62',
+  're2_revision': 'd2836d1b1c34c4e330a85a1006201db474bf2c8a',
+  'spirv_headers_revision': '47f2465ee3e78ec5ec38f00b2c405d9475797228',
 }
 
 deps = {
diff --git a/third_party/SPIRV-Tools/PRESUBMIT.py b/third_party/SPIRV-Tools/PRESUBMIT.py
index dd3117f..847deb7 100644
--- a/third_party/SPIRV-Tools/PRESUBMIT.py
+++ b/third_party/SPIRV-Tools/PRESUBMIT.py
@@ -18,6 +18,8 @@
 for more details about the presubmit API built into depot_tools.
 """
 
+USE_PYTHON3 = True
+
 LINT_FILTERS = [
   "-build/storage_class",
   "-readability/casting",
diff --git a/third_party/SPIRV-Tools/build_defs.bzl b/third_party/SPIRV-Tools/build_defs.bzl
index 7189137..ed726ae 100644
--- a/third_party/SPIRV-Tools/build_defs.bzl
+++ b/third_party/SPIRV-Tools/build_defs.bzl
@@ -66,7 +66,8 @@
             "--extinst-debuginfo-grammar=$(location {1}) " +
             "--extinst-cldebuginfo100-grammar=$(location {2}) " +
             "--core-insts-output=$(location {3}) " +
-            "--operand-kinds-output=$(location {4})"
+            "--operand-kinds-output=$(location {4}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         cmd_bat = (
             "$(location :generate_grammar_tables) " +
@@ -74,7 +75,8 @@
             "--extinst-debuginfo-grammar=$(location {1}) " +
             "--extinst-cldebuginfo100-grammar=$(location {2}) " +
             "--core-insts-output=$(location {3}) " +
-            "--operand-kinds-output=$(location {4})"
+            "--operand-kinds-output=$(location {4}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
@@ -103,7 +105,8 @@
             "--extinst-debuginfo-grammar=$(location {1}) " +
             "--extinst-cldebuginfo100-grammar=$(location {2}) " +
             "--extension-enum-output=$(location {3}) " +
-            "--enum-string-mapping-output=$(location {4})"
+            "--enum-string-mapping-output=$(location {4}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         cmd_bat = (
             "$(location :generate_grammar_tables) " +
@@ -111,7 +114,8 @@
             "--extinst-debuginfo-grammar=$(location {1}) " +
             "--extinst-cldebuginfo100-grammar=$(location {2}) " +
             "--extension-enum-output=$(location {3}) " +
-            "--enum-string-mapping-output=$(location {4})"
+            "--enum-string-mapping-output=$(location {4}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
@@ -158,12 +162,14 @@
         cmd = (
             "$(location :generate_grammar_tables) " +
             "--extinst-glsl-grammar=$(location {0}) " +
-            "--glsl-insts-output=$(location {1})"
+            "--glsl-insts-output=$(location {1}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         cmd_bat = (
             "$(location :generate_grammar_tables) " +
             "--extinst-glsl-grammar=$(location {0}) " +
-            "--glsl-insts-output=$(location {1})"
+            "--glsl-insts-output=$(location {1}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
diff --git a/third_party/SPIRV-Tools/include/spirv-tools/instrument.hpp b/third_party/SPIRV-Tools/include/spirv-tools/instrument.hpp
index a19491f..a75561b 100644
--- a/third_party/SPIRV-Tools/include/spirv-tools/instrument.hpp
+++ b/third_party/SPIRV-Tools/include/spirv-tools/instrument.hpp
@@ -36,16 +36,25 @@
 // generated by InstrumentPass::GenDebugStreamWrite. This method is utilized
 // by InstBindlessCheckPass, InstBuffAddrCheckPass, and InstDebugPrintfPass.
 //
-// The first member of the debug output buffer contains the next available word
+// The 1st member of the debug output buffer contains a set of flags
+// controlling the behavior of instrumentation code.
+static const int kDebugOutputFlagsOffset = 0;
+
+// Values stored at kDebugOutputFlagsOffset
+enum kInstFlags : unsigned int {
+  kInstBufferOOBEnable = 0x1,
+};
+
+// The 2nd member of the debug output buffer contains the next available word
 // in the data stream to be written. Shaders will atomically read and update
 // this value so as not to overwrite each others records. This value must be
 // initialized to zero
-static const int kDebugOutputSizeOffset = 0;
+static const int kDebugOutputSizeOffset = 1;
 
-// The second member of the output buffer is the start of the stream of records
+// The 3rd member of the output buffer is the start of the stream of records
 // written by the instrumented shaders. Each record represents a validation
 // error. The format of the records is documented below.
-static const int kDebugOutputDataOffset = 1;
+static const int kDebugOutputDataOffset = 2;
 
 // Common Stream Record Offsets
 //
diff --git a/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h b/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h
index e1b8890..b549efb 100644
--- a/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h
+++ b/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h
@@ -670,6 +670,10 @@
 SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetAllowLocalSizeId(
     spv_validator_options options, bool val);
 
+// Whether friendly names should be used in validation error messages.
+SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetFriendlyNames(
+    spv_validator_options options, bool val);
+
 // Creates an optimizer options object with default options. Returns a valid
 // options object. The object remains valid until it is passed into
 // |spvOptimizerOptionsDestroy|.
diff --git a/third_party/SPIRV-Tools/include/spirv-tools/libspirv.hpp b/third_party/SPIRV-Tools/include/spirv-tools/libspirv.hpp
index 25eb8a1..408e3eb 100644
--- a/third_party/SPIRV-Tools/include/spirv-tools/libspirv.hpp
+++ b/third_party/SPIRV-Tools/include/spirv-tools/libspirv.hpp
@@ -148,6 +148,11 @@
     spvValidatorOptionsSetBeforeHlslLegalization(options_, val);
   }
 
+  // Whether friendly names should be used in validation error messages.
+  void SetFriendlyNames(bool val) {
+    spvValidatorOptionsSetFriendlyNames(options_, val);
+  }
+
  private:
   spv_validator_options options_;
 };
diff --git a/third_party/SPIRV-Tools/include/spirv-tools/optimizer.hpp b/third_party/SPIRV-Tools/include/spirv-tools/optimizer.hpp
index 9497356..41752d6 100644
--- a/third_party/SPIRV-Tools/include/spirv-tools/optimizer.hpp
+++ b/third_party/SPIRV-Tools/include/spirv-tools/optimizer.hpp
@@ -19,6 +19,7 @@
 #include <ostream>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -887,12 +888,59 @@
 Optimizer::PassToken CreateInterpolateFixupPass();
 
 // Removes unused components from composite input variables. Current
-// implementation just removes trailing unused components from input arrays.
-// The pass performs best after maximizing dead code removal. A subsequent dead
-// code elimination pass would be beneficial in removing newly unused component
-// types.
+// implementation just removes trailing unused components from input arrays
+// and structs. The pass performs best after maximizing dead code removal.
+// A subsequent dead code elimination pass would be beneficial in removing
+// newly unused component types.
+//
+// WARNING: This pass can only be safely applied standalone to vertex shaders
+// as it can otherwise cause interface incompatibilities with the preceding
+// shader in the pipeline. If applied to non-vertex shaders, the user should
+// follow by applying EliminateDeadOutputStores and
+// EliminateDeadOutputComponents to the preceding shader.
 Optimizer::PassToken CreateEliminateDeadInputComponentsPass();
 
+// Removes unused components from composite output variables. Current
+// implementation just removes trailing unused components from output arrays
+// and structs. The pass performs best after eliminating dead output stores.
+// A subsequent dead code elimination pass would be beneficial in removing
+// newly unused component types. Currently only supports vertex and fragment
+// shaders.
+//
+// WARNING: This pass cannot be safely applied standalone as it can cause
+// interface incompatibility with the following shader in the pipeline. The
+// user should first apply EliminateDeadInputComponents to the following
+// shader, then apply EliminateDeadOutputStores to this shader.
+Optimizer::PassToken CreateEliminateDeadOutputComponentsPass();
+
+// Removes unused components from composite input variables. This safe
+// version will not cause interface incompatibilities since it only changes
+// vertex shaders. The current implementation just removes trailing unused
+// components from input structs and input arrays. The pass performs best
+// after maximizing dead code removal. A subsequent dead code elimination
+// pass would be beneficial in removing newly unused component types.
+Optimizer::PassToken CreateEliminateDeadInputComponentsSafePass();
+
+// Analyzes shader and populates |live_locs| and |live_builtins|. Best results
+// will be obtained if shader has all dead code eliminated first. |live_locs|
+// and |live_builtins| are subsequently used when calling
+// CreateEliminateDeadOutputStoresPass on the preceding shader. Currently only
+// supports tesc, tese, geom, and frag shaders.
+Optimizer::PassToken CreateAnalyzeLiveInputPass(
+    std::unordered_set<uint32_t>* live_locs,
+    std::unordered_set<uint32_t>* live_builtins);
+
+// Removes stores to output locations not listed in |live_locs| or
+// |live_builtins|. Best results are obtained if constant propagation is
+// performed first. A subsequent call to ADCE will eliminate any dead code
+// created by the removal of the stores. A subsequent call to
+// CreateEliminateDeadOutputComponentsPass will eliminate any dead output
+// components created by the elimination of the stores. Currently only supports
+// vert, tesc, tese, and geom shaders.
+Optimizer::PassToken CreateEliminateDeadOutputStoresPass(
+    std::unordered_set<uint32_t>* live_locs,
+    std::unordered_set<uint32_t>* live_builtins);
+
 // Creates a convert-to-sampled-image pass to convert images and/or
 // samplers with given pairs of descriptor set and binding to sampled image.
 // If a pair of an image and a sampler have the same pair of descriptor set and
diff --git a/third_party/SPIRV-Tools/kokoro/scripts/macos/build.sh b/third_party/SPIRV-Tools/kokoro/scripts/macos/build.sh
index 4612823..3618e69 100644
--- a/third_party/SPIRV-Tools/kokoro/scripts/macos/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/scripts/macos/build.sh
@@ -43,11 +43,9 @@
 # Invoke the build.
 BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
 echo $(date): Starting build...
-# We need Python 3.  At the moment python3.7 is the newest Python on Kokoro.
 cmake \
   -GNinja \
   -DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install \
-  -DPYTHON_EXECUTABLE:FILEPATH=/usr/local/bin/python3.7 \
   -DCMAKE_C_COMPILER=clang \
   -DCMAKE_CXX_COMPILER=clang++ \
   -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
diff --git a/third_party/SPIRV-Tools/source/CMakeLists.txt b/third_party/SPIRV-Tools/source/CMakeLists.txt
index 1ceb78f..f904024 100644
--- a/third_party/SPIRV-Tools/source/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/CMakeLists.txt
@@ -37,6 +37,7 @@
       --extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE}
       --core-insts-output=${GRAMMAR_INSTS_INC_FILE}
       --operand-kinds-output=${GRAMMAR_KINDS_INC_FILE}
+      --output-language=c++
     DEPENDS ${GRAMMAR_PROCESSING_SCRIPT}
             ${GRAMMAR_JSON_FILE}
             ${DEBUGINFO_GRAMMAR_JSON_FILE}
@@ -58,6 +59,7 @@
       --extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE}
       --extension-enum-output=${GRAMMAR_EXTENSION_ENUM_INC_FILE}
       --enum-string-mapping-output=${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
+      --output-language=c++
     DEPENDS ${GRAMMAR_PROCESSING_SCRIPT}
             ${GRAMMAR_JSON_FILE}
             ${DEBUGINFO_GRAMMAR_JSON_FILE}
@@ -92,6 +94,7 @@
     COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
       --extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
       --glsl-insts-output=${GRAMMAR_INC_FILE}
+      --output-language=c++
     DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${GLSL_GRAMMAR_JSON_FILE}
     COMMENT "Generate info tables for GLSL extended instructions and operands v${CONFIG_VERSION}.")
   list(APPEND EXTINST_CPP_DEPENDS ${GRAMMAR_INC_FILE})
@@ -318,11 +321,13 @@
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_logicals.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_memory.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_memory_semantics.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_mesh_shading.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_misc.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_mode_setting.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_non_uniform.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_primitives.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_ray_query.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_ray_tracing.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_scopes.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_small_type_uses.cpp
   ${CMAKE_CURRENT_SOURCE_DIR}/val/validate_type.cpp
diff --git a/third_party/SPIRV-Tools/source/assembly_grammar.cpp b/third_party/SPIRV-Tools/source/assembly_grammar.cpp
index 4f5942a..6df823e 100644
--- a/third_party/SPIRV-Tools/source/assembly_grammar.cpp
+++ b/third_party/SPIRV-Tools/source/assembly_grammar.cpp
@@ -78,16 +78,16 @@
 
 // Associates an opcode with its name.
 struct SpecConstantOpcodeEntry {
-  SpvOp opcode;
+  spv::Op opcode;
   const char* name;
 };
 
 // All the opcodes allowed as the operation for OpSpecConstantOp.
-// The name does not have the usual "Op" prefix. For example opcode SpvOpIAdd
-// is associated with the name "IAdd".
+// The name does not have the usual "Op" prefix. For example opcode
+// spv::Op::IAdd is associated with the name "IAdd".
 //
 // clang-format off
-#define CASE(NAME) { SpvOp##NAME, #NAME }
+#define CASE(NAME) { spv::Op::Op##NAME, #NAME }
 const SpecConstantOpcodeEntry kOpSpecConstantOpcodes[] = {
     // Conversion
     CASE(SConvert),
@@ -173,7 +173,7 @@
 }
 
 CapabilitySet AssemblyGrammar::filterCapsAgainstTargetEnv(
-    const SpvCapability* cap_array, uint32_t count) const {
+    const spv::Capability* cap_array, uint32_t count) const {
   CapabilitySet cap_set;
   for (uint32_t i = 0; i < count; ++i) {
     spv_operand_desc cap_desc = {};
@@ -194,7 +194,7 @@
   return spvOpcodeTableNameLookup(target_env_, opcodeTable_, name, desc);
 }
 
-spv_result_t AssemblyGrammar::lookupOpcode(SpvOp opcode,
+spv_result_t AssemblyGrammar::lookupOpcode(spv::Op opcode,
                                            spv_opcode_desc* desc) const {
   return spvOpcodeTableValueLookup(target_env_, opcodeTable_, opcode, desc);
 }
@@ -214,7 +214,7 @@
 }
 
 spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(const char* name,
-                                                       SpvOp* opcode) const {
+                                                       spv::Op* opcode) const {
   const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
   const auto* found =
       std::find_if(kOpSpecConstantOpcodes, last,
@@ -226,7 +226,7 @@
   return SPV_SUCCESS;
 }
 
-spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(SpvOp opcode) const {
+spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(spv::Op opcode) const {
   const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
   const auto* found =
       std::find_if(kOpSpecConstantOpcodes, last,
diff --git a/third_party/SPIRV-Tools/source/assembly_grammar.h b/third_party/SPIRV-Tools/source/assembly_grammar.h
index 17c2bd3..36fdd08 100644
--- a/third_party/SPIRV-Tools/source/assembly_grammar.h
+++ b/third_party/SPIRV-Tools/source/assembly_grammar.h
@@ -41,7 +41,7 @@
 
   // Removes capabilities not available in the current target environment and
   // returns the rest.
-  CapabilitySet filterCapsAgainstTargetEnv(const SpvCapability* cap_array,
+  CapabilitySet filterCapsAgainstTargetEnv(const spv::Capability* cap_array,
                                            uint32_t count) const;
 
   // Fills in the desc parameter with the information about the opcode
@@ -52,7 +52,7 @@
   // Fills in the desc parameter with the information about the opcode
   // of the valid. Returns SPV_SUCCESS if the opcode was found, and
   // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
-  spv_result_t lookupOpcode(SpvOp opcode, spv_opcode_desc* desc) const;
+  spv_result_t lookupOpcode(spv::Op opcode, spv_opcode_desc* desc) const;
 
   // Fills in the desc parameter with the information about the given
   // operand. Returns SPV_SUCCESS if the operand was found, and
@@ -82,11 +82,12 @@
   // the integer add opcode for OpSpecConstantOp.  On success, returns
   // SPV_SUCCESS and sends the discovered operation code through the opcode
   // parameter.  On failure, returns SPV_ERROR_INVALID_LOOKUP.
-  spv_result_t lookupSpecConstantOpcode(const char* name, SpvOp* opcode) const;
+  spv_result_t lookupSpecConstantOpcode(const char* name,
+                                        spv::Op* opcode) const;
 
   // Returns SPV_SUCCESS if the given opcode is valid as the opcode operand
   // to OpSpecConstantOp.
-  spv_result_t lookupSpecConstantOpcode(SpvOp opcode) const;
+  spv_result_t lookupSpecConstantOpcode(spv::Op opcode) const;
 
   // Parses a mask expression string for the given operand type.
   //
diff --git a/third_party/SPIRV-Tools/source/binary.cpp b/third_party/SPIRV-Tools/source/binary.cpp
index 24d32f8..beb56be 100644
--- a/third_party/SPIRV-Tools/source/binary.cpp
+++ b/third_party/SPIRV-Tools/source/binary.cpp
@@ -156,7 +156,7 @@
   // Issues a diagnostic describing an exhaustion of input condition when
   // trying to decode an instruction operand, and returns
   // SPV_ERROR_INVALID_BINARY.
-  spv_result_t exhaustedInputDiagnostic(size_t inst_offset, SpvOp opcode,
+  spv_result_t exhaustedInputDiagnostic(size_t inst_offset, spv::Op opcode,
                                         spv_operand_type_t type) {
     return diagnostic() << "End of input reached while decoding Op"
                         << spvOpcodeString(opcode) << " starting at word "
@@ -318,7 +318,7 @@
                         << inst_word_count;
   }
   spv_opcode_desc opcode_desc;
-  if (grammar_.lookupOpcode(static_cast<SpvOp>(inst.opcode), &opcode_desc))
+  if (grammar_.lookupOpcode(static_cast<spv::Op>(inst.opcode), &opcode_desc))
     return diagnostic() << "Invalid opcode: " << inst.opcode;
 
   // Advance past the opcode word.  But remember the of the start
@@ -418,7 +418,7 @@
                                   std::vector<uint32_t>* words,
                                   std::vector<spv_parsed_operand_t>* operands,
                                   spv_operand_pattern_t* expected_operands) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+  const spv::Op opcode = static_cast<spv::Op>(inst->opcode);
   // We'll fill in this result as we go along.
   spv_parsed_operand_t parsed_operand;
   parsed_operand.offset = uint16_t(_.word_index - inst_offset);
@@ -473,7 +473,7 @@
       if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0";
       parsed_operand.type = SPV_OPERAND_TYPE_ID;
 
-      if (opcode == SpvOpExtInst && parsed_operand.offset == 3) {
+      if (opcode == spv::Op::OpExtInst && parsed_operand.offset == 3) {
         // The current word is the extended instruction set Id.
         // Set the extended instruction set type for the current instruction.
         auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word);
@@ -494,7 +494,7 @@
       break;
 
     case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
-      assert(SpvOpExtInst == opcode);
+      assert(spv::Op::OpExtInst == opcode);
       assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
       spv_ext_inst_desc ext_inst;
       if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst) ==
@@ -516,14 +516,14 @@
     } break;
 
     case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
-      assert(SpvOpSpecConstantOp == opcode);
-      if (word > static_cast<uint32_t>(SpvOp::SpvOpMax) ||
-          grammar_.lookupSpecConstantOpcode(SpvOp(word))) {
+      assert(spv::Op::OpSpecConstantOp == opcode);
+      if (word > static_cast<uint32_t>(spv::Op::Max) ||
+          grammar_.lookupSpecConstantOpcode(spv::Op(word))) {
         return diagnostic()
                << "Invalid " << spvOperandTypeStr(type) << ": " << word;
       }
       spv_opcode_desc opcode_entry = nullptr;
-      if (grammar_.lookupOpcode(SpvOp(word), &opcode_entry)) {
+      if (grammar_.lookupOpcode(spv::Op(word), &opcode_entry)) {
         return diagnostic(SPV_ERROR_INTERNAL)
                << "OpSpecConstant opcode table out of sync";
       }
@@ -549,7 +549,7 @@
     case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
     case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
       parsed_operand.type = SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
-      if (opcode == SpvOpSwitch) {
+      if (opcode == spv::Op::OpSwitch) {
         // The literal operands have the same type as the value
         // referenced by the selector Id.
         const uint32_t selector_id = peekAt(inst_offset + 1);
@@ -575,7 +575,8 @@
                               << " is not a scalar integer";
         }
       } else {
-        assert(opcode == SpvOpConstant || opcode == SpvOpSpecConstant);
+        assert(opcode == spv::Op::OpConstant ||
+               opcode == spv::Op::OpSpecConstant);
         // The literal number type is determined by the type Id for the
         // constant.
         assert(inst->type_id);
@@ -607,7 +608,7 @@
       parsed_operand.num_words = uint16_t(string_num_words);
       parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_STRING;
 
-      if (SpvOpExtInstImport == opcode) {
+      if (spv::Op::OpExtInstImport == opcode) {
         // Record the extended instruction type for the ID for this import.
         // There is only one string literal argument to OpExtInstImport,
         // so it's sufficient to guard this just on the opcode.
@@ -789,14 +790,14 @@
 
 void Parser::recordNumberType(size_t inst_offset,
                               const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+  const spv::Op opcode = static_cast<spv::Op>(inst->opcode);
   if (spvOpcodeGeneratesType(opcode)) {
     NumberType info = {SPV_NUMBER_NONE, 0};
-    if (SpvOpTypeInt == opcode) {
+    if (spv::Op::OpTypeInt == opcode) {
       const bool is_signed = peekAt(inst_offset + 3) != 0;
       info.type = is_signed ? SPV_NUMBER_SIGNED_INT : SPV_NUMBER_UNSIGNED_INT;
       info.bit_width = peekAt(inst_offset + 2);
-    } else if (SpvOpTypeFloat == opcode) {
+    } else if (spv::Op::OpTypeFloat == opcode) {
       info.type = SPV_NUMBER_FLOATING;
       info.bit_width = peekAt(inst_offset + 2);
     }
diff --git a/third_party/SPIRV-Tools/source/cfa.h b/third_party/SPIRV-Tools/source/cfa.h
index f55a7bd..9ae3e39 100644
--- a/third_party/SPIRV-Tools/source/cfa.h
+++ b/third_party/SPIRV-Tools/source/cfa.h
@@ -56,8 +56,33 @@
   ///
   /// This function performs a depth first traversal from the \p entry
   /// BasicBlock and calls the pre/postorder functions when it needs to process
+  /// the node in pre order, post order.
+  ///
+  /// @param[in] entry      The root BasicBlock of a CFG
+  /// @param[in] successor_func  A function which will return a pointer to the
+  ///                            successor nodes
+  /// @param[in] preorder   A function that will be called for every block in a
+  ///                       CFG following preorder traversal semantics
+  /// @param[in] postorder  A function that will be called for every block in a
+  ///                       CFG following postorder traversal semantics
+  /// @param[in] terminal   A function that will be called to determine if the
+  ///                       search should stop at the given node.
+  /// NOTE: The @p successor_func and predecessor_func each return a pointer to
+  /// a collection such that iterators to that collection remain valid for the
+  /// lifetime of the algorithm.
+  static void DepthFirstTraversal(const BB* entry,
+                                  get_blocks_func successor_func,
+                                  std::function<void(cbb_ptr)> preorder,
+                                  std::function<void(cbb_ptr)> postorder,
+                                  std::function<bool(cbb_ptr)> terminal);
+
+  /// @brief Depth first traversal starting from the \p entry BasicBlock
+  ///
+  /// This function performs a depth first traversal from the \p entry
+  /// BasicBlock and calls the pre/postorder functions when it needs to process
   /// the node in pre order, post order. It also calls the backedge function
-  /// when a back edge is encountered.
+  /// when a back edge is encountered. The backedge function can be empty.  The
+  /// runtime of the algorithm is improved if backedge is empty.
   ///
   /// @param[in] entry      The root BasicBlock of a CFG
   /// @param[in] successor_func  A function which will return a pointer to the
@@ -67,12 +92,11 @@
   /// @param[in] postorder  A function that will be called for every block in a
   ///                       CFG following postorder traversal semantics
   /// @param[in] backedge   A function that will be called when a backedge is
-  ///                       encountered during a traversal
+  ///                       encountered during a traversal.
   /// @param[in] terminal   A function that will be called to determine if the
   ///                       search should stop at the given node.
   /// NOTE: The @p successor_func and predecessor_func each return a pointer to
-  /// a
-  /// collection such that iterators to that collection remain valid for the
+  /// a collection such that iterators to that collection remain valid for the
   /// lifetime of the algorithm.
   static void DepthFirstTraversal(
       const BB* entry, get_blocks_func successor_func,
@@ -137,12 +161,27 @@
 }
 
 template <class BB>
+void CFA<BB>::DepthFirstTraversal(const BB* entry,
+                                  get_blocks_func successor_func,
+                                  std::function<void(cbb_ptr)> preorder,
+                                  std::function<void(cbb_ptr)> postorder,
+                                  std::function<bool(cbb_ptr)> terminal) {
+  DepthFirstTraversal(entry, successor_func, preorder, postorder,
+                      /* backedge = */ {}, terminal);
+}
+
+template <class BB>
 void CFA<BB>::DepthFirstTraversal(
     const BB* entry, get_blocks_func successor_func,
     std::function<void(cbb_ptr)> preorder,
     std::function<void(cbb_ptr)> postorder,
     std::function<void(cbb_ptr, cbb_ptr)> backedge,
     std::function<bool(cbb_ptr)> terminal) {
+  assert(successor_func && "The successor function cannot be empty.");
+  assert(preorder && "The preorder function cannot be empty.");
+  assert(postorder && "The postorder function cannot be empty.");
+  assert(terminal && "The terminal function cannot be empty.");
+
   std::unordered_set<uint32_t> processed;
 
   /// NOTE: work_list is the sequence of nodes from the root node to the node
@@ -162,7 +201,7 @@
     } else {
       BB* child = *top.iter;
       top.iter++;
-      if (FindInWorkList(work_list, child->id())) {
+      if (backedge && FindInWorkList(work_list, child->id())) {
         backedge(top.block, child);
       }
       if (processed.count(child->id()) == 0) {
@@ -236,10 +275,16 @@
 
   std::vector<std::pair<bb_ptr, bb_ptr>> out;
   for (auto idom : idoms) {
+    // At this point if there is no dominator for the node, just make it
+    // reflexive.
+    auto dominator = std::get<1>(idom).dominator;
+    if (dominator == undefined_dom) {
+      dominator = std::get<1>(idom).postorder_index;
+    }
     // NOTE: performing a const cast for convenient usage with
     // UpdateImmediateDominators
     out.push_back({const_cast<BB*>(std::get<0>(idom)),
-                   const_cast<BB*>(postorder[std::get<1>(idom).dominator])});
+                   const_cast<BB*>(postorder[dominator])});
   }
 
   // Sort by postorder index to generate a deterministic ordering of edges.
@@ -269,14 +314,12 @@
 
   auto mark_visited = [&visited](const BB* b) { visited.insert(b); };
   auto ignore_block = [](const BB*) {};
-  auto ignore_blocks = [](const BB*, const BB*) {};
   auto no_terminal_blocks = [](const BB*) { return false; };
 
   auto traverse_from_root = [&mark_visited, &succ_func, &ignore_block,
-                             &ignore_blocks,
                              &no_terminal_blocks](const BB* entry) {
     DepthFirstTraversal(entry, succ_func, mark_visited, ignore_block,
-                        ignore_blocks, no_terminal_blocks);
+                        no_terminal_blocks);
   };
 
   std::vector<BB*> result;
diff --git a/third_party/SPIRV-Tools/source/diff/diff.cpp b/third_party/SPIRV-Tools/source/diff/diff.cpp
index bca31b0..6daed32 100644
--- a/third_party/SPIRV-Tools/source/diff/diff.cpp
+++ b/third_party/SPIRV-Tools/source/diff/diff.cpp
@@ -44,8 +44,8 @@
 // different implementations produce identical results.
 using IdGroupMapByName = std::map<std::string, IdGroup>;
 using IdGroupMapByTypeId = std::map<uint32_t, IdGroup>;
-using IdGroupMapByOp = std::map<SpvOp, IdGroup>;
-using IdGroupMapByStorageClass = std::map<SpvStorageClass, IdGroup>;
+using IdGroupMapByOp = std::map<spv::Op, IdGroup>;
+using IdGroupMapByStorageClass = std::map<spv::StorageClass, IdGroup>;
 
 // A set of potential id mappings that haven't been resolved yet.  Any id in src
 // may map in any id in dst.  Note that ids are added in the same order as they
@@ -301,10 +301,10 @@
   // Get various properties from an id.  These Helper functions are passed to
   // `GroupIds` and `GroupIdsAndMatch` below (as the `get_group` argument).
   uint32_t GroupIdsHelperGetTypeId(const IdInstructions& id_to, uint32_t id);
-  SpvStorageClass GroupIdsHelperGetTypePointerStorageClass(
+  spv::StorageClass GroupIdsHelperGetTypePointerStorageClass(
       const IdInstructions& id_to, uint32_t id);
-  SpvOp GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
-                                           uint32_t id);
+  spv::Op GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
+                                             uint32_t id);
 
   // Given a list of ids, groups them based on some value.  The `get_group`
   // function extracts a piece of information corresponding to each id, and the
@@ -414,8 +414,8 @@
   // Helper functions to retrieve information pertaining to an id
   const opt::Instruction* GetInst(const IdInstructions& id_to, uint32_t id);
   uint32_t GetConstantUint(const IdInstructions& id_to, uint32_t constant_id);
-  SpvExecutionModel GetExecutionModel(const opt::Module* module,
-                                      uint32_t entry_point_id);
+  spv::ExecutionModel GetExecutionModel(const opt::Module* module,
+                                        uint32_t entry_point_id);
   bool HasName(const IdInstructions& id_to, uint32_t id);
   // Get the OpName associated with an id
   std::string GetName(const IdInstructions& id_to, uint32_t id, bool* has_name);
@@ -424,20 +424,21 @@
   // string, and this improves diff between SPIR-V from those tools and others.
   std::string GetSanitizedName(const IdInstructions& id_to, uint32_t id);
   uint32_t GetVarTypeId(const IdInstructions& id_to, uint32_t var_id,
-                        SpvStorageClass* storage_class);
+                        spv::StorageClass* storage_class);
   bool GetDecorationValue(const IdInstructions& id_to, uint32_t id,
-                          SpvDecoration decoration, uint32_t* decoration_value);
+                          spv::Decoration decoration,
+                          uint32_t* decoration_value);
   const opt::Instruction* GetForwardPointerInst(const IdInstructions& id_to,
                                                 uint32_t id);
   bool IsIntType(const IdInstructions& id_to, uint32_t type_id);
   bool IsFloatType(const IdInstructions& id_to, uint32_t type_id);
   bool IsConstantUint(const IdInstructions& id_to, uint32_t id);
   bool IsVariable(const IdInstructions& id_to, uint32_t pointer_id);
-  bool IsOp(const IdInstructions& id_to, uint32_t id, SpvOp opcode);
+  bool IsOp(const IdInstructions& id_to, uint32_t id, spv::Op opcode);
   bool IsPerVertexType(const IdInstructions& id_to, uint32_t type_id);
   bool IsPerVertexVariable(const IdInstructions& id_to, uint32_t type_id);
-  SpvStorageClass GetPerVertexStorageClass(const opt::Module* module,
-                                           uint32_t type_id);
+  spv::StorageClass GetPerVertexStorageClass(const opt::Module* module,
+                                             uint32_t type_id);
   spv_ext_inst_type_t GetExtInstType(const IdInstructions& id_to,
                                      uint32_t set_id);
   spv_number_kind_t GetNumberKind(const IdInstructions& id_to,
@@ -561,19 +562,19 @@
     uint32_t id_operand = 0;
 
     switch (inst.opcode()) {
-      case SpvOpName:
+      case spv::Op::OpName:
         info_map = &name_map_;
         break;
-      case SpvOpMemberName:
+      case spv::Op::OpMemberName:
         info_map = &name_map_;
         break;
-      case SpvOpDecorate:
+      case spv::Op::OpDecorate:
         info_map = &decoration_map_;
         break;
-      case SpvOpMemberDecorate:
+      case spv::Op::OpMemberDecorate:
         info_map = &decoration_map_;
         break;
-      case SpvOpTypeForwardPointer: {
+      case spv::Op::OpTypeForwardPointer: {
         uint32_t id = inst.GetSingleWordOperand(0);
         assert(id != 0);
 
@@ -731,10 +732,10 @@
   // Instead of comparing OpExecutionMode entry point ids as ids, compare them
   // through their corresponding execution model.  This simplifies traversing
   // the sorted list of instructions between src and dst modules.
-  if (a->opcode() == SpvOpExecutionMode) {
-    const SpvExecutionModel src_model =
+  if (a->opcode() == spv::Op::OpExecutionMode) {
+    const spv::ExecutionModel src_model =
         GetExecutionModel(src_inst_module, a->GetSingleWordOperand(0));
-    const SpvExecutionModel dst_model =
+    const spv::ExecutionModel dst_model =
         GetExecutionModel(dst_inst_module, b->GetSingleWordOperand(0));
 
     if (src_model < dst_model) {
@@ -758,9 +759,6 @@
       return 1;
     }
 
-    assert(a_operand.words.size() == 1);
-    assert(b_operand.words.size() == 1);
-
     switch (a_operand.type) {
       case SPV_OPERAND_TYPE_ID:
         // Don't compare ids, there can't be multiple instances of the
@@ -781,6 +779,9 @@
       }
       default:
         // Expect literal values to match.
+        assert(a_operand.words.size() == 1);
+        assert(b_operand.words.size() == 1);
+
         if (a_operand.words[0] < b_operand.words[0]) {
           return -1;
         }
@@ -818,17 +819,17 @@
   return GetInst(id_to, id)->type_id();
 }
 
-SpvStorageClass Differ::GroupIdsHelperGetTypePointerStorageClass(
+spv::StorageClass Differ::GroupIdsHelperGetTypePointerStorageClass(
     const IdInstructions& id_to, uint32_t id) {
   const opt::Instruction* inst = GetInst(id_to, id);
-  assert(inst && inst->opcode() == SpvOpTypePointer);
-  return SpvStorageClass(inst->GetSingleWordInOperand(0));
+  assert(inst && inst->opcode() == spv::Op::OpTypePointer);
+  return spv::StorageClass(inst->GetSingleWordInOperand(0));
 }
 
-SpvOp Differ::GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
-                                                 uint32_t id) {
+spv::Op Differ::GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
+                                                   uint32_t id) {
   const opt::Instruction* inst = GetInst(id_to, id);
-  assert(inst && inst->opcode() == SpvOpTypePointer);
+  assert(inst && inst->opcode() == spv::Op::OpTypePointer);
 
   const uint32_t type_id = inst->GetSingleWordInOperand(1);
   const opt::Instruction* type_inst = GetInst(id_to, type_id);
@@ -1020,7 +1021,7 @@
   }
   // For external instructions, make sure the set and opcode of the external
   // instruction matches too.
-  if (src_inst->opcode() == SpvOpExtInst) {
+  if (src_inst->opcode() == spv::Op::OpExtInst) {
     if (!DoOperandsMatch(src_inst, dst_inst, 0, 2)) {
       return false;
     }
@@ -1064,26 +1065,26 @@
   }
 
   switch (src_inst->opcode()) {
-    case SpvOpString:
-    case SpvOpSourceExtension:
-    case SpvOpModuleProcessed:
+    case spv::Op::OpString:
+    case spv::Op::OpSourceExtension:
+    case spv::Op::OpModuleProcessed:
       return DoesOperandMatch(src_inst->GetOperand(0), dst_inst->GetOperand(0));
-    case SpvOpSource:
+    case spv::Op::OpSource:
       return DoOperandsMatch(src_inst, dst_inst, 0, 2);
-    case SpvOpSourceContinued:
+    case spv::Op::OpSourceContinued:
       return true;
-    case SpvOpName:
+    case spv::Op::OpName:
       return DoOperandsMatch(src_inst, dst_inst, 0, 1);
-    case SpvOpMemberName:
+    case spv::Op::OpMemberName:
       return DoOperandsMatch(src_inst, dst_inst, 0, 2);
-    case SpvOpDecorate:
+    case spv::Op::OpDecorate:
       return DoOperandsMatch(src_inst, dst_inst, 0, 2);
-    case SpvOpMemberDecorate:
+    case spv::Op::OpMemberDecorate:
       return DoOperandsMatch(src_inst, dst_inst, 0, 3);
-    case SpvOpExtInst:
-    case SpvOpDecorationGroup:
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate:
+    case spv::Op::OpExtInst:
+    case spv::Op::OpDecorationGroup:
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate:
       return false;
     default:
       return false;
@@ -1095,9 +1096,9 @@
   // Variables must match by their built-in decorations.
   uint32_t src_built_in_decoration = 0, dst_built_in_decoration = 0;
   const bool src_is_built_in = GetDecorationValue(
-      src_id_to_, src_id, SpvDecorationBuiltIn, &src_built_in_decoration);
+      src_id_to_, src_id, spv::Decoration::BuiltIn, &src_built_in_decoration);
   const bool dst_is_built_in = GetDecorationValue(
-      dst_id_to_, dst_id, SpvDecorationBuiltIn, &dst_built_in_decoration);
+      dst_id_to_, dst_id, spv::Decoration::BuiltIn, &dst_built_in_decoration);
 
   if (src_is_built_in != dst_is_built_in) {
     return false;
@@ -1107,7 +1108,7 @@
   }
 
   // Check their types and storage classes.
-  SpvStorageClass src_storage_class, dst_storage_class;
+  spv::StorageClass src_storage_class, dst_storage_class;
   const uint32_t src_type_id =
       GetVarTypeId(src_id_to_, src_id, &src_storage_class);
   const uint32_t dst_type_id =
@@ -1127,12 +1128,14 @@
         // Allow one of the two to be Private while the other is Input or
         // Output, this allows matching in/out variables that have been turned
         // global as part of linking two stages (as done in ANGLE).
-        const bool src_is_io = src_storage_class == SpvStorageClassInput ||
-                               src_storage_class == SpvStorageClassOutput;
-        const bool dst_is_io = dst_storage_class == SpvStorageClassInput ||
-                               dst_storage_class == SpvStorageClassOutput;
-        const bool src_is_private = src_storage_class == SpvStorageClassPrivate;
-        const bool dst_is_private = dst_storage_class == SpvStorageClassPrivate;
+        const bool src_is_io = src_storage_class == spv::StorageClass::Input ||
+                               src_storage_class == spv::StorageClass::Output;
+        const bool dst_is_io = dst_storage_class == spv::StorageClass::Input ||
+                               dst_storage_class == spv::StorageClass::Output;
+        const bool src_is_private =
+            src_storage_class == spv::StorageClass::Private;
+        const bool dst_is_private =
+            dst_storage_class == spv::StorageClass::Private;
 
         if (!((src_is_io && dst_is_private) || (src_is_private && dst_is_io))) {
           return false;
@@ -1277,15 +1280,22 @@
   // Otherwise, match them by SpecId.
   uint32_t src_spec_id, dst_spec_id;
 
-  if (GetDecorationValue(src_id_to_, src_id, SpvDecorationSpecId,
+  if (GetDecorationValue(src_id_to_, src_id, spv::Decoration::SpecId,
                          &src_spec_id) &&
-      GetDecorationValue(dst_id_to_, dst_id, SpvDecorationSpecId,
+      GetDecorationValue(dst_id_to_, dst_id, spv::Decoration::SpecId,
                          &dst_spec_id)) {
     return src_spec_id == dst_spec_id;
   }
 
-  // There is no spec id, this is not valid.
-  assert(false && "Unreachable");
+  // There is no SpecId decoration, while not practical, still valid.
+  // SpecConstantOp don't have SpecId and can be matched by operands
+  if (src_inst->opcode() == spv::Op::OpSpecConstantOp) {
+    if (src_inst->NumInOperandWords() == dst_inst->NumInOperandWords()) {
+      return DoOperandsMatch(src_inst, dst_inst, 0,
+                             src_inst->NumInOperandWords());
+    }
+  }
+
   return false;
 }
 
@@ -1320,13 +1330,13 @@
   // built-in decorations.
   uint32_t src_built_in_decoration;
   const bool src_is_built_in = GetDecorationValue(
-      src_id_to_, src_id, SpvDecorationBuiltIn, &src_built_in_decoration);
+      src_id_to_, src_id, spv::Decoration::BuiltIn, &src_built_in_decoration);
 
   if (src_is_built_in && AreVariablesMatchable(src_id, dst_id, flexibility)) {
     return true;
   }
 
-  SpvStorageClass src_storage_class, dst_storage_class;
+  spv::StorageClass src_storage_class, dst_storage_class;
   GetVarTypeId(src_id_to_, src_id, &src_storage_class);
   GetVarTypeId(dst_id_to_, dst_id, &dst_storage_class);
 
@@ -1341,13 +1351,13 @@
     uint32_t src_binding = 0, dst_binding = 0;
 
     const bool src_has_set = GetDecorationValue(
-        src_id_to_, src_id, SpvDecorationDescriptorSet, &src_set);
+        src_id_to_, src_id, spv::Decoration::DescriptorSet, &src_set);
     const bool dst_has_set = GetDecorationValue(
-        dst_id_to_, dst_id, SpvDecorationDescriptorSet, &dst_set);
-    const bool src_has_binding =
-        GetDecorationValue(src_id_to_, src_id, SpvDecorationBinding, &src_set);
-    const bool dst_has_binding =
-        GetDecorationValue(dst_id_to_, dst_id, SpvDecorationBinding, &dst_set);
+        dst_id_to_, dst_id, spv::Decoration::DescriptorSet, &dst_set);
+    const bool src_has_binding = GetDecorationValue(
+        src_id_to_, src_id, spv::Decoration::Binding, &src_set);
+    const bool dst_has_binding = GetDecorationValue(
+        dst_id_to_, dst_id, spv::Decoration::Binding, &dst_set);
 
     if (src_has_set && dst_has_set && src_has_binding && dst_has_binding) {
       return src_set == dst_set && src_binding == dst_binding;
@@ -1360,9 +1370,9 @@
     uint32_t src_location, dst_location;
 
     const bool src_has_location = GetDecorationValue(
-        src_id_to_, src_id, SpvDecorationLocation, &src_location);
+        src_id_to_, src_id, spv::Decoration::Location, &src_location);
     const bool dst_has_location = GetDecorationValue(
-        dst_id_to_, dst_id, SpvDecorationLocation, &dst_location);
+        dst_id_to_, dst_id, spv::Decoration::Location, &dst_location);
 
     if (src_has_location && dst_has_location) {
       return src_location == dst_location;
@@ -1377,25 +1387,25 @@
   // For gl_PerVertex, find the type pointer of this type (array) and make sure
   // the storage classes of src and dst match; geometry and tessellation shaders
   // have two instances of gl_PerVertex.
-  SpvStorageClass src_storage_class =
+  spv::StorageClass src_storage_class =
       GetPerVertexStorageClass(src_, src_type_id);
-  SpvStorageClass dst_storage_class =
+  spv::StorageClass dst_storage_class =
       GetPerVertexStorageClass(dst_, dst_type_id);
 
-  assert(src_storage_class == SpvStorageClassInput ||
-         src_storage_class == SpvStorageClassOutput);
-  assert(dst_storage_class == SpvStorageClassInput ||
-         dst_storage_class == SpvStorageClassOutput);
+  assert(src_storage_class == spv::StorageClass::Input ||
+         src_storage_class == spv::StorageClass::Output);
+  assert(dst_storage_class == spv::StorageClass::Input ||
+         dst_storage_class == spv::StorageClass::Output);
 
   return src_storage_class == dst_storage_class;
 }
 
 bool Differ::MatchPerVertexVariable(const opt::Instruction* src_inst,
                                     const opt::Instruction* dst_inst) {
-  SpvStorageClass src_storage_class =
-      SpvStorageClass(src_inst->GetSingleWordInOperand(0));
-  SpvStorageClass dst_storage_class =
-      SpvStorageClass(dst_inst->GetSingleWordInOperand(0));
+  spv::StorageClass src_storage_class =
+      spv::StorageClass(src_inst->GetSingleWordInOperand(0));
+  spv::StorageClass dst_storage_class =
+      spv::StorageClass(dst_inst->GetSingleWordInOperand(0));
 
   return src_storage_class == dst_storage_class;
 }
@@ -1472,7 +1482,7 @@
   InstructionList body;
   function.WhileEachInst(
       [&body](const opt::Instruction* inst) {
-        if (inst->opcode() == SpvOpLabel) {
+        if (inst->opcode() == spv::Op::OpLabel) {
           return false;
         }
         body.push_back(inst);
@@ -1687,12 +1697,12 @@
     default:
       // TODO: match functions based on OpFunctionCall?
       break;
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
-    case SpvOpLoad:
-    case SpvOpStore:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
       const uint32_t src_pointer_id = src_inst->GetSingleWordInOperand(0);
       const uint32_t dst_pointer_id = dst_inst->GetSingleWordInOperand(0);
       if (IsVariable(src_id_to_, src_pointer_id) &&
@@ -1720,23 +1730,24 @@
 uint32_t Differ::GetConstantUint(const IdInstructions& id_to,
                                  uint32_t constant_id) {
   const opt::Instruction* constant_inst = GetInst(id_to, constant_id);
-  assert(constant_inst->opcode() == SpvOpConstant);
-  assert(GetInst(id_to, constant_inst->type_id())->opcode() == SpvOpTypeInt);
+  assert(constant_inst->opcode() == spv::Op::OpConstant);
+  assert(GetInst(id_to, constant_inst->type_id())->opcode() ==
+         spv::Op::OpTypeInt);
 
   return constant_inst->GetSingleWordInOperand(0);
 }
 
-SpvExecutionModel Differ::GetExecutionModel(const opt::Module* module,
-                                            uint32_t entry_point_id) {
+spv::ExecutionModel Differ::GetExecutionModel(const opt::Module* module,
+                                              uint32_t entry_point_id) {
   for (const opt::Instruction& inst : module->entry_points()) {
-    assert(inst.opcode() == SpvOpEntryPoint);
+    assert(inst.opcode() == spv::Op::OpEntryPoint);
     if (inst.GetSingleWordOperand(1) == entry_point_id) {
-      return SpvExecutionModel(inst.GetSingleWordOperand(0));
+      return spv::ExecutionModel(inst.GetSingleWordOperand(0));
     }
   }
 
   assert(false && "Unreachable");
-  return SpvExecutionModel(0xFFF);
+  return spv::ExecutionModel(0xFFF);
 }
 
 bool Differ::HasName(const IdInstructions& id_to, uint32_t id) {
@@ -1744,7 +1755,7 @@
   assert(id < id_to.name_map_.size());
 
   for (const opt::Instruction* inst : id_to.name_map_[id]) {
-    if (inst->opcode() == SpvOpName) {
+    if (inst->opcode() == spv::Op::OpName) {
       return true;
     }
   }
@@ -1758,7 +1769,7 @@
   assert(id < id_to.name_map_.size());
 
   for (const opt::Instruction* inst : id_to.name_map_[id]) {
-    if (inst->opcode() == SpvOpName) {
+    if (inst->opcode() == spv::Op::OpName) {
       *has_name = true;
       return inst->GetOperand(1).AsString();
     }
@@ -1781,11 +1792,11 @@
 }
 
 uint32_t Differ::GetVarTypeId(const IdInstructions& id_to, uint32_t var_id,
-                              SpvStorageClass* storage_class) {
+                              spv::StorageClass* storage_class) {
   const opt::Instruction* var_inst = GetInst(id_to, var_id);
-  assert(var_inst->opcode() == SpvOpVariable);
+  assert(var_inst->opcode() == spv::Op::OpVariable);
 
-  *storage_class = SpvStorageClass(var_inst->GetSingleWordInOperand(0));
+  *storage_class = spv::StorageClass(var_inst->GetSingleWordInOperand(0));
 
   // Get the type pointer from the variable.
   const uint32_t type_pointer_id = var_inst->type_id();
@@ -1796,15 +1807,15 @@
 }
 
 bool Differ::GetDecorationValue(const IdInstructions& id_to, uint32_t id,
-                                SpvDecoration decoration,
+                                spv::Decoration decoration,
                                 uint32_t* decoration_value) {
   assert(id != 0);
   assert(id < id_to.decoration_map_.size());
 
   for (const opt::Instruction* inst : id_to.decoration_map_[id]) {
-    if (inst->opcode() == SpvOpDecorate &&
+    if (inst->opcode() == spv::Op::OpDecorate &&
         inst->GetSingleWordOperand(0) == id &&
-        inst->GetSingleWordOperand(1) == decoration) {
+        spv::Decoration(inst->GetSingleWordOperand(1)) == decoration) {
       *decoration_value = inst->GetSingleWordOperand(2);
       return true;
     }
@@ -1821,28 +1832,28 @@
 }
 
 bool Differ::IsIntType(const IdInstructions& id_to, uint32_t type_id) {
-  return IsOp(id_to, type_id, SpvOpTypeInt);
+  return IsOp(id_to, type_id, spv::Op::OpTypeInt);
 }
 
 bool Differ::IsFloatType(const IdInstructions& id_to, uint32_t type_id) {
-  return IsOp(id_to, type_id, SpvOpTypeFloat);
+  return IsOp(id_to, type_id, spv::Op::OpTypeFloat);
 }
 
 bool Differ::IsConstantUint(const IdInstructions& id_to, uint32_t id) {
   const opt::Instruction* constant_inst = GetInst(id_to, id);
-  if (constant_inst->opcode() != SpvOpConstant) {
+  if (constant_inst->opcode() != spv::Op::OpConstant) {
     return false;
   }
 
   const opt::Instruction* type_inst = GetInst(id_to, constant_inst->type_id());
-  return type_inst->opcode() == SpvOpTypeInt;
+  return type_inst->opcode() == spv::Op::OpTypeInt;
 }
 
 bool Differ::IsVariable(const IdInstructions& id_to, uint32_t pointer_id) {
-  return IsOp(id_to, pointer_id, SpvOpVariable);
+  return IsOp(id_to, pointer_id, spv::Op::OpVariable);
 }
 
-bool Differ::IsOp(const IdInstructions& id_to, uint32_t id, SpvOp op) {
+bool Differ::IsOp(const IdInstructions& id_to, uint32_t id, spv::Op op) {
   return GetInst(id_to, id)->opcode() == op;
 }
 
@@ -1851,17 +1862,18 @@
   assert(type_id < id_to.decoration_map_.size());
 
   for (const opt::Instruction* inst : id_to.decoration_map_[type_id]) {
-    if (inst->opcode() == SpvOpMemberDecorate &&
+    if (inst->opcode() == spv::Op::OpMemberDecorate &&
         inst->GetSingleWordOperand(0) == type_id &&
-        inst->GetSingleWordOperand(2) == SpvDecorationBuiltIn) {
-      SpvBuiltIn built_in = SpvBuiltIn(inst->GetSingleWordOperand(3));
+        spv::Decoration(inst->GetSingleWordOperand(2)) ==
+            spv::Decoration::BuiltIn) {
+      spv::BuiltIn built_in = spv::BuiltIn(inst->GetSingleWordOperand(3));
 
       // Only gl_PerVertex can have, and it can only have, the following
       // built-in decorations.
-      return built_in == SpvBuiltInPosition ||
-             built_in == SpvBuiltInPointSize ||
-             built_in == SpvBuiltInClipDistance ||
-             built_in == SpvBuiltInCullDistance;
+      return built_in == spv::BuiltIn::Position ||
+             built_in == spv::BuiltIn::PointSize ||
+             built_in == spv::BuiltIn::ClipDistance ||
+             built_in == spv::BuiltIn::CullDistance;
     }
   }
 
@@ -1870,12 +1882,12 @@
 
 bool Differ::IsPerVertexVariable(const IdInstructions& id_to, uint32_t var_id) {
   // Get the type from the type pointer.
-  SpvStorageClass storage_class;
+  spv::StorageClass storage_class;
   uint32_t type_id = GetVarTypeId(id_to, var_id, &storage_class);
   const opt::Instruction* type_inst = GetInst(id_to, type_id);
 
   // If array, get the element type.
-  if (type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeArray) {
     type_id = type_inst->GetSingleWordInOperand(0);
   }
 
@@ -1883,21 +1895,21 @@
   return IsPerVertexType(id_to, type_id);
 }
 
-SpvStorageClass Differ::GetPerVertexStorageClass(const opt::Module* module,
-                                                 uint32_t type_id) {
+spv::StorageClass Differ::GetPerVertexStorageClass(const opt::Module* module,
+                                                   uint32_t type_id) {
   for (const opt::Instruction& inst : module->types_values()) {
     switch (inst.opcode()) {
-      case SpvOpTypeArray:
+      case spv::Op::OpTypeArray:
         // The gl_PerVertex instance could be an array, look for a variable of
         // the array type instead.
         if (inst.GetSingleWordInOperand(0) == type_id) {
           type_id = inst.result_id();
         }
         break;
-      case SpvOpTypePointer:
+      case spv::Op::OpTypePointer:
         // Find the storage class of the pointer to this type.
         if (inst.GetSingleWordInOperand(1) == type_id) {
-          return SpvStorageClass(inst.GetSingleWordInOperand(0));
+          return spv::StorageClass(inst.GetSingleWordInOperand(0));
         }
         break;
       default:
@@ -1908,7 +1920,7 @@
   // gl_PerVertex is declared, but is unused.  Return either of Input or Output
   // classes just so it matches one in the other module.  This should be highly
   // unlikely, perhaps except for ancient GS-used-to-emulate-CS scenarios.
-  return SpvStorageClassOutput;
+  return spv::StorageClass::Output;
 }
 
 spv_ext_inst_type_t Differ::GetExtInstType(const IdInstructions& id_to,
@@ -1934,9 +1946,9 @@
     case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
     case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
       switch (inst.opcode()) {
-        case SpvOpSwitch:
-        case SpvOpConstant:
-        case SpvOpSpecConstant:
+        case spv::Op::OpSwitch:
+        case spv::Op::OpConstant:
+        case spv::Op::OpSpecConstant:
           // Same kind of number as the selector (OpSwitch) or the type
           // (Op*Constant).
           return GetTypeNumberKind(id_to, inst.GetSingleWordOperand(0),
@@ -1962,12 +1974,12 @@
   }
 
   switch (type_inst->opcode()) {
-    case SpvOpTypeInt:
+    case spv::Op::OpTypeInt:
       *number_bit_width = type_inst->GetSingleWordOperand(1);
       return type_inst->GetSingleWordOperand(2) == 0 ? SPV_NUMBER_UNSIGNED_INT
                                                      : SPV_NUMBER_SIGNED_INT;
       break;
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeFloat:
       *number_bit_width = type_inst->GetSingleWordOperand(1);
       return SPV_NUMBER_FLOATING;
     default:
@@ -2085,7 +2097,7 @@
     return inst.GetSingleWordOperand(0);
   };
   auto accept_type_forward_pointer_ops = [](const opt::Instruction& inst) {
-    return inst.opcode() == SpvOpTypeForwardPointer;
+    return inst.opcode() == spv::Op::OpTypeForwardPointer;
   };
 
   PoolPotentialIds(src_->types_values(), potential_id_map.src_ids, true,
@@ -2109,17 +2121,17 @@
   //     - If leftover is unique, match
 
   // Group forwarded pointers by storage class first and loop over them.
-  GroupIdsAndMatch<SpvStorageClass>(
-      potential_id_map.src_ids, potential_id_map.dst_ids, SpvStorageClassMax,
-      &Differ::GroupIdsHelperGetTypePointerStorageClass,
+  GroupIdsAndMatch<spv::StorageClass>(
+      potential_id_map.src_ids, potential_id_map.dst_ids,
+      spv::StorageClass::Max, &Differ::GroupIdsHelperGetTypePointerStorageClass,
       [this](const IdGroup& src_group_by_storage_class,
              const IdGroup& dst_group_by_storage_class) {
 
         // Group them further by the type they are pointing to and loop over
         // them.
-        GroupIdsAndMatch<SpvOp>(
-            src_group_by_storage_class, dst_group_by_storage_class, SpvOpMax,
-            &Differ::GroupIdsHelperGetTypePointerTypeOp,
+        GroupIdsAndMatch<spv::Op>(
+            src_group_by_storage_class, dst_group_by_storage_class,
+            spv::Op::Max, &Differ::GroupIdsHelperGetTypePointerTypeOp,
             [this](const IdGroup& src_group_by_type_op,
                    const IdGroup& dst_group_by_type_op) {
 
@@ -2175,8 +2187,8 @@
     MatchIds(potential_id_map, [this, flexibility](
                                    const opt::Instruction* src_inst,
                                    const opt::Instruction* dst_inst) {
-      const SpvOp src_op = src_inst->opcode();
-      const SpvOp dst_op = dst_inst->opcode();
+      const spv::Op src_op = src_inst->opcode();
+      const spv::Op dst_op = dst_inst->opcode();
 
       // Don't match if the opcode is not the same.
       if (src_op != dst_op) {
@@ -2184,26 +2196,26 @@
       }
 
       switch (src_op) {
-        case SpvOpTypeVoid:
-        case SpvOpTypeBool:
-        case SpvOpTypeSampler:
+        case spv::Op::OpTypeVoid:
+        case spv::Op::OpTypeBool:
+        case spv::Op::OpTypeSampler:
           // void, bool and sampler are unique, match them.
           return true;
-        case SpvOpTypeInt:
-        case SpvOpTypeFloat:
-        case SpvOpTypeVector:
-        case SpvOpTypeMatrix:
-        case SpvOpTypeSampledImage:
-        case SpvOpTypeRuntimeArray:
-        case SpvOpTypePointer:
+        case spv::Op::OpTypeInt:
+        case spv::Op::OpTypeFloat:
+        case spv::Op::OpTypeVector:
+        case spv::Op::OpTypeMatrix:
+        case spv::Op::OpTypeSampledImage:
+        case spv::Op::OpTypeRuntimeArray:
+        case spv::Op::OpTypePointer:
           // Match these instructions when all operands match.
           assert(src_inst->NumInOperandWords() ==
                  dst_inst->NumInOperandWords());
           return DoOperandsMatch(src_inst, dst_inst, 0,
                                  src_inst->NumInOperandWords());
 
-        case SpvOpTypeFunction:
-        case SpvOpTypeImage:
+        case spv::Op::OpTypeFunction:
+        case spv::Op::OpTypeImage:
           // Match function types only if they have the same number of operands,
           // and they all match.
           // Match image types similarly, expecting the optional final parameter
@@ -2214,7 +2226,7 @@
           return DoOperandsMatch(src_inst, dst_inst, 0,
                                  src_inst->NumInOperandWords());
 
-        case SpvOpTypeArray:
+        case spv::Op::OpTypeArray:
           // Match arrays only if the element type and length match.  The length
           // is an id of a constant, so the actual constant it's defining is
           // compared instead.
@@ -2231,7 +2243,7 @@
           // example if a spec contant is used).
           return DoOperandsMatch(src_inst, dst_inst, 1, 1);
 
-        case SpvOpTypeStruct:
+        case spv::Op::OpTypeStruct:
           return MatchOpTypeStruct(src_inst, dst_inst, flexibility);
 
         default:
@@ -2263,8 +2275,8 @@
     MatchIds(potential_id_map, [this, flexibility](
                                    const opt::Instruction* src_inst,
                                    const opt::Instruction* dst_inst) {
-      const SpvOp src_op = src_inst->opcode();
-      const SpvOp dst_op = dst_inst->opcode();
+      const spv::Op src_op = src_inst->opcode();
+      const spv::Op dst_op = dst_inst->opcode();
 
       // Don't match if the opcode is not the same.
       if (src_op != dst_op) {
@@ -2272,14 +2284,14 @@
       }
 
       switch (src_op) {
-        case SpvOpConstantTrue:
-        case SpvOpConstantFalse:
+        case spv::Op::OpConstantTrue:
+        case spv::Op::OpConstantFalse:
           // true and false are unique, match them.
           return true;
-        case SpvOpConstant:
+        case spv::Op::OpConstant:
           return MatchOpConstant(src_inst, dst_inst, flexibility);
-        case SpvOpConstantComposite:
-        case SpvOpSpecConstantComposite:
+        case spv::Op::OpConstantComposite:
+        case spv::Op::OpSpecConstantComposite:
           // Composite constants must match in type and value.
           //
           // TODO: match OpConstantNull with OpConstantComposite with all zeros
@@ -2292,7 +2304,7 @@
                                   dst_inst->GetOperand(0)) &&
                  DoOperandsMatch(src_inst, dst_inst, 0,
                                  src_inst->NumInOperandWords());
-        case SpvOpConstantSampler:
+        case spv::Op::OpConstantSampler:
           // Match sampler constants exactly.
           // TODO: Allow flexibility in parameters to better diff shaders where
           // the sampler param has changed.
@@ -2300,15 +2312,15 @@
                  dst_inst->NumInOperandWords());
           return DoOperandsMatch(src_inst, dst_inst, 0,
                                  src_inst->NumInOperandWords());
-        case SpvOpConstantNull:
+        case spv::Op::OpConstantNull:
           // Match null constants as long as the type matches.
           return DoesOperandMatch(src_inst->GetOperand(0),
                                   dst_inst->GetOperand(0));
 
-        case SpvOpSpecConstantTrue:
-        case SpvOpSpecConstantFalse:
-        case SpvOpSpecConstant:
-        case SpvOpSpecConstantOp:
+        case spv::Op::OpSpecConstantTrue:
+        case spv::Op::OpSpecConstantFalse:
+        case spv::Op::OpSpecConstant:
+        case spv::Op::OpSpecConstantOp:
           // Match spec constants by name if available, then by the SpecId
           // decoration.
           return MatchOpSpecConstant(src_inst, dst_inst);
@@ -2327,7 +2339,7 @@
     return inst.result_id();
   };
   auto accept_type_ops = [](const opt::Instruction& inst) {
-    return inst.opcode() == SpvOpVariable;
+    return inst.opcode() == spv::Op::OpVariable;
   };
 
   PoolPotentialIds(src_->types_values(), potential_id_map.src_ids, true,
@@ -2343,8 +2355,8 @@
     MatchIds(potential_id_map,
              [this, flexibility](const opt::Instruction* src_inst,
                                  const opt::Instruction* dst_inst) {
-               assert(src_inst->opcode() == SpvOpVariable);
-               assert(dst_inst->opcode() == SpvOpVariable);
+               assert(src_inst->opcode() == spv::Op::OpVariable);
+               assert(dst_inst->opcode() == spv::Op::OpVariable);
 
                return MatchOpVariable(src_inst, dst_inst, flexibility);
              });
@@ -2590,7 +2602,7 @@
   parsed_inst->num_words = static_cast<uint16_t>(inst_binary.size());
   parsed_inst->opcode = static_cast<uint16_t>(inst.opcode());
   parsed_inst->ext_inst_type =
-      inst.opcode() == SpvOpExtInst
+      inst.opcode() == spv::Op::OpExtInst
           ? GetExtInstType(id_to, original_inst.GetSingleWordInOperand(0))
           : SPV_EXT_INST_TYPE_NONE;
   parsed_inst->type_id =
diff --git a/third_party/SPIRV-Tools/source/disassemble.cpp b/third_party/SPIRV-Tools/source/disassemble.cpp
index 1d61b9f..f862efd 100644
--- a/third_party/SPIRV-Tools/source/disassemble.cpp
+++ b/third_party/SPIRV-Tools/source/disassemble.cpp
@@ -244,7 +244,7 @@
 
 void InstructionDisassembler::EmitInstruction(
     const spv_parsed_instruction_t& inst, size_t inst_byte_offset) {
-  auto opcode = static_cast<SpvOp>(inst.opcode);
+  auto opcode = static_cast<spv::Op>(inst.opcode);
 
   if (inst.result_id) {
     SetBlue();
@@ -268,7 +268,7 @@
     EmitOperand(inst, i);
   }
 
-  if (comment_ && opcode == SpvOpName) {
+  if (comment_ && opcode == spv::Op::OpName) {
     const spv_parsed_operand_t& operand = inst.operands[0];
     const uint32_t word = inst.words[operand.offset];
     stream_ << "  ; id %" << word;
@@ -290,8 +290,8 @@
 void InstructionDisassembler::EmitSectionComment(
     const spv_parsed_instruction_t& inst, bool& inserted_decoration_space,
     bool& inserted_debug_space, bool& inserted_type_space) {
-  auto opcode = static_cast<SpvOp>(inst.opcode);
-  if (comment_ && opcode == SpvOpFunction) {
+  auto opcode = static_cast<spv::Op>(inst.opcode);
+  if (comment_ && opcode == spv::Op::OpFunction) {
     stream_ << std::endl;
     stream_ << std::string(indent_, ' ');
     stream_ << "; Function " << name_mapper_(inst.result_id) << std::endl;
@@ -351,7 +351,7 @@
     } break;
     case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
       spv_opcode_desc opcode_desc;
-      if (grammar_.lookupOpcode(SpvOp(word), &opcode_desc))
+      if (grammar_.lookupOpcode(spv::Op(word), &opcode_desc))
         assert(false && "should have caught this earlier");
       SetRed();
       stream_ << opcode_desc->name;
diff --git a/third_party/SPIRV-Tools/source/enum_set.h b/third_party/SPIRV-Tools/source/enum_set.h
index d4d31e3..28ee5fe 100644
--- a/third_party/SPIRV-Tools/source/enum_set.h
+++ b/third_party/SPIRV-Tools/source/enum_set.h
@@ -200,8 +200,8 @@
   std::unique_ptr<OverflowSetType> overflow_ = {};
 };
 
-// A set of SpvCapability, optimized for small capability values.
-using CapabilitySet = EnumSet<SpvCapability>;
+// A set of spv::Capability, optimized for small capability values.
+using CapabilitySet = EnumSet<spv::Capability>;
 
 }  // namespace spvtools
 
diff --git a/third_party/SPIRV-Tools/source/enum_string_mapping.h b/third_party/SPIRV-Tools/source/enum_string_mapping.h
index af8f56b..b136584 100644
--- a/third_party/SPIRV-Tools/source/enum_string_mapping.h
+++ b/third_party/SPIRV-Tools/source/enum_string_mapping.h
@@ -29,7 +29,7 @@
 const char* ExtensionToString(Extension extension);
 
 // Returns text string corresponding to |capability|.
-const char* CapabilityToString(SpvCapability capability);
+const char* CapabilityToString(spv::Capability capability);
 
 }  // namespace spvtools
 
diff --git a/third_party/SPIRV-Tools/source/extensions.cpp b/third_party/SPIRV-Tools/source/extensions.cpp
index 049a3ad..ebf6bec 100644
--- a/third_party/SPIRV-Tools/source/extensions.cpp
+++ b/third_party/SPIRV-Tools/source/extensions.cpp
@@ -24,7 +24,9 @@
 namespace spvtools {
 
 std::string GetExtensionString(const spv_parsed_instruction_t* inst) {
-  if (inst->opcode != SpvOpExtension) return "ERROR_not_op_extension";
+  if (inst->opcode != static_cast<uint16_t>(spv::Op::OpExtension)) {
+    return "ERROR_not_op_extension";
+  }
 
   assert(inst->num_operands == 1);
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/added_function_reducer.cpp b/third_party/SPIRV-Tools/source/fuzz/added_function_reducer.cpp
index e7cb027..95cf9d6 100644
--- a/third_party/SPIRV-Tools/source/fuzz/added_function_reducer.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/added_function_reducer.cpp
@@ -130,7 +130,7 @@
                   binary_under_reduction.size());
   assert(ir_context != nullptr && "The binary should be parsable.");
   for (auto& type_or_value : ir_context->module()->types_values()) {
-    if (type_or_value.opcode() != SpvOpVariable) {
+    if (type_or_value.opcode() != spv::Op::OpVariable) {
       continue;
     }
     if (irrelevant_pointee_global_variables.count(type_or_value.result_id())) {
@@ -202,7 +202,7 @@
   auto* ir_context = replay_result.transformed_module.get();
 
   for (auto& type_or_value : ir_context->module()->types_values()) {
-    if (type_or_value.opcode() != SpvOpVariable) {
+    if (type_or_value.opcode() != spv::Op::OpVariable) {
       continue;
     }
     if (replay_result.transformation_context->GetFactManager()
diff --git a/third_party/SPIRV-Tools/source/fuzz/call_graph.cpp b/third_party/SPIRV-Tools/source/fuzz/call_graph.cpp
index c52bc34..d61a5f8 100644
--- a/third_party/SPIRV-Tools/source/fuzz/call_graph.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/call_graph.cpp
@@ -54,7 +54,7 @@
     // Consider every function call instruction in every block.
     for (auto& block : function) {
       for (auto& instruction : block) {
-        if (instruction.opcode() != SpvOpFunctionCall) {
+        if (instruction.opcode() != spv::Op::OpFunctionCall) {
           continue;
         }
         // Get the id of the function being called.
diff --git a/third_party/SPIRV-Tools/source/fuzz/fact_manager/constant_uniform_facts.cpp b/third_party/SPIRV-Tools/source/fuzz/fact_manager/constant_uniform_facts.cpp
index a629c0d..461859b 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fact_manager/constant_uniform_facts.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fact_manager/constant_uniform_facts.cpp
@@ -63,7 +63,7 @@
 bool ConstantUniformFacts::DataMatches(
     const opt::Instruction& constant_instruction,
     const protobufs::FactConstantUniform& constant_uniform_fact) {
-  assert(constant_instruction.opcode() == SpvOpConstant);
+  assert(constant_instruction.opcode() == spv::Op::OpConstant);
   std::vector<uint32_t> data_in_constant;
   for (uint32_t i = 0; i < constant_instruction.NumInOperands(); i++) {
     data_in_constant.push_back(constant_instruction.GetSingleWordInOperand(i));
@@ -95,7 +95,7 @@
     uint32_t constant_id) const {
   std::vector<protobufs::UniformBufferElementDescriptor> result;
   auto constant_inst = ir_context_->get_def_use_mgr()->GetDef(constant_id);
-  assert(constant_inst->opcode() == SpvOpConstant &&
+  assert(constant_inst->opcode() == spv::Op::OpConstant &&
          "The given id must be that of a constant");
   auto type_id = constant_inst->type_id();
   for (auto& fact_and_type_id : facts_and_type_ids_) {
@@ -175,8 +175,9 @@
     return false;
   }
 
-  assert(SpvOpVariable == uniform_variable->opcode());
-  assert(SpvStorageClassUniform == uniform_variable->GetSingleWordInOperand(0));
+  assert(spv::Op::OpVariable == uniform_variable->opcode());
+  assert(spv::StorageClass::Uniform ==
+         spv::StorageClass(uniform_variable->GetSingleWordInOperand(0)));
 
   auto should_be_uniform_pointer_type =
       ir_context_->get_type_mgr()->GetType(uniform_variable->type_id());
@@ -184,7 +185,7 @@
     return false;
   }
   if (should_be_uniform_pointer_type->AsPointer()->storage_class() !=
-      SpvStorageClassUniform) {
+      spv::StorageClass::Uniform) {
     return false;
   }
   auto should_be_uniform_pointer_instruction =
diff --git a/third_party/SPIRV-Tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp b/third_party/SPIRV-Tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp
index a2c1f2c..b43b8ed 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp
@@ -23,7 +23,7 @@
 size_t DataSynonymAndIdEquationFacts::OperationHash::operator()(
     const Operation& operation) const {
   std::u32string hash;
-  hash.push_back(operation.opcode);
+  hash.push_back(uint32_t(operation.opcode));
   for (auto operand : operation.operands) {
     hash.push_back(static_cast<uint32_t>(DataDescriptorHash()(operand)));
   }
@@ -104,7 +104,8 @@
   }
 
   // Now add the fact.
-  AddEquationFactRecursive(lhs_dd, static_cast<SpvOp>(fact.opcode()), rhs_dds);
+  AddEquationFactRecursive(lhs_dd, static_cast<spv::Op>(fact.opcode()),
+                           rhs_dds);
   return true;
 }
 
@@ -119,7 +120,7 @@
 }
 
 void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
-    const protobufs::DataDescriptor& lhs_dd, SpvOp opcode,
+    const protobufs::DataDescriptor& lhs_dd, spv::Op opcode,
     const std::vector<const protobufs::DataDescriptor*>& rhs_dds) {
   assert(synonymous_.Exists(lhs_dd) &&
          "The LHS must be known to the equivalence relation.");
@@ -155,21 +156,21 @@
   // Now try to work out corollaries implied by the new equation and existing
   // facts.
   switch (opcode) {
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
       ComputeConversionDataSynonymFacts(*rhs_dds[0]);
       break;
-    case SpvOpBitcast: {
+    case spv::Op::OpBitcast: {
       assert(DataDescriptorsAreWellFormedAndComparable(lhs_dd, *rhs_dds[0]) &&
              "Operands of OpBitcast equation fact must have compatible types");
       if (!synonymous_.IsEquivalent(lhs_dd, *rhs_dds[0])) {
         AddDataSynonymFactRecursive(lhs_dd, *rhs_dds[0]);
       }
     } break;
-    case SpvOpIAdd: {
+    case spv::Op::OpIAdd: {
       // Equation form: "a = b + c"
       for (const auto& equation : GetEquations(rhs_dds[0])) {
-        if (equation.opcode == SpvOpISub) {
+        if (equation.opcode == spv::Op::OpISub) {
           // Equation form: "a = (d - e) + c"
           if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[1])) {
             // Equation form: "a = (d - c) + c"
@@ -179,7 +180,7 @@
         }
       }
       for (const auto& equation : GetEquations(rhs_dds[1])) {
-        if (equation.opcode == SpvOpISub) {
+        if (equation.opcode == spv::Op::OpISub) {
           // Equation form: "a = b + (d - e)"
           if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
             // Equation form: "a = b + (d - b)"
@@ -190,10 +191,10 @@
       }
       break;
     }
-    case SpvOpISub: {
+    case spv::Op::OpISub: {
       // Equation form: "a = b - c"
       for (const auto& equation : GetEquations(rhs_dds[0])) {
-        if (equation.opcode == SpvOpIAdd) {
+        if (equation.opcode == spv::Op::OpIAdd) {
           // Equation form: "a = (d + e) - c"
           if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
             // Equation form: "a = (c + e) - c"
@@ -207,34 +208,34 @@
           }
         }
 
-        if (equation.opcode == SpvOpISub) {
+        if (equation.opcode == spv::Op::OpISub) {
           // Equation form: "a = (d - e) - c"
           if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
             // Equation form: "a = (c - e) - c"
             // We can thus infer "a = -e"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
+            AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
                                      {equation.operands[1]});
           }
         }
       }
 
       for (const auto& equation : GetEquations(rhs_dds[1])) {
-        if (equation.opcode == SpvOpIAdd) {
+        if (equation.opcode == spv::Op::OpIAdd) {
           // Equation form: "a = b - (d + e)"
           if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
             // Equation form: "a = b - (b + e)"
             // We can thus infer "a = -e"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
+            AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
                                      {equation.operands[1]});
           }
           if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
             // Equation form: "a = b - (d + b)"
             // We can thus infer "a = -d"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
+            AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
                                      {equation.operands[0]});
           }
         }
-        if (equation.opcode == SpvOpISub) {
+        if (equation.opcode == spv::Op::OpISub) {
           // Equation form: "a = b - (d - e)"
           if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
             // Equation form: "a = b - (b - e)"
@@ -245,8 +246,8 @@
       }
       break;
     }
-    case SpvOpLogicalNot:
-    case SpvOpSNegate: {
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSNegate: {
       // Equation form: "a = !b" or "a = -b"
       for (const auto& equation : GetEquations(rhs_dds[0])) {
         if (equation.opcode == opcode) {
@@ -321,9 +322,9 @@
 
       for (const auto& equation : fact.second) {
         if (synonymous_.IsEquivalent(*equation.operands[0], dd)) {
-          if (equation.opcode == SpvOpConvertSToF) {
+          if (equation.opcode == spv::Op::OpConvertSToF) {
             convert_s_to_f_lhs.push_back(*dd_it);
-          } else if (equation.opcode == SpvOpConvertUToF) {
+          } else if (equation.opcode == spv::Op::OpConvertUToF) {
             convert_u_to_f_lhs.push_back(*dd_it);
           }
         }
@@ -808,9 +809,9 @@
   }
   // Neither end type is allowed to be void.
   if (ir_context_->get_def_use_mgr()->GetDef(end_type_id_1)->opcode() ==
-          SpvOpTypeVoid ||
+          spv::Op::OpTypeVoid ||
       ir_context_->get_def_use_mgr()->GetDef(end_type_id_2)->opcode() ==
-          SpvOpTypeVoid) {
+          spv::Op::OpTypeVoid) {
     return false;
   }
   // If the end types are the same, the data descriptors are comparable.
diff --git a/third_party/SPIRV-Tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h b/third_party/SPIRV-Tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h
index 6652f30..36d92ca 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h
+++ b/third_party/SPIRV-Tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h
@@ -79,7 +79,7 @@
   // This helper struct represents the right hand side of an equation as an
   // operator applied to a number of data descriptor operands.
   struct Operation {
-    SpvOp opcode;
+    spv::Op opcode;
     std::vector<const protobufs::DataDescriptor*> operands;
   };
 
@@ -144,7 +144,7 @@
   // corollaries, in the form of data synonym or equation facts, that follow
   // from this and other known facts.
   void AddEquationFactRecursive(
-      const protobufs::DataDescriptor& lhs_dd, SpvOp opcode,
+      const protobufs::DataDescriptor& lhs_dd, spv::Op opcode,
       const std::vector<const protobufs::DataDescriptor*>& rhs_dds);
 
   // Returns true if and only if |dd.object()| still exists in the module.
diff --git a/third_party/SPIRV-Tools/source/fuzz/fact_manager/fact_manager.cpp b/third_party/SPIRV-Tools/source/fuzz/fact_manager/fact_manager.cpp
index 40c0865..c99f690 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fact_manager/fact_manager.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fact_manager/fact_manager.cpp
@@ -64,7 +64,7 @@
 std::string ToString(const protobufs::FactIdEquation& fact) {
   std::stringstream stream;
   stream << fact.lhs_id();
-  stream << " " << static_cast<SpvOp>(fact.opcode());
+  stream << " " << fact.opcode();
   for (auto rhs_id : fact.rhs_id()) {
     stream << " " << rhs_id;
   }
@@ -255,11 +255,11 @@
   assert(success && "|result_id| is invalid");
 }
 
-void FactManager::AddFactIdEquation(uint32_t lhs_id, SpvOp opcode,
+void FactManager::AddFactIdEquation(uint32_t lhs_id, spv::Op opcode,
                                     const std::vector<uint32_t>& rhs_id) {
   protobufs::FactIdEquation fact;
   fact.set_lhs_id(lhs_id);
-  fact.set_opcode(opcode);
+  fact.set_opcode(uint32_t(opcode));
   for (auto an_rhs_id : rhs_id) {
     fact.add_rhs_id(an_rhs_id);
   }
diff --git a/third_party/SPIRV-Tools/source/fuzz/fact_manager/fact_manager.h b/third_party/SPIRV-Tools/source/fuzz/fact_manager/fact_manager.h
index ce28ae4..4453e44 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fact_manager/fact_manager.h
+++ b/third_party/SPIRV-Tools/source/fuzz/fact_manager/fact_manager.h
@@ -83,7 +83,7 @@
   //   |lhs_id| = |opcode| |rhs_id[0]| ... |rhs_id[N-1]|
   //
   // Neither |lhs_id| nor any of |rhs_id| may be irrelevant.
-  void AddFactIdEquation(uint32_t lhs_id, SpvOp opcode,
+  void AddFactIdEquation(uint32_t lhs_id, spv::Op opcode,
                          const std::vector<uint32_t>& rhs_id);
 
   // Inspects all known facts and adds corollary facts; e.g. if we know that
diff --git a/third_party/SPIRV-Tools/source/fuzz/force_render_red.cpp b/third_party/SPIRV-Tools/source/fuzz/force_render_red.cpp
index 3267487..191fd71 100644
--- a/third_party/SPIRV-Tools/source/fuzz/force_render_red.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/force_render_red.cpp
@@ -36,8 +36,9 @@
   // Check that this is a fragment shader
   bool found_capability_shader = false;
   for (auto& capability : ir_context->capabilities()) {
-    assert(capability.opcode() == SpvOpCapability);
-    if (capability.GetSingleWordInOperand(0) == SpvCapabilityShader) {
+    assert(capability.opcode() == spv::Op::OpCapability);
+    if (spv::Capability(capability.GetSingleWordInOperand(0)) ==
+        spv::Capability::Shader) {
       found_capability_shader = true;
       break;
     }
@@ -51,7 +52,8 @@
 
   opt::Instruction* fragment_entry_point = nullptr;
   for (auto& entry_point : ir_context->module()->entry_points()) {
-    if (entry_point.GetSingleWordInOperand(0) == SpvExecutionModelFragment) {
+    if (spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) ==
+        spv::ExecutionModel::Fragment) {
       fragment_entry_point = &entry_point;
       break;
     }
@@ -81,8 +83,9 @@
                                          MessageConsumer message_consumer) {
   opt::Instruction* output_variable = nullptr;
   for (auto& inst : ir_context->types_values()) {
-    if (inst.opcode() == SpvOpVariable &&
-        inst.GetSingleWordInOperand(0) == SpvStorageClassOutput) {
+    if (inst.opcode() == spv::Op::OpVariable &&
+        spv::StorageClass(inst.GetSingleWordInOperand(0)) ==
+            spv::StorageClass::Output) {
       if (output_variable != nullptr) {
         message_consumer(SPV_MSG_ERROR, nullptr, {},
                          "Only one output variable can be handled at present; "
@@ -144,10 +147,11 @@
                                uint32_t greater_than_instruction,
                                uint32_t in_operand_index) {
   return MakeUnique<TransformationReplaceConstantWithUniform>(
-      MakeIdUseDescriptor(constant_id,
-                          MakeInstructionDescriptor(greater_than_instruction,
-                                                    SpvOpFOrdGreaterThan, 0),
-                          in_operand_index),
+      MakeIdUseDescriptor(
+          constant_id,
+          MakeInstructionDescriptor(greater_than_instruction,
+                                    spv::Op::OpFOrdGreaterThan, 0),
+          in_operand_index),
       fact_manager.GetUniformDescriptorsForConstant(constant_id)[0],
       ir_context->TakeNextId(), ir_context->TakeNextId());
 }
@@ -204,20 +208,21 @@
   // Make the new exit block
   auto new_exit_block_id = ir_context->TakeNextId();
   {
-    auto label = MakeUnique<opt::Instruction>(ir_context.get(), SpvOpLabel, 0,
-                                              new_exit_block_id,
-                                              opt::Instruction::OperandList());
+    auto label = MakeUnique<opt::Instruction>(
+        ir_context.get(), spv::Op::OpLabel, 0, new_exit_block_id,
+        opt::Instruction::OperandList());
     auto new_exit_block = MakeUnique<opt::BasicBlock>(std::move(label));
-    new_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context.get(), SpvOpReturn, 0, 0, opt::Instruction::OperandList()));
+    new_exit_block->AddInstruction(
+        MakeUnique<opt::Instruction>(ir_context.get(), spv::Op::OpReturn, 0, 0,
+                                     opt::Instruction::OperandList()));
     entry_point_function->AddBasicBlock(std::move(new_exit_block));
   }
 
   // Make the new entry block
   {
-    auto label = MakeUnique<opt::Instruction>(ir_context.get(), SpvOpLabel, 0,
-                                              ir_context->TakeNextId(),
-                                              opt::Instruction::OperandList());
+    auto label = MakeUnique<opt::Instruction>(
+        ir_context.get(), spv::Op::OpLabel, 0, ir_context->TakeNextId(),
+        opt::Instruction::OperandList());
     auto new_entry_block = MakeUnique<opt::BasicBlock>(std::move(label));
 
     // Make an instruction to construct vec4(1.0, 0.0, 0.0, 1.0), representing
@@ -229,7 +234,7 @@
     auto temp_vec4 = opt::analysis::Vector(float_type, 4);
     auto vec4_id = ir_context->get_type_mgr()->GetId(&temp_vec4);
     auto red = MakeUnique<opt::Instruction>(
-        ir_context.get(), SpvOpCompositeConstruct, vec4_id,
+        ir_context.get(), spv::Op::OpCompositeConstruct, vec4_id,
         ir_context->TakeNextId(), op_composite_construct_operands);
     auto red_id = red->result_id();
     new_entry_block->AddInstruction(std::move(red));
@@ -241,7 +246,7 @@
     opt::Instruction::OperandList op_store_operands = {variable_to_store_into,
                                                        value_to_be_stored};
     new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context.get(), SpvOpStore, 0, 0, op_store_operands));
+        ir_context.get(), spv::Op::OpStore, 0, 0, op_store_operands));
 
     // We are going to attempt to construct 'false' as an expression of the form
     // 'literal1 > literal2'. If we succeed, we will later replace each literal
@@ -313,7 +318,7 @@
               {SPV_OPERAND_TYPE_ID, {smaller_constant}},
               {SPV_OPERAND_TYPE_ID, {larger_constant}}};
           new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-              ir_context.get(), SpvOpFOrdGreaterThan,
+              ir_context.get(), spv::Op::OpFOrdGreaterThan,
               ir_context->get_type_mgr()->GetId(registered_bool_type),
               id_guaranteed_to_be_false, greater_than_operands));
 
@@ -344,9 +349,9 @@
     opt::Operand else_block = {SPV_OPERAND_TYPE_ID, {new_exit_block_id}};
     opt::Instruction::OperandList op_branch_conditional_operands = {
         false_condition, then_block, else_block};
-    new_entry_block->AddInstruction(
-        MakeUnique<opt::Instruction>(ir_context.get(), SpvOpBranchConditional,
-                                     0, 0, op_branch_conditional_operands));
+    new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
+        ir_context.get(), spv::Op::OpBranchConditional, 0, 0,
+        op_branch_conditional_operands));
 
     entry_point_function->InsertBasicBlockBefore(
         std::move(new_entry_block), entry_point_function->entry().get());
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass.cpp
index 6a87985..02d8aa1 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass.cpp
@@ -131,14 +131,15 @@
     // should skip when searching from 'base' for the desired instruction.
     // (An instruction that has a result id is represented by its own opcode,
     // itself as 'base', and a skip-count of 0.)
-    std::vector<std::tuple<uint32_t, SpvOp, uint32_t>> base_opcode_skip_triples;
+    std::vector<std::tuple<uint32_t, spv::Op, uint32_t>>
+        base_opcode_skip_triples;
 
     // The initial base instruction is the block label.
     uint32_t base = block->id();
 
     // Counts the number of times we have seen each opcode since we reset the
     // base instruction.
-    std::map<SpvOp, uint32_t> skip_count;
+    std::map<spv::Op, uint32_t> skip_count;
 
     // Consider every instruction in the block.  The label is excluded: it is
     // only necessary to consider it as a base in case the first instruction
@@ -151,7 +152,7 @@
         base = inst_it->result_id();
         skip_count.clear();
       }
-      const SpvOp opcode = inst_it->opcode();
+      const spv::Op opcode = inst_it->opcode();
 
       // Invoke the provided function, which might apply a transformation.
       action(block, inst_it,
@@ -330,7 +331,7 @@
 }
 
 uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
-                                             SpvStorageClass storage_class) {
+                                             spv::StorageClass storage_class) {
   // We do not use the type manager here, due to problems related to isomorphic
   // but distinct structs not being regarded as different.
   auto existing_id = fuzzerutil::MaybeGetPointerType(
@@ -345,7 +346,7 @@
 }
 
 uint32_t FuzzerPass::FindOrCreatePointerToIntegerType(
-    uint32_t width, bool is_signed, SpvStorageClass storage_class) {
+    uint32_t width, bool is_signed, spv::StorageClass storage_class) {
   return FindOrCreatePointerType(FindOrCreateIntegerType(width, is_signed),
                                  storage_class);
 }
@@ -432,7 +433,7 @@
 
 uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) {
   for (auto& inst : GetIRContext()->types_values()) {
-    if (inst.opcode() == SpvOpUndef && inst.type_id() == type_id) {
+    if (inst.opcode() == spv::Op::OpUndef && inst.type_id() == type_id) {
       return inst.result_id();
     }
   }
@@ -464,7 +465,7 @@
 
 std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
 FuzzerPass::GetAvailableBasicTypesAndPointers(
-    SpvStorageClass storage_class) const {
+    spv::StorageClass storage_class) const {
   // Records all of the basic types available in the module.
   std::set<uint32_t> basic_types;
 
@@ -480,23 +481,23 @@
     // For pointer types with basic pointee types, associate the pointer type
     // with the basic type.
     switch (inst.opcode()) {
-      case SpvOpTypeBool:
-      case SpvOpTypeFloat:
-      case SpvOpTypeInt:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeBool:
+      case spv::Op::OpTypeFloat:
+      case spv::Op::OpTypeInt:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
         // These are all basic types.
         basic_types.insert(inst.result_id());
         basic_type_to_pointers.insert({inst.result_id(), {}});
         break;
-      case SpvOpTypeArray:
+      case spv::Op::OpTypeArray:
         // An array type is basic if its base type is basic.
         if (basic_types.count(inst.GetSingleWordInOperand(0))) {
           basic_types.insert(inst.result_id());
           basic_type_to_pointers.insert({inst.result_id(), {}});
         }
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // A struct type is basic if it does not have the Block/BufferBlock
         // decoration, and if all of its members are basic.
         if (!fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
@@ -515,11 +516,12 @@
         }
         break;
       }
-      case SpvOpTypePointer: {
+      case spv::Op::OpTypePointer: {
         // We are interested in the pointer if its pointee type is basic and it
         // has the right storage class.
         auto pointee_type = inst.GetSingleWordInOperand(1);
-        if (inst.GetSingleWordInOperand(0) == storage_class &&
+        if (spv::StorageClass(inst.GetSingleWordInOperand(0)) ==
+                storage_class &&
             basic_types.count(pointee_type)) {
           // The pointer has the desired storage class, and its pointee type is
           // a basic type, so we are interested in it.  Associate it with its
@@ -541,22 +543,22 @@
       GetIRContext()->get_def_use_mgr()->GetDef(scalar_or_composite_type_id);
   assert(type_instruction && "The type instruction must exist.");
   switch (type_instruction->opcode()) {
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       return FindOrCreateBoolConstant(false, is_irrelevant);
-    case SpvOpTypeFloat: {
+    case spv::Op::OpTypeFloat: {
       auto width = type_instruction->GetSingleWordInOperand(0);
       auto num_words = (width + 32 - 1) / 32;
       return FindOrCreateFloatConstant(std::vector<uint32_t>(num_words, 0),
                                        width, is_irrelevant);
     }
-    case SpvOpTypeInt: {
+    case spv::Op::OpTypeInt: {
       auto width = type_instruction->GetSingleWordInOperand(0);
       auto num_words = (width + 32 - 1) / 32;
       return FindOrCreateIntegerConstant(
           std::vector<uint32_t>(num_words, 0), width,
           type_instruction->GetSingleWordInOperand(1), is_irrelevant);
     }
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       auto component_type_id = type_instruction->GetSingleWordInOperand(0);
       auto num_components =
           fuzzerutil::GetArraySize(*type_instruction, GetIRContext());
@@ -566,8 +568,8 @@
               FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
           scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector: {
       auto component_type_id = type_instruction->GetSingleWordInOperand(0);
       auto num_components = type_instruction->GetSingleWordInOperand(1);
       return FindOrCreateCompositeConstant(
@@ -576,7 +578,7 @@
               FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
           scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       assert(!fuzzerutil::HasBlockOrBufferBlockDecoration(
                  GetIRContext(), scalar_or_composite_type_id) &&
              "We do not construct constants of struct types decorated with "
@@ -646,7 +648,7 @@
 
     // |maybe_preheader| is a preheader if it branches unconditionally to
     // the header. We also require it not to be a loop header.
-    if (maybe_preheader->terminator()->opcode() == SpvOpBranch &&
+    if (maybe_preheader->terminator()->opcode() == spv::Op::OpBranch &&
         !maybe_preheader->IsLoopHeader()) {
       return maybe_preheader;
     }
@@ -683,8 +685,8 @@
 
   // Find the first non-OpPhi and non-OpVariable instruction.
   auto non_phi_or_var_inst = &*block->begin();
-  while (non_phi_or_var_inst->opcode() == SpvOpPhi ||
-         non_phi_or_var_inst->opcode() == SpvOpVariable) {
+  while (non_phi_or_var_inst->opcode() == spv::Op::OpPhi ||
+         non_phi_or_var_inst->opcode() == spv::Op::OpVariable) {
     non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
   }
 
@@ -706,7 +708,7 @@
   (void)pointer_type;
   assert(pointer_type && pointer_type->AsPointer() &&
          pointer_type->AsPointer()->storage_class() ==
-             SpvStorageClassFunction &&
+             spv::StorageClass::Function &&
          "The pointer_type_id must refer to a defined pointer type with "
          "storage class Function");
   auto function = fuzzerutil::FindFunction(GetIRContext(), function_id);
@@ -715,7 +717,7 @@
   // First we try to find a suitable existing variable.
   // All of the local variable declarations are located in the first block.
   for (auto& instruction : *function->begin()) {
-    if (instruction.opcode() != SpvOpVariable) {
+    if (instruction.opcode() != spv::Op::OpVariable) {
       continue;
     }
     // The existing OpVariable must have type |pointer_type_id|.
@@ -749,15 +751,16 @@
   (void)pointer_type;
   assert(
       pointer_type && pointer_type->AsPointer() &&
-      (pointer_type->AsPointer()->storage_class() == SpvStorageClassPrivate ||
+      (pointer_type->AsPointer()->storage_class() ==
+           spv::StorageClass::Private ||
        pointer_type->AsPointer()->storage_class() ==
-           SpvStorageClassWorkgroup) &&
+           spv::StorageClass::Workgroup) &&
       "The pointer_type_id must refer to a defined pointer type with storage "
       "class Private or Workgroup");
 
   // First we try to find a suitable existing variable.
   for (auto& instruction : GetIRContext()->module()->types_values()) {
-    if (instruction.opcode() != SpvOpVariable) {
+    if (instruction.opcode() != spv::Op::OpVariable) {
       continue;
     }
     // The existing OpVariable must have type |pointer_type_id|.
@@ -781,13 +784,13 @@
   uint32_t result_id = GetFuzzerContext()->GetFreshId();
 
   // A variable with storage class Workgroup shouldn't have an initializer.
-  if (storage_class == SpvStorageClassWorkgroup) {
+  if (storage_class == spv::StorageClass::Workgroup) {
     ApplyTransformation(TransformationAddGlobalVariable(
-        result_id, pointer_type_id, SpvStorageClassWorkgroup, 0,
+        result_id, pointer_type_id, spv::StorageClass::Workgroup, 0,
         pointee_value_is_irrelevant));
   } else {
     ApplyTransformation(TransformationAddGlobalVariable(
-        result_id, pointer_type_id, SpvStorageClassPrivate,
+        result_id, pointer_type_id, spv::StorageClass::Private,
         FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant),
         pointee_value_is_irrelevant));
   }
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass.h b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass.h
index 2655b54..5c76be1 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass.h
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass.h
@@ -159,14 +159,14 @@
   // already exist) and storage class |storage_class|.  A transformation is
   // applied to add the pointer if it does not already exist.
   uint32_t FindOrCreatePointerType(uint32_t base_type_id,
-                                   SpvStorageClass storage_class);
+                                   spv::StorageClass storage_class);
 
   // Returns the id of an OpTypePointer instruction, with a integer base
   // type of width and signedness specified by |width| and |is_signed|,
   // respectively.  If the pointer type or required integer base type do not
   // exist, transformations are applied to add them.
   uint32_t FindOrCreatePointerToIntegerType(uint32_t width, bool is_signed,
-                                            SpvStorageClass storage_class);
+                                            spv::StorageClass storage_class);
 
   // Returns the id of an OpConstant instruction, with a integer type of
   // width and signedness specified by |width| and |is_signed|, respectively,
@@ -239,7 +239,7 @@
   //   storage class, and the sequence will have multiple elements if there are
   //   repeated pointer declarations for the same basic type and storage class.
   std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
-  GetAvailableBasicTypesAndPointers(SpvStorageClass storage_class) const;
+  GetAvailableBasicTypesAndPointers(spv::StorageClass storage_class) const;
 
   // Given a type id, |scalar_or_composite_type_id|, which must correspond to
   // some scalar or composite type, returns the result id of an instruction
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_access_chains.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_access_chains.cpp
index 39f193d..85ca57d 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_access_chains.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_access_chains.cpp
@@ -34,15 +34,16 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            inst_it->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Check whether it is legitimate to insert an access chain
         // instruction before this instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAccessChain,
-                                                          inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpAccessChain, inst_it)) {
           return;
         }
 
@@ -64,8 +65,8 @@
                     return false;
                   }
                   switch (instruction->opcode()) {
-                    case SpvOpConstantNull:
-                    case SpvOpUndef:
+                    case spv::Op::OpConstantNull:
+                    case spv::Op::OpUndef:
                       // Do not allow making an access chain from a null or
                       // undefined pointer.  (We can eliminate these cases
                       // before actually checking that the instruction is a
@@ -78,7 +79,7 @@
                   // make an access chain from it.
                   return context->get_def_use_mgr()
                              ->GetDef(instruction->type_id())
-                             ->opcode() == SpvOpTypePointer;
+                             ->opcode() == spv::Op::OpTypePointer;
                 });
 
         // At this point, |relevant_instructions| contains all the pointers
@@ -112,14 +113,14 @@
           }
           uint32_t bound;
           switch (subobject_type->opcode()) {
-            case SpvOpTypeArray:
+            case spv::Op::OpTypeArray:
               bound = fuzzerutil::GetArraySize(*subobject_type, GetIRContext());
               break;
-            case SpvOpTypeMatrix:
-            case SpvOpTypeVector:
+            case spv::Op::OpTypeMatrix:
+            case spv::Op::OpTypeVector:
               bound = subobject_type->GetSingleWordInOperand(1);
               break;
-            case SpvOpTypeStruct:
+            case spv::Op::OpTypeStruct:
               bound = fuzzerutil::GetNumberOfStructMembers(*subobject_type);
               break;
             default:
@@ -140,9 +141,9 @@
               GetFuzzerContext()->GetRandomIndexForAccessChain(bound);
 
           switch (subobject_type->opcode()) {
-            case SpvOpTypeArray:
-            case SpvOpTypeMatrix:
-            case SpvOpTypeVector: {
+            case spv::Op::OpTypeArray:
+            case spv::Op::OpTypeMatrix:
+            case spv::Op::OpTypeVector: {
               // The index will be clamped
 
               bool is_signed = GetFuzzerContext()->ChooseEven();
@@ -164,7 +165,7 @@
               subobject_type_id = subobject_type->GetSingleWordInOperand(0);
 
             } break;
-            case SpvOpTypeStruct:
+            case spv::Op::OpTypeStruct:
               index_ids.push_back(FindOrCreateIntegerConstant(
                   {index_value}, 32, GetFuzzerContext()->ChooseEven(), false));
               subobject_type_id =
@@ -178,7 +179,7 @@
         // pointer suitable for the access chain's result type exists, so we
         // create one if it does not.
         FindOrCreatePointerType(subobject_type_id,
-                                static_cast<SpvStorageClass>(
+                                static_cast<spv::StorageClass>(
                                     pointer_type->GetSingleWordInOperand(0)));
         // Apply the transformation to add an access chain.
         ApplyTransformation(TransformationAccessChain(
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_extract.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_extract.cpp
index dbbec0c..c33ae44 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_extract.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_extract.cpp
@@ -53,8 +53,8 @@
           opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
           opt::BasicBlock::iterator inst_it,
           const protobufs::InstructionDescriptor& instruction_descriptor) {
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                          inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpCompositeExtract, inst_it)) {
           return;
         }
 
@@ -97,15 +97,15 @@
             assert(type_inst && "Composite instruction has invalid type id");
 
             switch (type_inst->opcode()) {
-              case SpvOpTypeArray:
+              case spv::Op::OpTypeArray:
                 number_of_members =
                     fuzzerutil::GetArraySize(*type_inst, GetIRContext());
                 break;
-              case SpvOpTypeVector:
-              case SpvOpTypeMatrix:
+              case spv::Op::OpTypeVector:
+              case spv::Op::OpTypeMatrix:
                 number_of_members = type_inst->GetSingleWordInOperand(1);
                 break;
-              case SpvOpTypeStruct:
+              case spv::Op::OpTypeStruct:
                 number_of_members = type_inst->NumInOperands();
                 break;
               default:
@@ -122,12 +122,12 @@
                     number_of_members));
 
             switch (type_inst->opcode()) {
-              case SpvOpTypeArray:
-              case SpvOpTypeVector:
-              case SpvOpTypeMatrix:
+              case spv::Op::OpTypeArray:
+              case spv::Op::OpTypeVector:
+              case spv::Op::OpTypeMatrix:
                 type_id = type_inst->GetSingleWordInOperand(0);
                 break;
-              case SpvOpTypeStruct:
+              case spv::Op::OpTypeStruct:
                 type_id = type_inst->GetSingleWordInOperand(indices.back());
                 break;
               default:
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_inserts.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
index 2ac12de..048cdfd 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
@@ -36,10 +36,11 @@
              opt::BasicBlock::iterator instruction_iterator,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(instruction_iterator->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            instruction_iterator->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try adding an OpCompositeInsert
         // instruction.
@@ -51,7 +52,7 @@
         // It must be possible to insert an OpCompositeInsert instruction
         // before |instruction_iterator|.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpCompositeInsert, instruction_iterator)) {
+                spv::Op::OpCompositeInsert, instruction_iterator)) {
           return;
         }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_types.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_types.cpp
index af36ad0..bb90991 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_types.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_composite_types.cpp
@@ -114,15 +114,15 @@
   std::vector<uint32_t> candidates;
   for (auto& inst : GetIRContext()->types_values()) {
     switch (inst.opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeBool:
-      case SpvOpTypeFloat:
-      case SpvOpTypeInt:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeBool:
+      case spv::Op::OpTypeFloat:
+      case spv::Op::OpTypeInt:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
         candidates.push_back(inst.result_id());
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         if (!fuzzerutil::MembersHaveBuiltInDecoration(GetIRContext(),
                                                       inst.result_id()) &&
             !fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_copy_memory.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_copy_memory.cpp
index 6551f49..d54d4ad 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_copy_memory.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_copy_memory.cpp
@@ -36,7 +36,7 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor) {
         // Check that we can insert an OpCopyMemory before this instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyMemory,
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyMemory,
                                                           inst_it)) {
           return;
         }
@@ -61,8 +61,8 @@
 
         // Decide whether to create global or local variable.
         auto storage_class = GetFuzzerContext()->ChooseEven()
-                                 ? SpvStorageClassPrivate
-                                 : SpvStorageClassFunction;
+                                 ? spv::StorageClass::Private
+                                 : spv::StorageClass::Function;
 
         auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
             GetIRContext(), inst->type_id());
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
index 4bbded8..e720c4e 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
@@ -29,12 +29,14 @@
       return true;
     case 64:
       return ir_context->get_feature_mgr()->HasCapability(
-                 SpvCapabilityFloat64) &&
-             ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt64);
+                 spv::Capability::Float64) &&
+             ir_context->get_feature_mgr()->HasCapability(
+                 spv::Capability::Int64);
     case 16:
       return ir_context->get_feature_mgr()->HasCapability(
-                 SpvCapabilityFloat16) &&
-             ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt16);
+                 spv::Capability::Float16) &&
+             ir_context->get_feature_mgr()->HasCapability(
+                 spv::Capability::Int16);
     default:
       return false;
   }
@@ -66,7 +68,8 @@
         // as an example opcode for this check, to be representative of *some*
         // opcode that defines an equation, even though we may choose a
         // different opcode below.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd, inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
+                                                          inst_it)) {
           return;
         }
 
@@ -78,7 +81,7 @@
                 [this](opt::IRContext* /*unused*/,
                        opt::Instruction* instruction) -> bool {
                   return instruction->result_id() && instruction->type_id() &&
-                         instruction->opcode() != SpvOpUndef &&
+                         instruction->opcode() != spv::Op::OpUndef &&
                          !GetTransformationContext()
                               ->GetFactManager()
                               ->IdIsIrrelevant(instruction->result_id());
@@ -86,15 +89,16 @@
 
         // Try the opcodes for which we know how to make ids at random until
         // something works.
-        std::vector<SpvOp> candidate_opcodes = {
-            SpvOpIAdd,        SpvOpISub,        SpvOpLogicalNot, SpvOpSNegate,
-            SpvOpConvertUToF, SpvOpConvertSToF, SpvOpBitcast};
+        std::vector<spv::Op> candidate_opcodes = {
+            spv::Op::OpIAdd,    spv::Op::OpISub,        spv::Op::OpLogicalNot,
+            spv::Op::OpSNegate, spv::Op::OpConvertUToF, spv::Op::OpConvertSToF,
+            spv::Op::OpBitcast};
         do {
           auto opcode =
               GetFuzzerContext()->RemoveAtRandomIndex(&candidate_opcodes);
           switch (opcode) {
-            case SpvOpConvertSToF:
-            case SpvOpConvertUToF: {
+            case spv::Op::OpConvertSToF:
+            case spv::Op::OpConvertUToF: {
               std::vector<const opt::Instruction*> candidate_instructions;
               for (const auto* inst :
                    GetIntegerInstructions(available_instructions)) {
@@ -144,7 +148,7 @@
                   {operand->result_id()}, instruction_descriptor));
               return;
             }
-            case SpvOpBitcast: {
+            case spv::Op::OpBitcast: {
               const auto candidate_instructions =
                   GetNumericalInstructions(available_instructions);
 
@@ -197,8 +201,8 @@
                 return;
               }
             } break;
-            case SpvOpIAdd:
-            case SpvOpISub: {
+            case spv::Op::OpIAdd:
+            case spv::Op::OpISub: {
               // Instructions of integer (scalar or vector) result type are
               // suitable for these opcodes.
               auto integer_instructions =
@@ -251,7 +255,7 @@
               }
               break;
             }
-            case SpvOpLogicalNot: {
+            case spv::Op::OpLogicalNot: {
               // Choose any available instruction of boolean scalar/vector
               // result type and equate its negation with a fresh id.
               auto boolean_instructions =
@@ -268,7 +272,7 @@
               }
               break;
             }
-            case SpvOpSNegate: {
+            case spv::Op::OpSNegate: {
               // Similar to OpLogicalNot, but for signed integer negation.
               auto integer_instructions =
                   GetIntegerInstructions(available_instructions);
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_function_calls.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_function_calls.cpp
index 033f4a2..70b8657 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_function_calls.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_function_calls.cpp
@@ -39,8 +39,8 @@
           -> void {
         // Check whether it is legitimate to insert a function call before the
         // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall,
-                                                          inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpFunctionCall, inst_it)) {
           return;
         }
 
@@ -112,8 +112,8 @@
   auto available_pointers = FindAvailableInstructions(
       caller_function, caller_block, caller_inst_it,
       [this, caller_block](opt::IRContext* /*unused*/, opt::Instruction* inst) {
-        if (inst->opcode() != SpvOpVariable ||
-            inst->opcode() != SpvOpFunctionParameter) {
+        if (inst->opcode() != spv::Op::OpVariable ||
+            inst->opcode() != spv::Op::OpFunctionParameter) {
           // Function parameters and variables are the only
           // kinds of pointer that can be used as actual
           // parameters.
@@ -172,15 +172,15 @@
     auto storage_class = param_type->AsPointer()->storage_class();
     auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
         GetIRContext(), param->type_id());
-    if (storage_class == SpvStorageClassFunction) {
+    if (storage_class == spv::StorageClass::Function) {
       // Add a new zero-initialized local variable to the current
       // function, noting that its pointee value is irrelevant.
       ApplyTransformation(TransformationAddLocalVariable(
           fresh_variable_id, param->type_id(), caller_function->result_id(),
           FindOrCreateZeroConstant(pointee_type_id, false), true));
     } else {
-      assert((storage_class == SpvStorageClassPrivate ||
-              storage_class == SpvStorageClassWorkgroup) &&
+      assert((storage_class == spv::StorageClass::Private ||
+              storage_class == spv::StorageClass::Workgroup) &&
              "Only Function, Private and Workgroup storage classes are "
              "supported at present.");
       // Add a new global variable to the module, zero-initializing it if
@@ -188,7 +188,7 @@
       // irrelevant.
       ApplyTransformation(TransformationAddGlobalVariable(
           fresh_variable_id, param->type_id(), storage_class,
-          storage_class == SpvStorageClassPrivate
+          storage_class == spv::StorageClass::Private
               ? FindOrCreateZeroConstant(pointee_type_id, false)
               : 0,
           true));
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_global_variables.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_global_variables.cpp
index 061f44d..4106856 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_global_variables.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_global_variables.cpp
@@ -29,16 +29,17 @@
                  transformations, ignore_inapplicable_transformations) {}
 
 void FuzzerPassAddGlobalVariables::Apply() {
-  SpvStorageClass variable_storage_class = SpvStorageClassPrivate;
+  spv::StorageClass variable_storage_class = spv::StorageClass::Private;
   for (auto& entry_point : GetIRContext()->module()->entry_points()) {
     // If the execution model of some entry point is GLCompute,
     // then the variable storage class may be Workgroup.
-    if (entry_point.GetSingleWordInOperand(0) == SpvExecutionModelGLCompute) {
+    if (spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) ==
+        spv::ExecutionModel::GLCompute) {
       variable_storage_class =
           GetFuzzerContext()->ChoosePercentage(
               GetFuzzerContext()->GetChanceOfChoosingWorkgroupStorageClass())
-              ? SpvStorageClassWorkgroup
-              : SpvStorageClassPrivate;
+              ? spv::StorageClass::Workgroup
+              : spv::StorageClass::Private;
       break;
     }
   }
@@ -87,7 +88,7 @@
     ApplyTransformation(TransformationAddGlobalVariable(
         GetFuzzerContext()->GetFreshId(), pointer_type_id,
         variable_storage_class,
-        variable_storage_class == SpvStorageClassPrivate
+        variable_storage_class == spv::StorageClass::Private
             ? FindOrCreateZeroConstant(basic_type, false)
             : 0,
         true));
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_loads.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_loads.cpp
index ab91543..3660328 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_loads.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_loads.cpp
@@ -34,10 +34,11 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            inst_it->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try inserting a load here.
         if (!GetFuzzerContext()->ChoosePercentage(
@@ -47,10 +48,11 @@
 
         // Check whether it is legitimate to insert a load or atomic load before
         // this instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
+                                                          inst_it)) {
           return;
         }
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAtomicLoad,
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpAtomicLoad,
                                                           inst_it)) {
           return;
         }
@@ -64,8 +66,8 @@
                     return false;
                   }
                   switch (instruction->opcode()) {
-                    case SpvOpConstantNull:
-                    case SpvOpUndef:
+                    case spv::Op::OpConstantNull:
+                    case spv::Op::OpUndef:
                       // Do not allow loading from a null or undefined pointer;
                       // this might be OK if the block is dead, but for now we
                       // conservatively avoid it.
@@ -75,7 +77,7 @@
                   }
                   return context->get_def_use_mgr()
                              ->GetDef(instruction->type_id())
-                             ->opcode() == SpvOpTypePointer;
+                             ->opcode() == spv::Op::OpTypePointer;
                 });
 
         // At this point, |relevant_instructions| contains all the pointers
@@ -92,25 +94,25 @@
         uint32_t memory_scope_id = 0;
         uint32_t memory_semantics_id = 0;
 
-        auto storage_class = static_cast<SpvStorageClass>(
+        auto storage_class = static_cast<spv::StorageClass>(
             GetIRContext()
                 ->get_def_use_mgr()
                 ->GetDef(chosen_instruction->type_id())
                 ->GetSingleWordInOperand(0));
 
         switch (storage_class) {
-          case SpvStorageClassStorageBuffer:
-          case SpvStorageClassPhysicalStorageBuffer:
-          case SpvStorageClassWorkgroup:
-          case SpvStorageClassCrossWorkgroup:
-          case SpvStorageClassAtomicCounter:
-          case SpvStorageClassImage:
+          case spv::StorageClass::StorageBuffer:
+          case spv::StorageClass::PhysicalStorageBuffer:
+          case spv::StorageClass::Workgroup:
+          case spv::StorageClass::CrossWorkgroup:
+          case spv::StorageClass::AtomicCounter:
+          case spv::StorageClass::Image:
             if (GetFuzzerContext()->ChoosePercentage(
                     GetFuzzerContext()->GetChanceOfAddingAtomicLoad())) {
               is_atomic_load = true;
 
               memory_scope_id = FindOrCreateConstant(
-                  {SpvScopeInvocation},
+                  {uint32_t(spv::Scope::Invocation)},
                   FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
                   false);
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_local_variables.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_local_variables.cpp
index a4e739f..f467f46 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_local_variables.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_local_variables.cpp
@@ -31,7 +31,7 @@
 
 void FuzzerPassAddLocalVariables::Apply() {
   auto basic_type_ids_and_pointers =
-      GetAvailableBasicTypesAndPointers(SpvStorageClassFunction);
+      GetAvailableBasicTypesAndPointers(spv::StorageClass::Function);
 
   // These are the basic types that are available to this fuzzer pass.
   auto& basic_types = basic_type_ids_and_pointers.first;
@@ -64,7 +64,7 @@
         // use it.
         pointer_type = GetFuzzerContext()->GetFreshId();
         ApplyTransformation(TransformationAddTypePointer(
-            pointer_type, SpvStorageClassFunction, basic_type));
+            pointer_type, spv::StorageClass::Function, basic_type));
         available_pointers_to_basic_type.push_back(pointer_type);
       } else {
         // There is - grab one.
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
index 73b6b0a..d0b1275 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
@@ -176,8 +176,8 @@
     // - OpFunction does not yield a value;
     // - OpUndef yields an undefined value at each use, so it should never be a
     //   synonym of another id.
-    if (pair.second->opcode() == SpvOpFunction ||
-        pair.second->opcode() == SpvOpUndef) {
+    if (pair.second->opcode() == spv::Op::OpFunction ||
+        pair.second->opcode() == spv::Op::OpUndef) {
       continue;
     }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_parameters.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_parameters.cpp
index 1cb6a79..e663d89 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_parameters.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_parameters.cpp
@@ -79,7 +79,7 @@
         auto storage_class = fuzzerutil::GetStorageClassFromPointerType(
             GetIRContext(), current_type_id);
         switch (storage_class) {
-          case SpvStorageClassFunction: {
+          case spv::StorageClass::Function: {
             // In every caller find or create a local variable that has the
             // selected type.
             for (auto* instr :
@@ -91,8 +91,8 @@
               call_parameter_ids[instr->result_id()] = variable_id;
             }
           } break;
-          case SpvStorageClassPrivate:
-          case SpvStorageClassWorkgroup: {
+          case spv::StorageClass::Private:
+          case spv::StorageClass::Workgroup: {
             // If there exists at least one caller, find or create a global
             // variable that has the selected type.
             std::vector<opt::Instruction*> callers =
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_stores.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_stores.cpp
index 606e4a6..0de02a5 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_stores.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_stores.cpp
@@ -34,10 +34,11 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            inst_it->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try inserting a store here.
         if (!GetFuzzerContext()->ChoosePercentage(
@@ -47,12 +48,12 @@
 
         // Check whether it is legitimate to insert a store before this
         // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpStore,
                                                           inst_it)) {
           return;
         }
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAtomicStore,
-                                                          inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpAtomicStore, inst_it)) {
           return;
         }
 
@@ -67,7 +68,7 @@
                   }
                   auto type_inst = context->get_def_use_mgr()->GetDef(
                       instruction->type_id());
-                  if (type_inst->opcode() != SpvOpTypePointer) {
+                  if (type_inst->opcode() != spv::Op::OpTypePointer) {
                     // Not a pointer.
                     return false;
                   }
@@ -76,8 +77,8 @@
                     return false;
                   }
                   switch (instruction->opcode()) {
-                    case SpvOpConstantNull:
-                    case SpvOpUndef:
+                    case spv::Op::OpConstantNull:
+                    case spv::Op::OpUndef:
                       // Do not allow storing to a null or undefined pointer;
                       // this might be OK if the block is dead, but for now we
                       // conservatively avoid it.
@@ -126,24 +127,24 @@
         uint32_t memory_semantics_id = 0;
 
         auto storage_class =
-            static_cast<SpvStorageClass>(GetIRContext()
-                                             ->get_def_use_mgr()
-                                             ->GetDef(pointer->type_id())
-                                             ->GetSingleWordInOperand(0));
+            static_cast<spv::StorageClass>(GetIRContext()
+                                               ->get_def_use_mgr()
+                                               ->GetDef(pointer->type_id())
+                                               ->GetSingleWordInOperand(0));
 
         switch (storage_class) {
-          case SpvStorageClassStorageBuffer:
-          case SpvStorageClassPhysicalStorageBuffer:
-          case SpvStorageClassWorkgroup:
-          case SpvStorageClassCrossWorkgroup:
-          case SpvStorageClassAtomicCounter:
-          case SpvStorageClassImage:
+          case spv::StorageClass::StorageBuffer:
+          case spv::StorageClass::PhysicalStorageBuffer:
+          case spv::StorageClass::Workgroup:
+          case spv::StorageClass::CrossWorkgroup:
+          case spv::StorageClass::AtomicCounter:
+          case spv::StorageClass::Image:
             if (GetFuzzerContext()->ChoosePercentage(
                     GetFuzzerContext()->GetChanceOfAddingAtomicStore())) {
               is_atomic_store = true;
 
               memory_scope_id = FindOrCreateConstant(
-                  {SpvScopeInvocation},
+                  {uint32_t(spv::Scope::Invocation)},
                   FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
                   false);
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_synonyms.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_synonyms.cpp
index 1d188de..5782732 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_synonyms.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_synonyms.cpp
@@ -44,7 +44,8 @@
         // Skip |inst_it| if we can't insert anything above it. OpIAdd is just
         // a representative of some instruction that might be produced by the
         // transformation.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd, inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
+                                                          inst_it)) {
           return;
         }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
index a29d1d3..4cddf55 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
@@ -35,10 +35,11 @@
              opt::BasicBlock::iterator instruction_iterator,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(instruction_iterator->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            instruction_iterator->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try adding an OpVectorShuffle instruction.
         if (!GetFuzzerContext()->ChoosePercentage(
@@ -49,7 +50,7 @@
         // It must be valid to insert an OpVectorShuffle instruction
         // before |instruction_iterator|.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpVectorShuffle, instruction_iterator)) {
+                spv::Op::OpVectorShuffle, instruction_iterator)) {
           return;
         }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
index 94428f7..6bf46e1 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
@@ -33,7 +33,7 @@
   // For all OpBranchConditional instructions,
   // randomly applies the transformation.
   GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
-    if (instruction->opcode() == SpvOpBranchConditional &&
+    if (instruction->opcode() == spv::Op::OpBranchConditional &&
         GetFuzzerContext()->ChoosePercentage(
             GetFuzzerContext()->GetChanceOfAdjustingBranchWeights())) {
       ApplyTransformation(TransformationAdjustBranchWeights(
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
index 1c2bc8c..363edc7 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
@@ -40,21 +40,21 @@
       // For the new mask, we first randomly select one of three basic masks:
       // None, Inline or DontInline.  These are always valid (and are mutually
       // exclusive).
-      std::vector<uint32_t> basic_function_control_masks = {
-          SpvFunctionControlMaskNone, SpvFunctionControlInlineMask,
-          SpvFunctionControlDontInlineMask};
+      std::vector<spv::FunctionControlMask> basic_function_control_masks = {
+          spv::FunctionControlMask::MaskNone, spv::FunctionControlMask::Inline,
+          spv::FunctionControlMask::DontInline};
       uint32_t new_function_control_mask =
-          basic_function_control_masks[GetFuzzerContext()->RandomIndex(
-              basic_function_control_masks)];
+          uint32_t(basic_function_control_masks[GetFuzzerContext()->RandomIndex(
+              basic_function_control_masks)]);
 
       // We now consider the Pure and Const mask bits.  If these are already
       // set on the function then it's OK to keep them, but also interesting
       // to consider dropping them, so we decide randomly in each case.
       for (auto mask_bit :
-           {SpvFunctionControlPureMask, SpvFunctionControlConstMask}) {
-        if ((existing_function_control_mask & mask_bit) &&
+           {spv::FunctionControlMask::Pure, spv::FunctionControlMask::Const}) {
+        if ((existing_function_control_mask & uint32_t(mask_bit)) &&
             GetFuzzerContext()->ChooseEven()) {
-          new_function_control_mask |= mask_bit;
+          new_function_control_mask |= uint32_t(mask_bit);
         }
       }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
index fe855ca..53dbe54 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
@@ -34,7 +34,7 @@
     for (auto& block : function) {
       if (auto merge_inst = block.GetMergeInst()) {
         // Ignore the instruction if it is not a loop merge.
-        if (merge_inst->opcode() != SpvOpLoopMerge) {
+        if (merge_inst->opcode() != spv::Op::OpLoopMerge) {
           continue;
         }
 
@@ -48,9 +48,10 @@
             TransformationSetLoopControl::kLoopControlMaskInOperandIndex);
 
         // First, set the new mask to one of None, Unroll or DontUnroll.
-        std::vector<uint32_t> basic_masks = {SpvLoopControlMaskNone,
-                                             SpvLoopControlUnrollMask,
-                                             SpvLoopControlDontUnrollMask};
+        std::vector<uint32_t> basic_masks = {
+            uint32_t(spv::LoopControlMask::MaskNone),
+            uint32_t(spv::LoopControlMask::Unroll),
+            uint32_t(spv::LoopControlMask::DontUnroll)};
         uint32_t new_mask =
             basic_masks[GetFuzzerContext()->RandomIndex(basic_masks)];
 
@@ -58,19 +59,20 @@
         // does, check which of these were present in the existing mask and
         // randomly decide whether to keep them.  They are just hints, so
         // removing them should not change the semantics of the module.
-        for (auto mask_bit :
-             {SpvLoopControlDependencyInfiniteMask,
-              SpvLoopControlDependencyLengthMask,
-              SpvLoopControlMinIterationsMask, SpvLoopControlMaxIterationsMask,
-              SpvLoopControlIterationMultipleMask}) {
-          if ((existing_mask & mask_bit) && GetFuzzerContext()->ChooseEven()) {
+        for (auto mask_bit : {spv::LoopControlMask::DependencyInfinite,
+                              spv::LoopControlMask::DependencyLength,
+                              spv::LoopControlMask::MinIterations,
+                              spv::LoopControlMask::MaxIterations,
+                              spv::LoopControlMask::IterationMultiple}) {
+          if ((existing_mask & uint32_t(mask_bit)) &&
+              GetFuzzerContext()->ChooseEven()) {
             // The mask bits we are considering are not available in all SPIR-V
             // versions.  However, we only include a mask bit if it was present
             // in the original loop control mask, and we work under the
             // assumption that we are transforming a valid module, thus we don't
             // need to actually check whether the SPIR-V version being used
             // supports these loop control mask bits.
-            new_mask |= mask_bit;
+            new_mask |= uint32_t(mask_bit);
           }
         }
 
@@ -81,14 +83,14 @@
 
         // PeelCount and PartialCount are not compatible with DontUnroll, so
         // we check whether DontUnroll is set.
-        if (!(new_mask & SpvLoopControlDontUnrollMask)) {
+        if (!(new_mask & uint32_t(spv::LoopControlMask::DontUnroll))) {
           // If PeelCount is supported by this SPIR-V version, randomly choose
           // whether to set it.  If it was set in the original mask and is not
           // selected for setting here, that amounts to dropping it.
           if (TransformationSetLoopControl::PeelCountIsSupported(
                   GetIRContext()) &&
               GetFuzzerContext()->ChooseEven()) {
-            new_mask |= SpvLoopControlPeelCountMask;
+            new_mask |= uint32_t(spv::LoopControlMask::PeelCount);
             // The peel count is chosen randomly - if PeelCount was already set
             // this will overwrite whatever peel count was previously used.
             peel_count = GetFuzzerContext()->GetRandomLoopControlPeelCount();
@@ -97,7 +99,7 @@
           if (TransformationSetLoopControl::PartialCountIsSupported(
                   GetIRContext()) &&
               GetFuzzerContext()->ChooseEven()) {
-            new_mask |= SpvLoopControlPartialCountMask;
+            new_mask |= uint32_t(spv::LoopControlMask::PartialCount);
             partial_count =
                 GetFuzzerContext()->GetRandomLoopControlPartialCount();
           }
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
index d2ff40e..efae7d6 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
@@ -47,8 +47,8 @@
         // From SPIR-V 1.4 onwards, OpCopyMemory and OpCopyMemorySized have a
         // second mask.
         switch (inst_it->opcode()) {
-          case SpvOpCopyMemory:
-          case SpvOpCopyMemorySized:
+          case spv::Op::OpCopyMemory:
+          case spv::Op::OpCopyMemorySized:
             if (TransformationSetMemoryOperandsMask::
                     MultipleMemoryOperandMasksAreSupported(GetIRContext())) {
               indices_of_available_masks_to_adjust.push_back(1);
@@ -75,24 +75,26 @@
               existing_mask_in_operand_index < inst_it->NumInOperands()
                   ? inst_it->GetSingleWordInOperand(
                         existing_mask_in_operand_index)
-                  : static_cast<uint32_t>(SpvMemoryAccessMaskNone);
+                  : static_cast<uint32_t>(spv::MemoryAccessMask::MaskNone);
 
           // There are two things we can do to a mask:
           // - add Volatile if not already present
           // - toggle Nontemporal
           // The following ensures that we do at least one of these
-          bool add_volatile = !(existing_mask & SpvMemoryAccessVolatileMask) &&
-                              GetFuzzerContext()->ChooseEven();
+          bool add_volatile =
+              !(existing_mask & uint32_t(spv::MemoryAccessMask::Volatile)) &&
+              GetFuzzerContext()->ChooseEven();
           bool toggle_nontemporal =
               !add_volatile || GetFuzzerContext()->ChooseEven();
 
           // These bitwise operations use '|' to add Volatile if desired, and
           // '^' to toggle Nontemporal if desired.
           uint32_t new_mask =
-              (existing_mask | (add_volatile ? SpvMemoryAccessVolatileMask
-                                             : SpvMemoryAccessMaskNone)) ^
-              (toggle_nontemporal ? SpvMemoryAccessNontemporalMask
-                                  : SpvMemoryAccessMaskNone);
+              (existing_mask |
+               (add_volatile ? uint32_t(spv::MemoryAccessMask::Volatile)
+                             : uint32_t(spv::MemoryAccessMask::MaskNone))) ^
+              (toggle_nontemporal ? uint32_t(spv::MemoryAccessMask::Nontemporal)
+                                  : uint32_t(spv::MemoryAccessMask::MaskNone));
 
           TransformationSetMemoryOperandsMask transformation(
               MakeInstructionDescriptor(block, inst_it), new_mask, mask_index);
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
index 7d8e6b5..fe0cf7a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
@@ -34,7 +34,7 @@
     for (auto& block : function) {
       if (auto merge_inst = block.GetMergeInst()) {
         // Ignore the instruction if it is not a selection merge.
-        if (merge_inst->opcode() != SpvOpSelectionMerge) {
+        if (merge_inst->opcode() != spv::Op::OpSelectionMerge) {
           continue;
         }
 
@@ -48,13 +48,14 @@
         // The choices to change the selection control to are the set of valid
         // controls, minus the current control.
         std::vector<uint32_t> choices;
-        for (auto control :
-             {SpvSelectionControlMaskNone, SpvSelectionControlFlattenMask,
-              SpvSelectionControlDontFlattenMask}) {
-          if (control == merge_inst->GetSingleWordOperand(1)) {
+        for (auto control : {spv::SelectionControlMask::MaskNone,
+                             spv::SelectionControlMask::Flatten,
+                             spv::SelectionControlMask::DontFlatten}) {
+          if (control ==
+              spv::SelectionControlMask(merge_inst->GetSingleWordOperand(1))) {
             continue;
           }
-          choices.push_back(control);
+          choices.push_back(uint32_t(control));
         }
 
         // Apply the transformation and add it to the output transformation
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
index 5c3b86b..0367a26 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
@@ -107,9 +107,9 @@
         // which case we need to be able to add an extract instruction to get
         // that element out.
         if (synonym_to_try->index_size() > 0 &&
-            !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                          use_inst) &&
-            use_inst->opcode() != SpvOpPhi) {
+            !fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpCompositeExtract, use_inst) &&
+            use_inst->opcode() != spv::Op::OpPhi) {
           // We cannot insert an extract before this instruction, so this
           // synonym is no good.
           continue;
@@ -132,7 +132,7 @@
           id_with_which_to_replace_use = GetFuzzerContext()->GetFreshId();
           opt::Instruction* instruction_to_insert_before = nullptr;
 
-          if (use_inst->opcode() != SpvOpPhi) {
+          if (use_inst->opcode() != spv::Op::OpPhi) {
             instruction_to_insert_before = use_inst;
           } else {
             auto parent_block_id =
@@ -182,7 +182,7 @@
 }
 
 bool FuzzerPassApplyIdSynonyms::DataDescriptorsHaveCompatibleTypes(
-    SpvOp opcode, uint32_t use_in_operand_index,
+    spv::Op opcode, uint32_t use_in_operand_index,
     const protobufs::DataDescriptor& dd1,
     const protobufs::DataDescriptor& dd2) {
   auto base_object_type_id_1 =
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_apply_id_synonyms.h b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_apply_id_synonyms.h
index 3da9c5d..d1a0e1a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_apply_id_synonyms.h
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_apply_id_synonyms.h
@@ -38,7 +38,7 @@
   // with respect to the type. Concretely, returns true if |dd1| and |dd2| have
   // the same type or both |dd1| and |dd2| are either a numerical or a vector
   // type of integral components with possibly different signedness.
-  bool DataDescriptorsHaveCompatibleTypes(SpvOp opcode,
+  bool DataDescriptorsHaveCompatibleTypes(spv::Op opcode,
                                           uint32_t use_in_operand_index,
                                           const protobufs::DataDescriptor& dd1,
                                           const protobufs::DataDescriptor& dd2);
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_construct_composites.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_construct_composites.cpp
index ff022fc..0ad630c 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_construct_composites.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_construct_composites.cpp
@@ -81,7 +81,7 @@
         // Check whether it is legitimate to insert a composite construction
         // before the instruction.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpCompositeConstruct, inst_it)) {
+                spv::Op::OpCompositeConstruct, inst_it)) {
           return;
         }
 
@@ -121,19 +121,19 @@
         auto composite_type_inst =
             GetIRContext()->get_def_use_mgr()->GetDef(chosen_composite_type);
         switch (composite_type_inst->opcode()) {
-          case SpvOpTypeArray:
+          case spv::Op::OpTypeArray:
             constructor_arguments = FindComponentsToConstructArray(
                 *composite_type_inst, type_id_to_available_instructions);
             break;
-          case SpvOpTypeMatrix:
+          case spv::Op::OpTypeMatrix:
             constructor_arguments = FindComponentsToConstructMatrix(
                 *composite_type_inst, type_id_to_available_instructions);
             break;
-          case SpvOpTypeStruct:
+          case spv::Op::OpTypeStruct:
             constructor_arguments = FindComponentsToConstructStruct(
                 *composite_type_inst, type_id_to_available_instructions);
             break;
-          case SpvOpTypeVector:
+          case spv::Op::OpTypeVector:
             constructor_arguments = FindComponentsToConstructVector(
                 *composite_type_inst, type_id_to_available_instructions);
             break;
@@ -156,7 +156,7 @@
 FuzzerPassConstructComposites::FindComponentsToConstructArray(
     const opt::Instruction& array_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  assert(array_type_instruction.opcode() == SpvOpTypeArray &&
+  assert(array_type_instruction.opcode() == spv::Op::OpTypeArray &&
          "Precondition: instruction must be an array type.");
 
   // Get the element type for the array.
@@ -191,7 +191,7 @@
 FuzzerPassConstructComposites::FindComponentsToConstructMatrix(
     const opt::Instruction& matrix_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  assert(matrix_type_instruction.opcode() == SpvOpTypeMatrix &&
+  assert(matrix_type_instruction.opcode() == spv::Op::OpTypeMatrix &&
          "Precondition: instruction must be a matrix type.");
 
   // Get the element type for the matrix.
@@ -221,7 +221,7 @@
 FuzzerPassConstructComposites::FindComponentsToConstructStruct(
     const opt::Instruction& struct_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  assert(struct_type_instruction.opcode() == SpvOpTypeStruct &&
+  assert(struct_type_instruction.opcode() == spv::Op::OpTypeStruct &&
          "Precondition: instruction must be a struct type.");
   std::vector<uint32_t> result;
   // Consider the type of each field of the struct.
@@ -251,7 +251,7 @@
 FuzzerPassConstructComposites::FindComponentsToConstructVector(
     const opt::Instruction& vector_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  assert(vector_type_instruction.opcode() == SpvOpTypeVector &&
+  assert(vector_type_instruction.opcode() == spv::Op::OpTypeVector &&
          "Precondition: instruction must be a vector type.");
 
   // Get details of the type underlying the vector, and the width of the vector,
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_copy_objects.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_copy_objects.cpp
index 80cc2a5..725c33e 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_copy_objects.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_copy_objects.cpp
@@ -35,10 +35,11 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            inst_it->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         if (GetTransformationContext()->GetFactManager()->BlockIsDead(
                 block->id())) {
@@ -48,7 +49,7 @@
 
         // Check whether it is legitimate to insert a copy before this
         // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyObject,
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyObject,
                                                           inst_it)) {
           return;
         }
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_donate_modules.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_donate_modules.cpp
index 29ede58..1696c74 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_donate_modules.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_donate_modules.cpp
@@ -88,7 +88,7 @@
   // module.
   for (const auto& capability_inst : donor_ir_context->capabilities()) {
     auto capability =
-        static_cast<SpvCapability>(capability_inst.GetSingleWordInOperand(0));
+        static_cast<spv::Capability>(capability_inst.GetSingleWordInOperand(0));
     if (!GetIRContext()->get_feature_mgr()->HasCapability(capability)) {
       return;
     }
@@ -122,27 +122,27 @@
   //  kinds of decoration.
 }
 
-SpvStorageClass FuzzerPassDonateModules::AdaptStorageClass(
-    SpvStorageClass donor_storage_class) {
+spv::StorageClass FuzzerPassDonateModules::AdaptStorageClass(
+    spv::StorageClass donor_storage_class) {
   switch (donor_storage_class) {
-    case SpvStorageClassFunction:
-    case SpvStorageClassPrivate:
-    case SpvStorageClassWorkgroup:
+    case spv::StorageClass::Function:
+    case spv::StorageClass::Private:
+    case spv::StorageClass::Workgroup:
       // We leave these alone
       return donor_storage_class;
-    case SpvStorageClassInput:
-    case SpvStorageClassOutput:
-    case SpvStorageClassUniform:
-    case SpvStorageClassUniformConstant:
-    case SpvStorageClassPushConstant:
-    case SpvStorageClassImage:
-    case SpvStorageClassStorageBuffer:
+    case spv::StorageClass::Input:
+    case spv::StorageClass::Output:
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::UniformConstant:
+    case spv::StorageClass::PushConstant:
+    case spv::StorageClass::Image:
+    case spv::StorageClass::StorageBuffer:
       // We change these to Private
-      return SpvStorageClassPrivate;
+      return spv::StorageClass::Private;
     default:
       // Handle other cases on demand.
       assert(false && "Currently unsupported storage class.");
-      return SpvStorageClassMax;
+      return spv::StorageClass::Max;
   }
 }
 
@@ -200,14 +200,14 @@
   // that its component types will have been considered previously, and that
   // |original_id_to_donated_id| will already contain an entry for them.
   switch (type_or_value.opcode()) {
-    case SpvOpTypeImage:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeSampler:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
       // We do not donate types and variables that relate to images and
       // samplers, so we skip these types and subsequently skip anything that
       // depends on them.
       return;
-    case SpvOpTypeVoid: {
+    case spv::Op::OpTypeVoid: {
       // Void has to exist already in order for us to have an entry point.
       // Get the existing id of void.
       opt::analysis::Void void_type;
@@ -216,7 +216,7 @@
              "The module being transformed will always have 'void' type "
              "declared.");
     } break;
-    case SpvOpTypeBool: {
+    case spv::Op::OpTypeBool: {
       // Bool cannot be declared multiple times, so use its existing id if
       // present, or add a declaration of Bool with a fresh id if not.
       opt::analysis::Bool bool_type;
@@ -228,7 +228,7 @@
         ApplyTransformation(TransformationAddTypeBoolean(new_result_id));
       }
     } break;
-    case SpvOpTypeInt: {
+    case spv::Op::OpTypeInt: {
       // Int cannot be declared multiple times with the same width and
       // signedness, so check whether an existing identical Int type is
       // present and use its id if so.  Otherwise add a declaration of the
@@ -246,8 +246,8 @@
             TransformationAddTypeInt(new_result_id, width, is_signed));
       }
     } break;
-    case SpvOpTypeFloat: {
-      // Similar to SpvOpTypeInt.
+    case spv::Op::OpTypeFloat: {
+      // Similar to spv::Op::OpTypeInt.
       const uint32_t width = type_or_value.GetSingleWordInOperand(0);
       opt::analysis::Float float_type(width);
       auto float_type_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
@@ -258,7 +258,7 @@
         ApplyTransformation(TransformationAddTypeFloat(new_result_id, width));
       }
     } break;
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       // It is not legal to have two Vector type declarations with identical
       // element types and element counts, so check whether an existing
       // identical Vector type is present and use its id if so.  Otherwise add
@@ -282,8 +282,8 @@
             new_result_id, component_type_id, component_count));
       }
     } break;
-    case SpvOpTypeMatrix: {
-      // Similar to SpvOpTypeVector.
+    case spv::Op::OpTypeMatrix: {
+      // Similar to spv::Op::OpTypeVector.
       uint32_t column_type_id = original_id_to_donated_id->at(
           type_or_value.GetSingleWordInOperand(0));
       auto column_type =
@@ -302,7 +302,7 @@
       }
 
     } break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       // It is OK to have multiple structurally identical array types, so
       // we go ahead and add a remapped version of the type declared by the
       // donor.
@@ -318,7 +318,7 @@
           original_id_to_donated_id->at(
               type_or_value.GetSingleWordInOperand(1))));
     } break;
-    case SpvOpTypeRuntimeArray: {
+    case spv::Op::OpTypeRuntimeArray: {
       // A runtime array is allowed as the final member of an SSBO.  During
       // donation we turn runtime arrays into fixed-size arrays.  For dead
       // code donations this is OK because the array is never indexed into at
@@ -341,8 +341,8 @@
               {GetFuzzerContext()->GetRandomSizeForNewArray()}, 32, false,
               false)));
     } break;
-    case SpvOpTypeStruct: {
-      // Similar to SpvOpTypeArray.
+    case spv::Op::OpTypeStruct: {
+      // Similar to spv::Op::OpTypeArray.
       std::vector<uint32_t> member_type_ids;
       for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) {
         auto component_type_id = type_or_value.GetSingleWordInOperand(i);
@@ -358,8 +358,8 @@
       ApplyTransformation(
           TransformationAddTypeStruct(new_result_id, member_type_ids));
     } break;
-    case SpvOpTypePointer: {
-      // Similar to SpvOpTypeArray.
+    case spv::Op::OpTypePointer: {
+      // Similar to spv::Op::OpTypeArray.
       uint32_t pointee_type_id = type_or_value.GetSingleWordInOperand(1);
       if (!original_id_to_donated_id->count(pointee_type_id)) {
         // We did not donate the pointee type for this pointer type, so we
@@ -369,11 +369,11 @@
       new_result_id = GetFuzzerContext()->GetFreshId();
       ApplyTransformation(TransformationAddTypePointer(
           new_result_id,
-          AdaptStorageClass(static_cast<SpvStorageClass>(
+          AdaptStorageClass(static_cast<spv::StorageClass>(
               type_or_value.GetSingleWordInOperand(0))),
           original_id_to_donated_id->at(pointee_type_id)));
     } break;
-    case SpvOpTypeFunction: {
+    case spv::Op::OpTypeFunction: {
       // It is not OK to have multiple function types that use identical ids
       // for their return and parameter types.  We thus go through all
       // existing function types to look for a match.  We do not use the
@@ -425,10 +425,11 @@
             argument_type_ids));
       }
     } break;
-    case SpvOpSpecConstantOp: {
+    case spv::Op::OpSpecConstantOp: {
       new_result_id = GetFuzzerContext()->GetFreshId();
       auto type_id = original_id_to_donated_id->at(type_or_value.type_id());
-      auto opcode = static_cast<SpvOp>(type_or_value.GetSingleWordInOperand(0));
+      auto opcode =
+          static_cast<spv::Op>(type_or_value.GetSingleWordInOperand(0));
 
       // Make sure we take into account |original_id_to_donated_id| when
       // computing operands for OpSpecConstantOp.
@@ -447,20 +448,20 @@
       ApplyTransformation(TransformationAddSpecConstantOp(
           new_result_id, type_id, opcode, std::move(operands)));
     } break;
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
-    case SpvOpConstantTrue:
-    case SpvOpConstantFalse: {
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstantFalse: {
       // It is OK to have duplicate definitions of True and False, so add
       // these to the module, using a remapped Bool type.
       new_result_id = GetFuzzerContext()->GetFreshId();
-      auto value = type_or_value.opcode() == SpvOpConstantTrue ||
-                   type_or_value.opcode() == SpvOpSpecConstantTrue;
+      auto value = type_or_value.opcode() == spv::Op::OpConstantTrue ||
+                   type_or_value.opcode() == spv::Op::OpSpecConstantTrue;
       ApplyTransformation(
           TransformationAddConstantBoolean(new_result_id, value, false));
     } break;
-    case SpvOpSpecConstant:
-    case SpvOpConstant: {
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpConstant: {
       // It is OK to have duplicate constant definitions, so add this to the
       // module using a remapped result type.
       new_result_id = GetFuzzerContext()->GetFreshId();
@@ -472,8 +473,8 @@
           new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
           data_words, false));
     } break;
-    case SpvOpSpecConstantComposite:
-    case SpvOpConstantComposite: {
+    case spv::Op::OpSpecConstantComposite:
+    case spv::Op::OpConstantComposite: {
       assert(original_id_to_donated_id->count(type_or_value.type_id()) &&
              "Composite types for which it is possible to create a constant "
              "should have been donated.");
@@ -495,7 +496,7 @@
           new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
           constituent_ids, false));
     } break;
-    case SpvOpConstantNull: {
+    case spv::Op::OpConstantNull: {
       if (!original_id_to_donated_id->count(type_or_value.type_id())) {
         // We did not donate the type associated with this null constant, so
         // we cannot donate the null constant.
@@ -509,7 +510,7 @@
           new_result_id,
           original_id_to_donated_id->at(type_or_value.type_id())));
     } break;
-    case SpvOpVariable: {
+    case spv::Op::OpVariable: {
       if (!original_id_to_donated_id->count(type_or_value.type_id())) {
         // We did not donate the pointer type associated with this variable,
         // so we cannot donate the variable.
@@ -536,11 +537,11 @@
       uint32_t remapped_pointer_type =
           original_id_to_donated_id->at(type_or_value.type_id());
       uint32_t initializer_id;
-      SpvStorageClass storage_class =
-          static_cast<SpvStorageClass>(type_or_value.GetSingleWordInOperand(
-              0)) == SpvStorageClassWorkgroup
-              ? SpvStorageClassWorkgroup
-              : SpvStorageClassPrivate;
+      spv::StorageClass storage_class =
+          static_cast<spv::StorageClass>(type_or_value.GetSingleWordInOperand(
+              0)) == spv::StorageClass::Workgroup
+              ? spv::StorageClass::Workgroup
+              : spv::StorageClass::Private;
       if (type_or_value.NumInOperands() == 1) {
         // The variable did not have an initializer.  Initialize it to zero
         // if it has Private storage class (to limit problems associated with
@@ -551,7 +552,7 @@
         //  could initialize Workgroup variables at the start of an entry
         //  point, and should do so if their uninitialized nature proves
         //  problematic.
-        initializer_id = storage_class == SpvStorageClassWorkgroup
+        initializer_id = storage_class == spv::StorageClass::Workgroup
                              ? 0
                              : FindOrCreateZeroConstant(
                                    fuzzerutil::GetPointeeTypeIdFromPointerType(
@@ -566,7 +567,7 @@
           TransformationAddGlobalVariable(new_result_id, remapped_pointer_type,
                                           storage_class, initializer_id, true));
     } break;
-    case SpvOpUndef: {
+    case spv::Op::OpUndef: {
       if (!original_id_to_donated_id->count(type_or_value.type_id())) {
         // We did not donate the type associated with this undef, so we cannot
         // donate the undef.
@@ -638,7 +639,7 @@
         [this, &donated_instructions, donor_ir_context,
          &original_id_to_donated_id,
          &skipped_instructions](const opt::Instruction* instruction) {
-          if (instruction->opcode() == SpvOpArrayLength) {
+          if (instruction->opcode() == spv::Op::OpArrayLength) {
             // We treat OpArrayLength specially.
             HandleOpArrayLength(*instruction, original_id_to_donated_id,
                                 &donated_instructions);
@@ -682,70 +683,70 @@
   // Now consider instructions we specifically want to skip because we do not
   // yet support them.
   switch (instruction.opcode()) {
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
       // We conservatively ignore all atomic instructions at present.
       // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3276): Consider
       //  being less conservative here.
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageRead:
-    case SpvOpImageWrite:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseRead:
-    case SpvOpImageSampleFootprintNV:
-    case SpvOpImage:
-    case SpvOpImageQueryFormat:
-    case SpvOpImageQueryLevels:
-    case SpvOpImageQueryLod:
-    case SpvOpImageQueryOrder:
-    case SpvOpImageQuerySamples:
-    case SpvOpImageQuerySize:
-    case SpvOpImageQuerySizeLod:
-    case SpvOpSampledImage:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageWrite:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseRead:
+    case spv::Op::OpImageSampleFootprintNV:
+    case spv::Op::OpImage:
+    case spv::Op::OpImageQueryFormat:
+    case spv::Op::OpImageQueryLevels:
+    case spv::Op::OpImageQueryLod:
+    case spv::Op::OpImageQueryOrder:
+    case spv::Op::OpImageQuerySamples:
+    case spv::Op::OpImageQuerySize:
+    case spv::Op::OpImageQuerySizeLod:
+    case spv::Op::OpSampledImage:
       // We ignore all instructions related to accessing images, since we do not
       // donate images.
       return false;
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       switch (donor_ir_context->get_def_use_mgr()
                   ->GetDef(instruction.type_id())
                   ->opcode()) {
-        case SpvOpTypeImage:
-        case SpvOpTypeSampledImage:
-        case SpvOpTypeSampler:
+        case spv::Op::OpTypeImage:
+        case spv::Op::OpTypeSampledImage:
+        case spv::Op::OpTypeSampler:
           // Again, we ignore instructions that relate to accessing images.
           return false;
         default:
@@ -783,13 +784,13 @@
 bool FuzzerPassDonateModules::IsBasicType(
     const opt::Instruction& instruction) const {
   switch (instruction.opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeBool:
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeStruct:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeStruct:
+    case spv::Op::OpTypeVector:
       return true;
     default:
       return false;
@@ -800,7 +801,7 @@
     const opt::Instruction& instruction,
     std::map<uint32_t, uint32_t>* original_id_to_donated_id,
     std::vector<protobufs::Instruction>* donated_instructions) const {
-  assert(instruction.opcode() == SpvOpArrayLength &&
+  assert(instruction.opcode() == spv::Op::OpArrayLength &&
          "Precondition: instruction must be OpArrayLength.");
   uint32_t donated_variable_id =
       original_id_to_donated_id->at(instruction.GetSingleWordInOperand(0));
@@ -809,12 +810,12 @@
   auto pointer_to_struct_instruction =
       GetIRContext()->get_def_use_mgr()->GetDef(
           donated_variable_instruction->type_id());
-  assert(pointer_to_struct_instruction->opcode() == SpvOpTypePointer &&
+  assert(pointer_to_struct_instruction->opcode() == spv::Op::OpTypePointer &&
          "Type of variable must be pointer.");
   auto donated_struct_type_instruction =
       GetIRContext()->get_def_use_mgr()->GetDef(
           pointer_to_struct_instruction->GetSingleWordInOperand(1));
-  assert(donated_struct_type_instruction->opcode() == SpvOpTypeStruct &&
+  assert(donated_struct_type_instruction->opcode() == spv::Op::OpTypeStruct &&
          "Pointee type of pointer used by OpArrayLength must be struct.");
   assert(donated_struct_type_instruction->NumInOperands() ==
              instruction.GetSingleWordInOperand(1) + 1 &&
@@ -825,7 +826,7 @@
           donated_struct_type_instruction->NumInOperands() - 1);
   auto fixed_size_array_type_instruction =
       GetIRContext()->get_def_use_mgr()->GetDef(fixed_size_array_type_id);
-  assert(fixed_size_array_type_instruction->opcode() == SpvOpTypeArray &&
+  assert(fixed_size_array_type_instruction->opcode() == spv::Op::OpTypeArray &&
          "The donated array type must be fixed-size.");
   auto array_size_id =
       fixed_size_array_type_instruction->GetSingleWordInOperand(1);
@@ -837,7 +838,8 @@
   }
 
   donated_instructions->push_back(MakeInstructionMessage(
-      SpvOpCopyObject, original_id_to_donated_id->at(instruction.type_id()),
+      spv::Op::OpCopyObject,
+      original_id_to_donated_id->at(instruction.type_id()),
       original_id_to_donated_id->at(instruction.result_id()),
       opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {array_size_id}}})));
 }
@@ -892,7 +894,7 @@
   // more interesting value later.
   auto zero_constant = FindOrCreateZeroConstant(remapped_type_id, true);
   donated_instructions->push_back(MakeInstructionMessage(
-      SpvOpCopyObject, remapped_type_id,
+      spv::Op::OpCopyObject, remapped_type_id,
       original_id_to_donated_id->at(instruction.result_id()),
       opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {zero_constant}}})));
 }
@@ -926,8 +928,8 @@
         (void)(donor_ir_context);
         assert((donor_ir_context->get_def_use_mgr()
                         ->GetDef(operand_id)
-                        ->opcode() == SpvOpLabel ||
-                instruction.opcode() == SpvOpPhi) &&
+                        ->opcode() == spv::Op::OpLabel ||
+                instruction.opcode() == spv::Op::OpPhi) &&
                "Unsupported forward reference.");
         original_id_to_donated_id->insert(
             {operand_id, GetFuzzerContext()->GetFreshId()});
@@ -942,7 +944,7 @@
     input_operands.push_back({in_operand.type, operand_data});
   }
 
-  if (instruction.opcode() == SpvOpVariable &&
+  if (instruction.opcode() == spv::Op::OpVariable &&
       instruction.NumInOperands() == 1) {
     // This is an uninitialized local variable.  Initialize it to zero.
     input_operands.push_back(
@@ -1017,7 +1019,7 @@
 
   // Adjust OpPhi instructions in the |merge_block|.
   for (const auto& inst : *merge_block) {
-    if (inst.opcode() != SpvOpPhi) {
+    if (inst.opcode() != spv::Op::OpPhi) {
       break;
     }
 
@@ -1070,7 +1072,8 @@
   // live-safe.  Add them if not already present.
   FindOrCreateBoolType();  // Needed for comparisons
   FindOrCreatePointerToIntegerType(
-      32, false, SpvStorageClassFunction);  // Needed for adding loop limiters
+      32, false,
+      spv::StorageClass::Function);  // Needed for adding loop limiters
   FindOrCreateIntegerConstant({0}, 32, false,
                               false);  // Needed for initializing loop limiters
   FindOrCreateIntegerConstant({1}, 32, false,
@@ -1107,8 +1110,8 @@
   for (auto& block : function_to_donate) {
     for (auto& inst : block) {
       switch (inst.opcode()) {
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain: {
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain: {
           protobufs::AccessChainClampingInfo clamping_info;
           clamping_info.set_access_chain_id(
               original_id_to_donated_id.at(inst.result_id()));
@@ -1118,7 +1121,8 @@
           assert(base_object && "The base object must exist.");
           auto pointer_type = donor_ir_context->get_def_use_mgr()->GetDef(
               base_object->type_id());
-          assert(pointer_type && pointer_type->opcode() == SpvOpTypePointer &&
+          assert(pointer_type &&
+                 pointer_type->opcode() == spv::Op::OpTypePointer &&
                  "The base object must have pointer type.");
 
           auto should_be_composite_type =
@@ -1138,7 +1142,8 @@
 
             // Get the bound for the component being indexed into.
             uint32_t bound;
-            if (should_be_composite_type->opcode() == SpvOpTypeRuntimeArray) {
+            if (should_be_composite_type->opcode() ==
+                spv::Op::OpTypeRuntimeArray) {
               // The donor is indexing into a runtime array.  We do not
               // donate runtime arrays.  Instead, we donate a corresponding
               // fixed-size array for every runtime array.  We should thus
@@ -1148,7 +1153,7 @@
                   GetIRContext()->get_def_use_mgr()->GetDef(
                       original_id_to_donated_id.at(
                           should_be_composite_type->result_id()));
-              assert(fixed_size_array_type->opcode() == SpvOpTypeArray &&
+              assert(fixed_size_array_type->opcode() == spv::Op::OpTypeArray &&
                      "A runtime array type in the donor should have been "
                      "replaced by a fixed-sized array in the recipient.");
               // The size of this fixed-size array is a suitable bound.
@@ -1163,12 +1168,12 @@
                 donor_ir_context->get_def_use_mgr()->GetDef(index_id);
             auto index_type_inst = donor_ir_context->get_def_use_mgr()->GetDef(
                 index_inst->type_id());
-            assert(index_type_inst->opcode() == SpvOpTypeInt);
+            assert(index_type_inst->opcode() == spv::Op::OpTypeInt);
             opt::analysis::Integer* index_int_type =
                 donor_ir_context->get_type_mgr()
                     ->GetType(index_type_inst->result_id())
                     ->AsInteger();
-            if (index_inst->opcode() != SpvOpConstant) {
+            if (index_inst->opcode() != spv::Op::OpConstant) {
               // We will have to clamp this index, so we need a constant
               // whose value is one less than the bound, to compare
               // against and to use as the clamped value.
@@ -1194,7 +1199,7 @@
   uint32_t kill_unreachable_return_value_id = 0;
   auto function_return_type_inst =
       donor_ir_context->get_def_use_mgr()->GetDef(function_to_donate.type_id());
-  if (function_return_type_inst->opcode() != SpvOpTypeVoid &&
+  if (function_return_type_inst->opcode() != spv::Op::OpTypeVoid &&
       fuzzerutil::FunctionContainsOpKillOrUnreachable(function_to_donate)) {
     kill_unreachable_return_value_id = FindOrCreateZeroConstant(
         original_id_to_donated_id.at(function_return_type_inst->result_id()),
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_donate_modules.h b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_donate_modules.h
index 924dd35..004f158 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_donate_modules.h
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_donate_modules.h
@@ -45,7 +45,8 @@
  private:
   // Adapts a storage class coming from a donor module so that it will work
   // in a recipient module, e.g. by changing Uniform to Private.
-  static SpvStorageClass AdaptStorageClass(SpvStorageClass donor_storage_class);
+  static spv::StorageClass AdaptStorageClass(
+      spv::StorageClass donor_storage_class);
 
   // Identifies all external instruction set imports in |donor_ir_context| and
   // populates |original_id_to_donated_id| with a mapping from the donor's id
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp
index 5bf0461..fecd82e 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp
@@ -40,8 +40,8 @@
         }
 
         // |instruction| must be OpAny or OpAll.
-        if (instruction.opcode() != SpvOpAny &&
-            instruction.opcode() != SpvOpAll) {
+        if (instruction.opcode() != spv::Op::OpAny &&
+            instruction.opcode() != spv::Op::OpAll) {
           continue;
         }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp
index 70fa6a1..86ffff4 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp
@@ -48,8 +48,8 @@
       // Only consider this block if it is the header of a conditional, with a
       // non-irrelevant condition.
       if (block.GetMergeInst() &&
-          block.GetMergeInst()->opcode() == SpvOpSelectionMerge &&
-          block.terminator()->opcode() == SpvOpBranchConditional &&
+          block.GetMergeInst()->opcode() == spv::Op::OpSelectionMerge &&
+          block.terminator()->opcode() == spv::Op::OpBranchConditional &&
           !GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
               block.terminator()->GetSingleWordInOperand(0))) {
         selection_headers.emplace_back(&block);
@@ -94,11 +94,11 @@
                                    ->get_def_use_mgr()
                                    ->GetDef(phi_instruction->type_id())
                                    ->opcode()) {
-                         case SpvOpTypeBool:
-                         case SpvOpTypeInt:
-                         case SpvOpTypeFloat:
-                         case SpvOpTypePointer:
-                         case SpvOpTypeVector:
+                         case spv::Op::OpTypeBool:
+                         case spv::Op::OpTypeInt:
+                         case spv::Op::OpTypeFloat:
+                         case spv::Op::OpTypePointer:
+                         case spv::Op::OpTypeVector:
                            return true;
                          default:
                            return false;
@@ -143,7 +143,7 @@
                 GetIRContext()->get_def_use_mgr()->GetDef(
                     phi_instruction->type_id());
             switch (type_instruction->opcode()) {
-              case SpvOpTypeVector: {
+              case spv::Op::OpTypeVector: {
                 uint32_t dimension =
                     type_instruction->GetSingleWordInOperand(1);
                 switch (dimension) {
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_inline_functions.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_inline_functions.cpp
index 4024096..6839bbe 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_inline_functions.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_inline_functions.cpp
@@ -64,7 +64,7 @@
     auto* function_call_block =
         GetIRContext()->get_instr_block(function_call_instruction);
     if ((function_call_instruction != &*--function_call_block->tail() ||
-         function_call_block->terminator()->opcode() != SpvOpBranch) &&
+         function_call_block->terminator()->opcode() != spv::Op::OpBranch) &&
         !MaybeApplyTransformation(TransformationSplitBlock(
             MakeInstructionDescriptor(GetIRContext(),
                                       function_call_instruction->NextNode()),
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
index b755d23..ec5fc4b 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
@@ -47,18 +47,20 @@
         }
 
         // Make sure |instruction| has only one indexing operand.
-        assert(instruction.NumInOperands() ==
-                   (instruction.opcode() == SpvOpCompositeExtract ? 2 : 3) &&
-               "FuzzerPassMakeVectorOperationsDynamic: the composite "
-               "instruction must have "
-               "only one indexing operand.");
+        assert(
+            instruction.NumInOperands() ==
+                (instruction.opcode() == spv::Op::OpCompositeExtract ? 2 : 3) &&
+            "FuzzerPassMakeVectorOperationsDynamic: the composite "
+            "instruction must have "
+            "only one indexing operand.");
 
         // Applies the make vector operation dynamic transformation.
         ApplyTransformation(TransformationMakeVectorOperationDynamic(
             instruction.result_id(),
             FindOrCreateIntegerConstant(
                 {instruction.GetSingleWordInOperand(
-                    instruction.opcode() == SpvOpCompositeExtract ? 1 : 2)},
+                    instruction.opcode() == spv::Op::OpCompositeExtract ? 1
+                                                                        : 2)},
                 32, GetFuzzerContext()->ChooseEven(), false)));
       }
     }
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_merge_function_returns.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_merge_function_returns.cpp
index 220f707..48c1861 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_merge_function_returns.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_merge_function_returns.cpp
@@ -64,11 +64,11 @@
         [this, function](
             opt::BasicBlock* /*unused*/, opt::BasicBlock::iterator inst_it,
             const protobufs::InstructionDescriptor& instruction_descriptor) {
-          const SpvOp opcode = inst_it->opcode();
+          const spv::Op opcode = inst_it->opcode();
           switch (opcode) {
-            case SpvOpKill:
-            case SpvOpUnreachable:
-            case SpvOpTerminateInvocation: {
+            case spv::Op::OpKill:
+            case spv::Op::OpUnreachable:
+            case spv::Op::OpTerminateInvocation: {
               // This is an early termination instruction - we need to wrap it
               // so that it becomes a return.
               if (TransformationWrapEarlyTerminatorInFunction::
@@ -85,7 +85,7 @@
                   GetIRContext()->get_def_use_mgr()->GetDef(
                       function->type_id());
               uint32_t returned_value_id;
-              if (function_return_type->opcode() == SpvOpTypeVoid) {
+              if (function_return_type->opcode() == spv::Op::OpTypeVoid) {
                 // No value is needed.
                 returned_value_id = 0;
               } else if (fuzzerutil::CanCreateConstant(
@@ -130,7 +130,7 @@
 
     // If the entry block does not branch unconditionally to another block,
     // split it.
-    if (function->entry()->terminator()->opcode() != SpvOpBranch) {
+    if (function->entry()->terminator()->opcode() != spv::Op::OpBranch) {
       SplitBlockAfterOpPhiOrOpVariable(function->entry()->id());
     }
 
@@ -149,9 +149,9 @@
       if (GetIRContext()
               ->get_instr_block(merge_block)
               ->WhileEachInst([](opt::Instruction* inst) {
-                return inst->opcode() == SpvOpLabel ||
-                       inst->opcode() == SpvOpPhi ||
-                       inst->opcode() == SpvOpBranch;
+                return inst->opcode() == spv::Op::OpLabel ||
+                       inst->opcode() == spv::Op::OpPhi ||
+                       inst->opcode() == spv::Op::OpBranch;
               })) {
         actual_merge_blocks.emplace_back(merge_block);
         continue;
@@ -324,7 +324,8 @@
 
 bool FuzzerPassMergeFunctionReturns::IsEarlyTerminatorWrapper(
     const opt::Function& function) const {
-  for (SpvOp opcode : {SpvOpKill, SpvOpUnreachable, SpvOpTerminateInvocation}) {
+  for (spv::Op opcode : {spv::Op::OpKill, spv::Op::OpUnreachable,
+                         spv::Op::OpTerminateInvocation}) {
     if (TransformationWrapEarlyTerminatorInFunction::MaybeGetWrapperFunction(
             GetIRContext(), opcode) == &function) {
       return true;
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_mutate_pointers.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_mutate_pointers.cpp
index bbe0540..a7e9fdc 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_mutate_pointers.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_mutate_pointers.cpp
@@ -39,7 +39,8 @@
           return;
         }
 
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
+                                                          inst_it)) {
           return;
         }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
index f60c1b4..48ac589 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
@@ -37,21 +37,21 @@
 
 void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaConstantPair(
     uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
-    const std::vector<SpvOp>& greater_than_opcodes,
-    const std::vector<SpvOp>& less_than_opcodes, uint32_t constant_id_1,
+    const std::vector<spv::Op>& greater_than_opcodes,
+    const std::vector<spv::Op>& less_than_opcodes, uint32_t constant_id_1,
     uint32_t constant_id_2, bool first_constant_is_larger) {
   auto bool_constant_opcode = GetIRContext()
                                   ->get_def_use_mgr()
                                   ->GetDef(bool_constant_use.id_of_interest())
                                   ->opcode();
-  assert((bool_constant_opcode == SpvOpConstantFalse ||
-          bool_constant_opcode == SpvOpConstantTrue) &&
+  assert((bool_constant_opcode == spv::Op::OpConstantFalse ||
+          bool_constant_opcode == spv::Op::OpConstantTrue) &&
          "Precondition: this must be a usage of a boolean constant.");
 
   // Pick an opcode at random.  First randomly decide whether to generate
   // a 'greater than' or 'less than' kind of opcode, and then select a
   // random opcode from the resulting subset.
-  SpvOp comparison_opcode;
+  spv::Op comparison_opcode;
   if (GetFuzzerContext()->ChooseEven()) {
     comparison_opcode = greater_than_opcodes[GetFuzzerContext()->RandomIndex(
         greater_than_opcodes)];
@@ -68,9 +68,9 @@
                 comparison_opcode) != greater_than_opcodes.end();
   uint32_t lhs_id;
   uint32_t rhs_id;
-  if ((bool_constant_opcode == SpvOpConstantTrue &&
+  if ((bool_constant_opcode == spv::Op::OpConstantTrue &&
        first_constant_is_larger == is_greater_than_opcode) ||
-      (bool_constant_opcode == SpvOpConstantFalse &&
+      (bool_constant_opcode == spv::Op::OpConstantFalse &&
        first_constant_is_larger != is_greater_than_opcode)) {
     lhs_id = constant_id_1;
     rhs_id = constant_id_2;
@@ -147,12 +147,12 @@
     first_constant_is_larger =
         float_constant_1->GetDouble() > float_constant_2->GetDouble();
   }
-  std::vector<SpvOp> greater_than_opcodes{
-      SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan,
-      SpvOpFUnordGreaterThanEqual};
-  std::vector<SpvOp> less_than_opcodes{
-      SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan,
-      SpvOpFUnordGreaterThanEqual};
+  std::vector<spv::Op> greater_than_opcodes{
+      spv::Op::OpFOrdGreaterThan, spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThan, spv::Op::OpFUnordGreaterThanEqual};
+  std::vector<spv::Op> less_than_opcodes{
+      spv::Op::OpFOrdGreaterThan, spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThan, spv::Op::OpFUnordGreaterThanEqual};
 
   ObfuscateBoolConstantViaConstantPair(
       depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
@@ -190,9 +190,10 @@
     first_constant_is_larger =
         signed_int_constant_1->GetS64() > signed_int_constant_2->GetS64();
   }
-  std::vector<SpvOp> greater_than_opcodes{SpvOpSGreaterThan,
-                                          SpvOpSGreaterThanEqual};
-  std::vector<SpvOp> less_than_opcodes{SpvOpSLessThan, SpvOpSLessThanEqual};
+  std::vector<spv::Op> greater_than_opcodes{spv::Op::OpSGreaterThan,
+                                            spv::Op::OpSGreaterThanEqual};
+  std::vector<spv::Op> less_than_opcodes{spv::Op::OpSLessThan,
+                                         spv::Op::OpSLessThanEqual};
 
   ObfuscateBoolConstantViaConstantPair(
       depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
@@ -232,9 +233,10 @@
     first_constant_is_larger =
         unsigned_int_constant_1->GetU64() > unsigned_int_constant_2->GetU64();
   }
-  std::vector<SpvOp> greater_than_opcodes{SpvOpUGreaterThan,
-                                          SpvOpUGreaterThanEqual};
-  std::vector<SpvOp> less_than_opcodes{SpvOpULessThan, SpvOpULessThanEqual};
+  std::vector<spv::Op> greater_than_opcodes{spv::Op::OpUGreaterThan,
+                                            spv::Op::OpUGreaterThanEqual};
+  std::vector<spv::Op> less_than_opcodes{spv::Op::OpULessThan,
+                                         spv::Op::OpULessThanEqual};
 
   ObfuscateBoolConstantViaConstantPair(
       depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
@@ -379,7 +381,7 @@
       uniform_descriptor.index());
   assert(element_type_id && "Type of uniform variable is invalid");
 
-  FindOrCreatePointerType(element_type_id, SpvStorageClassUniform);
+  FindOrCreatePointerType(element_type_id, spv::StorageClass::Uniform);
 
   // Create, apply and record a transformation to replace the constant use with
   // the result of a load from the chosen uniform.
@@ -394,11 +396,11 @@
               ->get_def_use_mgr()
               ->GetDef(constant_use.id_of_interest())
               ->opcode()) {
-    case SpvOpConstantTrue:
-    case SpvOpConstantFalse:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstantFalse:
       ObfuscateBoolConstant(depth, constant_use);
       break;
-    case SpvOpConstant:
+    case spv::Op::OpConstant:
       ObfuscateScalarConstant(depth, constant_use);
       break;
     default:
@@ -410,7 +412,7 @@
 void FuzzerPassObfuscateConstants::MaybeAddConstantIdUse(
     const opt::Instruction& inst, uint32_t in_operand_index,
     uint32_t base_instruction_result_id,
-    const std::map<SpvOp, uint32_t>& skipped_opcode_count,
+    const std::map<spv::Op, uint32_t>& skipped_opcode_count,
     std::vector<protobufs::IdUseDescriptor>* constant_uses) {
   if (inst.GetInOperand(in_operand_index).type != SPV_OPERAND_TYPE_ID) {
     // The operand is not an id, so it cannot be a constant id.
@@ -420,15 +422,15 @@
   auto operand_definition =
       GetIRContext()->get_def_use_mgr()->GetDef(operand_id);
   switch (operand_definition->opcode()) {
-    case SpvOpConstantFalse:
-    case SpvOpConstantTrue:
-    case SpvOpConstant: {
+    case spv::Op::OpConstantFalse:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstant: {
       // The operand is a constant id, so make an id use descriptor and record
       // it.
       protobufs::IdUseDescriptor id_use_descriptor;
       id_use_descriptor.set_id_of_interest(operand_id);
       id_use_descriptor.mutable_enclosing_instruction()
-          ->set_target_instruction_opcode(inst.opcode());
+          ->set_target_instruction_opcode(uint32_t(inst.opcode()));
       id_use_descriptor.mutable_enclosing_instruction()
           ->set_base_instruction_result_id(base_instruction_result_id);
       id_use_descriptor.mutable_enclosing_instruction()
@@ -461,7 +463,7 @@
       // opcode need to be skipped in order to find the instruction of interest
       // from the base instruction. We maintain a mapping that records a skip
       // count for each relevant opcode.
-      std::map<SpvOp, uint32_t> skipped_opcode_count;
+      std::map<spv::Op, uint32_t> skipped_opcode_count;
 
       // Go through each instruction in the block.
       for (auto& inst : block) {
@@ -478,7 +480,7 @@
         // The instruction must not be an OpVariable, the only id that an
         // OpVariable uses is an initializer id, which has to remain
         // constant.
-        if (inst.opcode() != SpvOpVariable) {
+        if (inst.opcode() != spv::Op::OpVariable) {
           // Consider each operand of the instruction, and add a constant id
           // use for the operand if relevant.
           for (uint32_t in_operand_index = 0;
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_obfuscate_constants.h b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_obfuscate_constants.h
index 30e64d2..bfef597 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_obfuscate_constants.h
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_obfuscate_constants.h
@@ -85,8 +85,8 @@
   // (similar for |less_than_opcodes|).
   void ObfuscateBoolConstantViaConstantPair(
       uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
-      const std::vector<SpvOp>& greater_than_opcodes,
-      const std::vector<SpvOp>& less_than_opcodes, uint32_t constant_id_1,
+      const std::vector<spv::Op>& greater_than_opcodes,
+      const std::vector<spv::Op>& less_than_opcodes, uint32_t constant_id_1,
       uint32_t constant_id_2, bool first_constant_is_larger);
 
   // A helper method to determine whether input operand |in_operand_index| of
@@ -96,7 +96,7 @@
   void MaybeAddConstantIdUse(
       const opt::Instruction& inst, uint32_t in_operand_index,
       uint32_t base_instruction_result_id,
-      const std::map<SpvOp, uint32_t>& skipped_opcode_count,
+      const std::map<spv::Op, uint32_t>& skipped_opcode_count,
       std::vector<protobufs::IdUseDescriptor>* constant_uses);
 
   // Returns a vector of unique words that denote constants. Every such constant
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_outline_functions.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_outline_functions.cpp
index b90c12d..e64373a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_outline_functions.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_outline_functions.cpp
@@ -137,12 +137,12 @@
          "The entry block cannot be a loop header at this point.");
 
   // If the entry block starts with OpPhi or OpVariable, try to split it.
-  if (entry_block->begin()->opcode() == SpvOpPhi ||
-      entry_block->begin()->opcode() == SpvOpVariable) {
+  if (entry_block->begin()->opcode() == spv::Op::OpPhi ||
+      entry_block->begin()->opcode() == spv::Op::OpVariable) {
     // Find the first non-OpPhi and non-OpVariable instruction.
     auto non_phi_or_var_inst = &*entry_block->begin();
-    while (non_phi_or_var_inst->opcode() == SpvOpPhi ||
-           non_phi_or_var_inst->opcode() == SpvOpVariable) {
+    while (non_phi_or_var_inst->opcode() == spv::Op::OpPhi ||
+           non_phi_or_var_inst->opcode() == spv::Op::OpVariable) {
       non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
     }
 
@@ -175,7 +175,7 @@
 
     // Find the first non-OpPhi instruction, after which to split.
     auto split_before = &*exit_block->begin();
-    while (split_before->opcode() == SpvOpPhi) {
+    while (split_before->opcode() == spv::Op::OpPhi) {
       split_before = split_before->NextNode();
     }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_permute_function_variables.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_permute_function_variables.cpp
index f8b9b45..2313f42 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_permute_function_variables.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_permute_function_variables.cpp
@@ -47,7 +47,7 @@
 
     std::vector<opt::Instruction*> variables;
     for (auto& instruction : *first_block) {
-      if (instruction.opcode() == SpvOpVariable) {
+      if (instruction.opcode() == spv::Op::OpVariable) {
         variables.push_back(&instruction);
       }
     }
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_permute_phi_operands.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_permute_phi_operands.cpp
index 5fac981..7fbdd3b 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_permute_phi_operands.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_permute_phi_operands.cpp
@@ -40,7 +40,7 @@
              const protobufs::InstructionDescriptor& /*unused*/) {
         const auto& inst = *inst_it;
 
-        if (inst.opcode() != SpvOpPhi) {
+        if (inst.opcode() != spv::Op::OpPhi) {
           return;
         }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
index a6c07b4..c0397e1 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
@@ -35,10 +35,11 @@
              opt::BasicBlock::iterator instruction_iterator,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(instruction_iterator->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            instruction_iterator->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try pushing an id through a variable.
         if (!GetFuzzerContext()->ChoosePercentage(
@@ -55,16 +56,16 @@
         // It must be valid to insert OpStore and OpLoad instructions
         // before the instruction to insert before.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpStore, instruction_iterator) ||
+                spv::Op::OpStore, instruction_iterator) ||
             !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpLoad, instruction_iterator)) {
+                spv::Op::OpLoad, instruction_iterator)) {
           return;
         }
 
         // Randomly decides whether a global or local variable will be added.
         auto variable_storage_class = GetFuzzerContext()->ChooseEven()
-                                          ? SpvStorageClassPrivate
-                                          : SpvStorageClassFunction;
+                                          ? spv::StorageClass::Private
+                                          : spv::StorageClass::Function;
 
         // Gets the available basic and pointer types.
         auto basic_type_ids_and_pointers =
@@ -127,13 +128,13 @@
             GetIRContext()->get_def_use_mgr()->GetDef(basic_type_id);
         assert(type_inst);
         switch (type_inst->opcode()) {
-          case SpvOpTypeBool:
-          case SpvOpTypeFloat:
-          case SpvOpTypeInt:
-          case SpvOpTypeArray:
-          case SpvOpTypeMatrix:
-          case SpvOpTypeVector:
-          case SpvOpTypeStruct:
+          case spv::Op::OpTypeBool:
+          case spv::Op::OpTypeFloat:
+          case spv::Op::OpTypeInt:
+          case spv::Op::OpTypeArray:
+          case spv::Op::OpTypeMatrix:
+          case spv::Op::OpTypeVector:
+          case spv::Op::OpTypeStruct:
             break;
           default:
             return;
@@ -150,7 +151,8 @@
                                    value_instructions)]
                 ->result_id(),
             GetFuzzerContext()->GetFreshId(), GetFuzzerContext()->GetFreshId(),
-            variable_storage_class, initializer_id, instruction_descriptor));
+            uint32_t(variable_storage_class), initializer_id,
+            instruction_descriptor));
       });
 }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp
index 995657c..52c0381 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp
@@ -38,13 +38,13 @@
   // to be executed with the Fragment execution model.  We conservatively only
   // allow OpKill if every entry point in the module has the Fragment execution
   // model.
-  auto fragment_execution_model_guaranteed =
-      std::all_of(GetIRContext()->module()->entry_points().begin(),
-                  GetIRContext()->module()->entry_points().end(),
-                  [](const opt::Instruction& entry_point) -> bool {
-                    return entry_point.GetSingleWordInOperand(0) ==
-                           SpvExecutionModelFragment;
-                  });
+  auto fragment_execution_model_guaranteed = std::all_of(
+      GetIRContext()->module()->entry_points().begin(),
+      GetIRContext()->module()->entry_points().end(),
+      [](const opt::Instruction& entry_point) -> bool {
+        return spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) ==
+               spv::ExecutionModel::Fragment;
+      });
 
   // Transformations of this type can disable one another.  To avoid ordering
   // bias, we therefore build a set of candidate transformations to apply, and
@@ -71,20 +71,20 @@
       // Whether we can use OpKill depends on the execution model, and which of
       // OpReturn and OpReturnValue we can use depends on the return type of the
       // enclosing function.
-      std::vector<SpvOp> opcodes = {SpvOpUnreachable};
+      std::vector<spv::Op> opcodes = {spv::Op::OpUnreachable};
       if (fragment_execution_model_guaranteed) {
-        opcodes.emplace_back(SpvOpKill);
+        opcodes.emplace_back(spv::Op::OpKill);
       }
       auto function_return_type =
           GetIRContext()->get_type_mgr()->GetType(function.type_id());
       if (function_return_type->AsVoid()) {
-        opcodes.emplace_back(SpvOpReturn);
+        opcodes.emplace_back(spv::Op::OpReturn);
       } else if (fuzzerutil::CanCreateConstant(GetIRContext(),
                                                function.type_id())) {
         // For simplicity we only allow OpReturnValue if the function return
         // type is a type for which we can create a constant.  This allows us a
         // zero of the given type as a default return value.
-        opcodes.emplace_back(SpvOpReturnValue);
+        opcodes.emplace_back(spv::Op::OpReturnValue);
       }
       // Choose one of the available terminator opcodes at random and create a
       // candidate transformation.
@@ -92,7 +92,7 @@
       candidate_transformations.emplace_back(
           TransformationReplaceBranchFromDeadBlockWithExit(
               block.id(), opcode,
-              opcode == SpvOpReturnValue
+              opcode == spv::Op::OpReturnValue
                   ? FindOrCreateZeroConstant(function.type_id(), true)
                   : 0));
     }
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
index af1aace..aabc6bc 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
@@ -41,7 +41,7 @@
     }
 
     // The instruction must be OpCopyMemory.
-    if (instruction->opcode() != SpvOpCopyMemory) {
+    if (instruction->opcode() != spv::Op::OpCopyMemory) {
       return;
     }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
index d0992a3..c1892be 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
@@ -40,7 +40,7 @@
       return;
     }
     // The instruction must be OpCopyObject.
-    if (instruction->opcode() != SpvOpCopyObject) {
+    if (instruction->opcode() != spv::Op::OpCopyObject) {
       return;
     }
     // The opcode of the type_id instruction cannot be a OpTypePointer,
@@ -48,21 +48,22 @@
     if (GetIRContext()
             ->get_def_use_mgr()
             ->GetDef(instruction->type_id())
-            ->opcode() == SpvOpTypePointer) {
+            ->opcode() == spv::Op::OpTypePointer) {
       return;
     }
     // It must be valid to insert OpStore and OpLoad instructions
     // before the instruction OpCopyObject.
-    if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
+    if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpStore,
                                                       instruction) ||
-        !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, instruction)) {
+        !fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
+                                                      instruction)) {
       return;
     }
 
     // Randomly decides whether a global or local variable will be added.
     auto variable_storage_class = GetFuzzerContext()->ChooseEven()
-                                      ? SpvStorageClassPrivate
-                                      : SpvStorageClassFunction;
+                                      ? spv::StorageClass::Private
+                                      : spv::StorageClass::Function;
 
     // Find or create a constant to initialize the variable from. The type of
     // |instruction| must be such that the function FindOrCreateConstant can be
@@ -79,7 +80,7 @@
     // Apply the transformation replacing OpCopyObject with Store and Load.
     ApplyTransformation(TransformationReplaceCopyObjectWithStoreLoad(
         instruction->result_id(), GetFuzzerContext()->GetFreshId(),
-        variable_storage_class, variable_initializer_id));
+        uint32_t(variable_storage_class), variable_initializer_id));
   });
 }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp
index 4d55ae8..4c0bd85 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp
@@ -73,7 +73,7 @@
   // we cannot use these as replacements.
   for (const auto& pair : GetIRContext()->get_def_use_mgr()->id_to_defs()) {
     uint32_t type_id = pair.second->type_id();
-    if (pair.second->opcode() != SpvOpFunction && type_id &&
+    if (pair.second->opcode() != spv::Op::OpFunction && type_id &&
         types_to_ids.count(type_id)) {
       types_to_ids[type_id].push_back(pair.first);
     }
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
index 38ac048..8d292ac 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
@@ -50,9 +50,9 @@
       std::unordered_map<uint32_t, opt::Instruction*> current_op_loads;
       for (auto& instruction : block) {
         // Add a potential OpLoad instruction.
-        if (instruction.opcode() == SpvOpLoad) {
+        if (instruction.opcode() == spv::Op::OpLoad) {
           current_op_loads[instruction.result_id()] = &instruction;
-        } else if (instruction.opcode() == SpvOpStore) {
+        } else if (instruction.opcode() == spv::Op::OpStore) {
           if (current_op_loads.find(instruction.GetSingleWordOperand(1)) !=
               current_op_loads.end()) {
             // We have found the matching OpLoad instruction to the current
@@ -73,7 +73,7 @@
             opt::Instruction* source_id =
                 GetIRContext()->get_def_use_mgr()->GetDef(
                     it->second->GetSingleWordOperand(2));
-            SpvStorageClass storage_class =
+            spv::StorageClass storage_class =
                 fuzzerutil::GetStorageClassFromPointerType(
                     GetIRContext(), source_id->type_id());
             if (!TransformationReplaceLoadStoreWithCopyMemory::
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
index ea90a7a..26475ab 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
@@ -50,7 +50,7 @@
               block->id(), [this, &function, block, &transformations](
                                opt::Instruction* instruction, uint32_t) {
                 // Only consider OpPhi instructions.
-                if (instruction->opcode() != SpvOpPhi) {
+                if (instruction->opcode() != spv::Op::OpPhi) {
                   return;
                 }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp
index 72ed093..4691e0a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp
@@ -52,7 +52,7 @@
 
       for (auto& instruction : block) {
         // We only care about OpSelect instructions.
-        if (instruction.opcode() != SpvOpSelect) {
+        if (instruction.opcode() != spv::Op::OpSelect) {
           continue;
         }
 
@@ -69,7 +69,7 @@
                 ->get_def_use_mgr()
                 ->GetDef(fuzzerutil::GetTypeId(
                     GetIRContext(), instruction.GetSingleWordInOperand(0)))
-                ->opcode() != SpvOpTypeBool) {
+                ->opcode() != spv::Op::OpTypeBool) {
           continue;
         }
 
@@ -136,7 +136,7 @@
 
 bool FuzzerPassReplaceOpSelectsWithConditionalBranches::
     InstructionNeedsSplitBefore(opt::Instruction* instruction) {
-  assert(instruction && instruction->opcode() == SpvOpSelect &&
+  assert(instruction && instruction->opcode() == spv::Op::OpSelect &&
          "The instruction must be OpSelect.");
 
   auto block = GetIRContext()->get_instr_block(instruction);
@@ -163,7 +163,7 @@
   auto predecessor = GetIRContext()->get_instr_block(
       GetIRContext()->cfg()->preds(block->id())[0]);
   return predecessor->MergeBlockIdIfAny() ||
-         predecessor->terminator()->opcode() != SpvOpBranch;
+         predecessor->terminator()->opcode() != spv::Op::OpBranch;
 }
 
 }  // namespace fuzz
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp
index 7fb7b0d..d7eddca 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp
@@ -72,7 +72,8 @@
     assert(replaced_param && "Unable to find a parameter to replace");
 
     // Make sure type id for the global variable exists in the module.
-    FindOrCreatePointerType(replaced_param->type_id(), SpvStorageClassPrivate);
+    FindOrCreatePointerType(replaced_param->type_id(),
+                            spv::StorageClass::Private);
 
     // Make sure initializer for the global variable exists in the module.
     FindOrCreateZeroConstant(replaced_param->type_id(), false);
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_split_blocks.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_split_blocks.cpp
index 40a4151..5b4afcc 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_split_blocks.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_split_blocks.cpp
@@ -65,7 +65,7 @@
 
     // Counts the number of times we have seen each opcode since we reset the
     // base instruction.
-    std::map<SpvOp, uint32_t> skip_count;
+    std::map<spv::Op, uint32_t> skip_count;
 
     // Consider every instruction in the block.  The label is excluded: it is
     // only necessary to consider it as a base in case the first instruction
@@ -78,7 +78,7 @@
         base = inst.result_id();
         skip_count.clear();
       }
-      const SpvOp opcode = inst.opcode();
+      const spv::Op opcode = inst.opcode();
       instruction_descriptors.emplace_back(MakeInstructionDescriptor(
           base, opcode, skip_count.count(opcode) ? skip_count.at(opcode) : 0));
       if (!inst.HasResultId()) {
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp
index f8bf111..72c8358 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp
@@ -39,7 +39,7 @@
              const protobufs::InstructionDescriptor& instruction_descriptor) {
         const auto& inst = *inst_it;
 
-        if (inst.opcode() != SpvOpBranchConditional) {
+        if (inst.opcode() != spv::Op::OpBranchConditional) {
           return;
         }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
index ac2b156..2a1ad6e 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
@@ -36,8 +36,9 @@
   // probabilistically applied.
   context->module()->ForEachInst([this,
                                   context](opt::Instruction* instruction) {
-    SpvOp opcode = instruction->opcode();
-    if ((opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain) &&
+    spv::Op opcode = instruction->opcode();
+    if ((opcode == spv::Op::OpAccessChain ||
+         opcode == spv::Op::OpInBoundsAccessChain) &&
         GetFuzzerContext()->ChoosePercentage(
             GetFuzzerContext()->GetChanceOfTogglingAccessChainInstruction())) {
       auto instructionDescriptor =
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
index 35adcfe..55fbe2c 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
@@ -52,7 +52,7 @@
         // It must be valid to insert an OpCompositeConstruct instruction
         // before |instruction_iterator|.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpCompositeConstruct, instruction_iterator)) {
+                spv::Op::OpCompositeConstruct, instruction_iterator)) {
           return;
         }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_util.cpp b/third_party/SPIRV-Tools/source/fuzz/fuzzer_util.cpp
index 1d368a9..e85ff2f 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_util.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_util.cpp
@@ -49,7 +49,7 @@
                             const std::vector<uint32_t>& words,
                             uint32_t type_id, bool is_irrelevant) {
   for (const auto& inst : ir_context->types_values()) {
-    if (inst.opcode() == SpvOpConstant && inst.type_id() == type_id &&
+    if (inst.opcode() == spv::Op::OpConstant && inst.type_id() == type_id &&
         inst.GetInOperand(0).words == words &&
         transformation_context.GetFactManager()->IdIsIrrelevant(
             inst.result_id()) == is_irrelevant) {
@@ -112,7 +112,7 @@
     // No instruction defining this id was found.
     return nullptr;
   }
-  if (inst->opcode() != SpvOpLabel) {
+  if (inst->opcode() != spv::Op::OpLabel) {
     // The instruction defining the id is not a label, so it cannot be a block
     // id.
     return nullptr;
@@ -138,7 +138,7 @@
   // makes sense here because we need to increment |phi_index| for each OpPhi
   // instruction.
   for (auto& inst : *bb_to) {
-    if (inst.opcode() != SpvOpPhi) {
+    if (inst.opcode() != spv::Op::OpPhi) {
       // The OpPhi instructions all occur at the start of the block; if we find
       // a non-OpPhi then we have seen them all.
       break;
@@ -189,24 +189,24 @@
   const auto* bb_from = MaybeFindBlock(ir_context, bb_from_id);
   assert(bb_from && "|bb_from_id| is invalid");
   assert(MaybeFindBlock(ir_context, bb_to_id) && "|bb_to_id| is invalid");
-  assert(bb_from->terminator()->opcode() == SpvOpBranch &&
+  assert(bb_from->terminator()->opcode() == spv::Op::OpBranch &&
          "Precondition on terminator of bb_from is not satisfied");
 
   // Get the id of the boolean constant to be used as the condition.
   auto condition_inst = ir_context->get_def_use_mgr()->GetDef(bool_id);
   assert(condition_inst &&
-         (condition_inst->opcode() == SpvOpConstantTrue ||
-          condition_inst->opcode() == SpvOpConstantFalse) &&
+         (condition_inst->opcode() == spv::Op::OpConstantTrue ||
+          condition_inst->opcode() == spv::Op::OpConstantFalse) &&
          "|bool_id| is invalid");
 
-  auto condition_value = condition_inst->opcode() == SpvOpConstantTrue;
+  auto condition_value = condition_inst->opcode() == spv::Op::OpConstantTrue;
   auto successor_id = bb_from->terminator()->GetSingleWordInOperand(0);
 
   // Add the dead branch, by turning OpBranch into OpBranchConditional, and
   // ordering the targets depending on whether the given boolean corresponds to
   // true or false.
   return opt::Instruction(
-      ir_context, SpvOpBranchConditional, 0, 0,
+      ir_context, spv::Op::OpBranchConditional, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {bool_id}},
        {SPV_OPERAND_TYPE_ID, {condition_value ? successor_id : bb_to_id}},
        {SPV_OPERAND_TYPE_ID, {condition_value ? bb_to_id : successor_id}}});
@@ -228,7 +228,7 @@
   if (!from_to_edge_already_exists) {
     uint32_t phi_index = 0;
     for (auto& inst : *bb_to) {
-      if (inst.opcode() != SpvOpPhi) {
+      if (inst.opcode() != spv::Op::OpPhi) {
         break;
       }
       assert(phi_index < static_cast<uint32_t>(phi_ids.size()) &&
@@ -285,28 +285,30 @@
 }
 
 bool CanInsertOpcodeBeforeInstruction(
-    SpvOp opcode, const opt::BasicBlock::iterator& instruction_in_block) {
+    spv::Op opcode, const opt::BasicBlock::iterator& instruction_in_block) {
   if (instruction_in_block->PreviousNode() &&
-      (instruction_in_block->PreviousNode()->opcode() == SpvOpLoopMerge ||
-       instruction_in_block->PreviousNode()->opcode() == SpvOpSelectionMerge)) {
+      (instruction_in_block->PreviousNode()->opcode() == spv::Op::OpLoopMerge ||
+       instruction_in_block->PreviousNode()->opcode() ==
+           spv::Op::OpSelectionMerge)) {
     // We cannot insert directly after a merge instruction.
     return false;
   }
-  if (opcode != SpvOpVariable &&
-      instruction_in_block->opcode() == SpvOpVariable) {
+  if (opcode != spv::Op::OpVariable &&
+      instruction_in_block->opcode() == spv::Op::OpVariable) {
     // We cannot insert a non-OpVariable instruction directly before a
     // variable; variables in a function must be contiguous in the entry block.
     return false;
   }
   // We cannot insert a non-OpPhi instruction directly before an OpPhi, because
   // OpPhi instructions need to be contiguous at the start of a block.
-  return opcode == SpvOpPhi || instruction_in_block->opcode() != SpvOpPhi;
+  return opcode == spv::Op::OpPhi ||
+         instruction_in_block->opcode() != spv::Op::OpPhi;
 }
 
 bool CanMakeSynonymOf(opt::IRContext* ir_context,
                       const TransformationContext& transformation_context,
                       const opt::Instruction& inst) {
-  if (inst.opcode() == SpvOpSampledImage) {
+  if (inst.opcode() == spv::Op::OpSampledImage) {
     // The SPIR-V data rules say that only very specific instructions may
     // may consume the result id of an OpSampledImage, and this excludes the
     // instructions that are used for making synonyms.
@@ -326,15 +328,15 @@
     return false;
   }
   auto type_inst = ir_context->get_def_use_mgr()->GetDef(inst.type_id());
-  if (type_inst->opcode() == SpvOpTypeVoid) {
+  if (type_inst->opcode() == spv::Op::OpTypeVoid) {
     // We only make synonyms of instructions that define objects, and an object
     // cannot have void type.
     return false;
   }
-  if (type_inst->opcode() == SpvOpTypePointer) {
+  if (type_inst->opcode() == spv::Op::OpTypePointer) {
     switch (inst.opcode()) {
-      case SpvOpConstantNull:
-      case SpvOpUndef:
+      case spv::Op::OpConstantNull:
+      case spv::Op::OpUndef:
         // We disallow making synonyms of null or undefined pointers.  This is
         // to provide the property that if the original shader exhibited no bad
         // pointer accesses, the transformed shader will not either.
@@ -373,22 +375,22 @@
       context->get_def_use_mgr()->GetDef(base_object_type_id);
   assert(should_be_composite_type && "The type should exist.");
   switch (should_be_composite_type->opcode()) {
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       auto array_length = GetArraySize(*should_be_composite_type, context);
       if (array_length == 0 || index >= array_length) {
         return 0;
       }
       return should_be_composite_type->GetSingleWordInOperand(0);
     }
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector: {
       auto count = should_be_composite_type->GetSingleWordInOperand(1);
       if (index >= count) {
         return 0;
       }
       return should_be_composite_type->GetSingleWordInOperand(0);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       if (index >= GetNumberOfStructMembers(*should_be_composite_type)) {
         return 0;
       }
@@ -415,7 +417,7 @@
 
 uint32_t GetNumberOfStructMembers(
     const opt::Instruction& struct_type_instruction) {
-  assert(struct_type_instruction.opcode() == SpvOpTypeStruct &&
+  assert(struct_type_instruction.opcode() == spv::Op::OpTypeStruct &&
          "An OpTypeStruct instruction is required here.");
   return struct_type_instruction.NumInOperands();
 }
@@ -436,15 +438,15 @@
 uint32_t GetBoundForCompositeIndex(const opt::Instruction& composite_type_inst,
                                    opt::IRContext* ir_context) {
   switch (composite_type_inst.opcode()) {
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       return fuzzerutil::GetArraySize(composite_type_inst, ir_context);
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       return composite_type_inst.GetSingleWordInOperand(1);
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       return fuzzerutil::GetNumberOfStructMembers(composite_type_inst);
     }
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       assert(false &&
              "GetBoundForCompositeIndex should not be invoked with an "
              "OpTypeRuntimeArray, which does not have a static bound.");
@@ -455,27 +457,27 @@
   }
 }
 
-SpvMemorySemanticsMask GetMemorySemanticsForStorageClass(
-    SpvStorageClass storage_class) {
+spv::MemorySemanticsMask GetMemorySemanticsForStorageClass(
+    spv::StorageClass storage_class) {
   switch (storage_class) {
-    case SpvStorageClassWorkgroup:
-      return SpvMemorySemanticsWorkgroupMemoryMask;
+    case spv::StorageClass::Workgroup:
+      return spv::MemorySemanticsMask::WorkgroupMemory;
 
-    case SpvStorageClassStorageBuffer:
-    case SpvStorageClassPhysicalStorageBuffer:
-      return SpvMemorySemanticsUniformMemoryMask;
+    case spv::StorageClass::StorageBuffer:
+    case spv::StorageClass::PhysicalStorageBuffer:
+      return spv::MemorySemanticsMask::UniformMemory;
 
-    case SpvStorageClassCrossWorkgroup:
-      return SpvMemorySemanticsCrossWorkgroupMemoryMask;
+    case spv::StorageClass::CrossWorkgroup:
+      return spv::MemorySemanticsMask::CrossWorkgroupMemory;
 
-    case SpvStorageClassAtomicCounter:
-      return SpvMemorySemanticsAtomicCounterMemoryMask;
+    case spv::StorageClass::AtomicCounter:
+      return spv::MemorySemanticsMask::AtomicCounterMemory;
 
-    case SpvStorageClassImage:
-      return SpvMemorySemanticsImageMemoryMask;
+    case spv::StorageClass::Image:
+      return spv::MemorySemanticsMask::ImageMemory;
 
     default:
-      return SpvMemorySemanticsMaskNone;
+      return spv::MemorySemanticsMask::MaskNone;
   }
 }
 
@@ -562,8 +564,8 @@
       [&result](const opt::Instruction* use_instruction,
                 uint32_t /*unused*/) -> bool {
         switch (use_instruction->opcode()) {
-          case SpvOpLoopMerge:
-          case SpvOpSelectionMerge:
+          case spv::Op::OpLoopMerge:
+          case spv::Op::OpSelectionMerge:
             result = true;
             return false;
           default:
@@ -581,7 +583,7 @@
       [ir_context, &result](opt::Instruction* use_instruction,
                             uint32_t use_index) -> bool {
         switch (use_instruction->opcode()) {
-          case SpvOpLoopMerge:
+          case spv::Op::OpLoopMerge:
             // The merge block operand is the first operand in OpLoopMerge.
             if (use_index == 0) {
               result = ir_context->get_instr_block(use_instruction)->id();
@@ -599,7 +601,7 @@
                           const std::vector<uint32_t>& type_ids) {
   // Look through the existing types for a match.
   for (auto& type_or_value : ir_context->types_values()) {
-    if (type_or_value.opcode() != SpvOpTypeFunction) {
+    if (type_or_value.opcode() != spv::Op::OpTypeFunction) {
       // We are only interested in function types.
       continue;
     }
@@ -641,8 +643,8 @@
 
 bool FunctionContainsOpKillOrUnreachable(const opt::Function& function) {
   for (auto& block : function) {
-    if (block.terminator()->opcode() == SpvOpKill ||
-        block.terminator()->opcode() == SpvOpUnreachable) {
+    if (block.terminator()->opcode() == spv::Op::OpKill ||
+        block.terminator()->opcode() == spv::Op::OpUnreachable) {
       return true;
     }
   }
@@ -669,7 +671,7 @@
       context->get_instr_block(use_instruction)->GetParent();
   // If the id a function parameter, it needs to be associated with the
   // function containing the use.
-  if (defining_instruction->opcode() == SpvOpFunctionParameter) {
+  if (defining_instruction->opcode() == spv::Op::OpFunctionParameter) {
     return InstructionIsFunctionParameter(defining_instruction,
                                           enclosing_function);
   }
@@ -687,7 +689,7 @@
     return false;
   }
   auto dominator_analysis = context->GetDominatorAnalysis(enclosing_function);
-  if (use_instruction->opcode() == SpvOpPhi) {
+  if (use_instruction->opcode() == spv::Op::OpPhi) {
     // In the case where the use is an operand to OpPhi, it is actually the
     // *parent* block associated with the operand that must be dominated by
     // the synonym.
@@ -710,7 +712,7 @@
       context->get_instr_block(instruction)->GetParent();
   // If the id a function parameter, it needs to be associated with the
   // function containing the instruction.
-  if (id_definition->opcode() == SpvOpFunctionParameter) {
+  if (id_definition->opcode() == spv::Op::OpFunctionParameter) {
     return InstructionIsFunctionParameter(id_definition,
                                           function_enclosing_instruction);
   }
@@ -732,7 +734,7 @@
     // the instruction.
     return true;
   }
-  if (id_definition->opcode() == SpvOpVariable &&
+  if (id_definition->opcode() == spv::Op::OpVariable &&
       function_enclosing_instruction ==
           context->get_instr_block(id)->GetParent()) {
     assert(!context->IsReachable(*context->get_instr_block(instruction)) &&
@@ -747,7 +749,7 @@
 
 bool InstructionIsFunctionParameter(opt::Instruction* instruction,
                                     opt::Function* function) {
-  if (instruction->opcode() != SpvOpFunctionParameter) {
+  if (instruction->opcode() != spv::Op::OpFunctionParameter) {
     return false;
   }
   bool found_parameter = false;
@@ -767,7 +769,8 @@
 }
 
 uint32_t GetPointeeTypeIdFromPointerType(opt::Instruction* pointer_type_inst) {
-  assert(pointer_type_inst && pointer_type_inst->opcode() == SpvOpTypePointer &&
+  assert(pointer_type_inst &&
+         pointer_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Precondition: |pointer_type_inst| must be OpTypePointer.");
   return pointer_type_inst->GetSingleWordInOperand(1);
 }
@@ -778,26 +781,28 @@
       context->get_def_use_mgr()->GetDef(pointer_type_id));
 }
 
-SpvStorageClass GetStorageClassFromPointerType(
+spv::StorageClass GetStorageClassFromPointerType(
     opt::Instruction* pointer_type_inst) {
-  assert(pointer_type_inst && pointer_type_inst->opcode() == SpvOpTypePointer &&
+  assert(pointer_type_inst &&
+         pointer_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Precondition: |pointer_type_inst| must be OpTypePointer.");
-  return static_cast<SpvStorageClass>(
+  return static_cast<spv::StorageClass>(
       pointer_type_inst->GetSingleWordInOperand(0));
 }
 
-SpvStorageClass GetStorageClassFromPointerType(opt::IRContext* context,
-                                               uint32_t pointer_type_id) {
+spv::StorageClass GetStorageClassFromPointerType(opt::IRContext* context,
+                                                 uint32_t pointer_type_id) {
   return GetStorageClassFromPointerType(
       context->get_def_use_mgr()->GetDef(pointer_type_id));
 }
 
 uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id,
-                             SpvStorageClass storage_class) {
+                             spv::StorageClass storage_class) {
   for (auto& inst : context->types_values()) {
     switch (inst.opcode()) {
-      case SpvOpTypePointer:
-        if (inst.GetSingleWordInOperand(0) == storage_class &&
+      case spv::Op::OpTypePointer:
+        if (spv::StorageClass(inst.GetSingleWordInOperand(0)) ==
+                storage_class &&
             inst.GetSingleWordInOperand(1) == pointee_type_id) {
           return inst.result_id();
         }
@@ -818,30 +823,30 @@
 bool IsNullConstantSupported(opt::IRContext* ir_context,
                              const opt::Instruction& type_inst) {
   switch (type_inst.opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeBool:
-    case SpvOpTypeDeviceEvent:
-    case SpvOpTypeEvent:
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeQueue:
-    case SpvOpTypeReserveId:
-    case SpvOpTypeVector:
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeDeviceEvent:
+    case spv::Op::OpTypeEvent:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeQueue:
+    case spv::Op::OpTypeReserveId:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeStruct:
       return true;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       // Null pointers are allowed if the VariablePointers capability is
       // enabled, or if the VariablePointersStorageBuffer capability is enabled
       // and the pointer type has StorageBuffer as its storage class.
       if (ir_context->get_feature_mgr()->HasCapability(
-              SpvCapabilityVariablePointers)) {
+              spv::Capability::VariablePointers)) {
         return true;
       }
       if (ir_context->get_feature_mgr()->HasCapability(
-              SpvCapabilityVariablePointersStorageBuffer)) {
-        return type_inst.GetSingleWordInOperand(0) ==
-               SpvStorageClassStorageBuffer;
+              spv::Capability::VariablePointersStorageBuffer)) {
+        return spv::StorageClass(type_inst.GetSingleWordInOperand(0)) ==
+               spv::StorageClass::StorageBuffer;
       }
       return false;
     default:
@@ -885,22 +890,22 @@
 
 opt::Instruction* AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
                                     uint32_t type_id,
-                                    SpvStorageClass storage_class,
+                                    spv::StorageClass storage_class,
                                     uint32_t initializer_id) {
   // Check various preconditions.
   assert(result_id != 0 && "Result id can't be 0");
 
-  assert((storage_class == SpvStorageClassPrivate ||
-          storage_class == SpvStorageClassWorkgroup) &&
+  assert((storage_class == spv::StorageClass::Private ||
+          storage_class == spv::StorageClass::Workgroup) &&
          "Variable's storage class must be either Private or Workgroup");
 
   auto* type_inst = context->get_def_use_mgr()->GetDef(type_id);
   (void)type_inst;  // Variable becomes unused in release mode.
-  assert(type_inst && type_inst->opcode() == SpvOpTypePointer &&
+  assert(type_inst && type_inst->opcode() == spv::Op::OpTypePointer &&
          GetStorageClassFromPointerType(type_inst) == storage_class &&
          "Variable's type is invalid");
 
-  if (storage_class == SpvStorageClassWorkgroup) {
+  if (storage_class == spv::StorageClass::Workgroup) {
     assert(initializer_id == 0);
   }
 
@@ -922,7 +927,7 @@
   }
 
   auto new_instruction = MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, type_id, result_id, std::move(operands));
+      context, spv::Op::OpVariable, type_id, result_id, std::move(operands));
   auto result = new_instruction.get();
   context->module()->AddGlobalValue(std::move(new_instruction));
 
@@ -940,8 +945,9 @@
 
   auto* type_inst = context->get_def_use_mgr()->GetDef(type_id);
   (void)type_inst;  // Variable becomes unused in release mode.
-  assert(type_inst && type_inst->opcode() == SpvOpTypePointer &&
-         GetStorageClassFromPointerType(type_inst) == SpvStorageClassFunction &&
+  assert(type_inst && type_inst->opcode() == spv::Op::OpTypePointer &&
+         GetStorageClassFromPointerType(type_inst) ==
+             spv::StorageClass::Function &&
          "Variable's type is invalid");
 
   const auto* constant_inst =
@@ -956,10 +962,10 @@
   assert(function && "Function id is invalid");
 
   auto new_instruction = MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, type_id, result_id,
-      opt::Instruction::OperandList{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
-          {SPV_OPERAND_TYPE_ID, {initializer_id}}});
+      context, spv::Op::OpVariable, type_id, result_id,
+      opt::Instruction::OperandList{{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                     {uint32_t(spv::StorageClass::Function)}},
+                                    {SPV_OPERAND_TYPE_ID, {initializer_id}}});
   auto result = new_instruction.get();
   function->begin()->begin()->InsertBefore(std::move(new_instruction));
 
@@ -1022,7 +1028,7 @@
   std::vector<opt::Instruction*> result;
   ir_context->get_def_use_mgr()->ForEachUser(
       function_id, [&result, function_id](opt::Instruction* inst) {
-        if (inst->opcode() == SpvOpFunctionCall &&
+        if (inst->opcode() == spv::Op::OpFunctionCall &&
             inst->GetSingleWordInOperand(0) == function_id) {
           result.push_back(inst);
         }
@@ -1137,7 +1143,7 @@
   }
 
   ir_context->AddType(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeFunction, 0, result_id, std::move(operands)));
+      ir_context, spv::Op::OpTypeFunction, 0, result_id, std::move(operands)));
 
   UpdateModuleIdBound(ir_context, result_id);
 }
@@ -1186,7 +1192,7 @@
 uint32_t MaybeGetStructType(opt::IRContext* ir_context,
                             const std::vector<uint32_t>& component_type_ids) {
   for (auto& type_or_value : ir_context->types_values()) {
-    if (type_or_value.opcode() != SpvOpTypeStruct ||
+    if (type_or_value.opcode() != spv::Op::OpTypeStruct ||
         type_or_value.NumInOperands() !=
             static_cast<uint32_t>(component_type_ids.size())) {
       continue;
@@ -1219,11 +1225,11 @@
   assert(type_inst && "|scalar_or_composite_type_id| is invalid");
 
   switch (type_inst->opcode()) {
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       return MaybeGetBoolConstant(ir_context, transformation_context, false,
                                   is_irrelevant);
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt: {
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt: {
       const auto width = type_inst->GetSingleWordInOperand(0);
       std::vector<uint32_t> words = {0};
       if (width > 32) {
@@ -1233,7 +1239,7 @@
       return MaybeGetScalarConstant(ir_context, transformation_context, words,
                                     scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       std::vector<uint32_t> component_ids;
       for (uint32_t i = 0; i < type_inst->NumInOperands(); ++i) {
         const auto component_type_id = type_inst->GetSingleWordInOperand(i);
@@ -1260,8 +1266,8 @@
           ir_context, transformation_context, component_ids,
           scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector: {
       const auto component_type_id = type_inst->GetSingleWordInOperand(0);
 
       auto component_id = MaybeGetZeroConstant(
@@ -1284,7 +1290,7 @@
           std::vector<uint32_t>(component_count, component_id),
           scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       const auto component_type_id = type_inst->GetSingleWordInOperand(0);
 
       auto component_id = MaybeGetZeroConstant(
@@ -1319,16 +1325,16 @@
   assert(spvOpcodeGeneratesType(type_instr->opcode()) &&
          "A type-generating opcode was expected.");
   switch (type_instr->opcode()) {
-    case SpvOpTypeBool:
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       return true;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       return CanCreateConstant(ir_context,
                                type_instr->GetSingleWordInOperand(0));
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       if (HasBlockOrBufferBlockDecoration(ir_context, type_id)) {
         return false;
       }
@@ -1377,7 +1383,7 @@
   assert(IsCompositeType(type) && "|composite_type_id| is invalid");
 
   for (const auto& inst : ir_context->types_values()) {
-    if (inst.opcode() == SpvOpConstantComposite &&
+    if (inst.opcode() == spv::Op::OpConstantComposite &&
         inst.type_id() == composite_type_id &&
         transformation_context.GetFactManager()->IdIsIrrelevant(
             inst.result_id()) == is_irrelevant &&
@@ -1457,7 +1463,8 @@
     bool is_irrelevant) {
   if (auto type_id = MaybeGetBoolType(ir_context)) {
     for (const auto& inst : ir_context->types_values()) {
-      if (inst.opcode() == (value ? SpvOpConstantTrue : SpvOpConstantFalse) &&
+      if (inst.opcode() ==
+              (value ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse) &&
           inst.type_id() == type_id &&
           transformation_context.GetFactManager()->IdIsIrrelevant(
               inst.result_id()) == is_irrelevant) {
@@ -1552,13 +1559,13 @@
 
 opt::Instruction* GetLastInsertBeforeInstruction(opt::IRContext* ir_context,
                                                  uint32_t block_id,
-                                                 SpvOp opcode) {
+                                                 spv::Op opcode) {
   // CFG::block uses std::map::at which throws an exception when |block_id| is
   // invalid. The error message is unhelpful, though. Thus, we test that
   // |block_id| is valid here.
   const auto* label_inst = ir_context->get_def_use_mgr()->GetDef(block_id);
   (void)label_inst;  // Make compilers happy in release mode.
-  assert(label_inst && label_inst->opcode() == SpvOpLabel &&
+  assert(label_inst && label_inst->opcode() == spv::Op::OpLabel &&
          "|block_id| is invalid");
 
   auto* block = ir_context->cfg()->block(block_id);
@@ -1624,7 +1631,7 @@
         assert(composite_type_being_accessed->AsStruct());
         auto constant_index_instruction = ir_context->get_def_use_mgr()->GetDef(
             use_instruction->GetSingleWordInOperand(index_in_operand));
-        assert(constant_index_instruction->opcode() == SpvOpConstant);
+        assert(constant_index_instruction->opcode() == spv::Op::OpConstant);
         uint32_t member_index =
             constant_index_instruction->GetSingleWordInOperand(0);
         composite_type_being_accessed =
@@ -1641,7 +1648,7 @@
     }
   }
 
-  if (use_instruction->opcode() == SpvOpFunctionCall &&
+  if (use_instruction->opcode() == spv::Op::OpFunctionCall &&
       use_in_operand_index > 0) {
     // This is a function call argument.  It is not allowed to have pointer
     // type.
@@ -1663,7 +1670,7 @@
     }
   }
 
-  if (use_instruction->opcode() == SpvOpImageTexelPointer &&
+  if (use_instruction->opcode() == spv::Op::OpImageTexelPointer &&
       use_in_operand_index == 2) {
     // The OpImageTexelPointer instruction has a Sample parameter that in some
     // situations must be an id for the value 0.  To guard against disrupting
@@ -1671,38 +1678,38 @@
     return false;
   }
 
-  if (ir_context->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
+  if (ir_context->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
     // With the Shader capability, memory scope and memory semantics operands
     // are required to be constants, so they cannot be replaced arbitrarily.
     switch (use_instruction->opcode()) {
-      case SpvOpAtomicLoad:
-      case SpvOpAtomicStore:
-      case SpvOpAtomicExchange:
-      case SpvOpAtomicIIncrement:
-      case SpvOpAtomicIDecrement:
-      case SpvOpAtomicIAdd:
-      case SpvOpAtomicISub:
-      case SpvOpAtomicSMin:
-      case SpvOpAtomicUMin:
-      case SpvOpAtomicSMax:
-      case SpvOpAtomicUMax:
-      case SpvOpAtomicAnd:
-      case SpvOpAtomicOr:
-      case SpvOpAtomicXor:
+      case spv::Op::OpAtomicLoad:
+      case spv::Op::OpAtomicStore:
+      case spv::Op::OpAtomicExchange:
+      case spv::Op::OpAtomicIIncrement:
+      case spv::Op::OpAtomicIDecrement:
+      case spv::Op::OpAtomicIAdd:
+      case spv::Op::OpAtomicISub:
+      case spv::Op::OpAtomicSMin:
+      case spv::Op::OpAtomicUMin:
+      case spv::Op::OpAtomicSMax:
+      case spv::Op::OpAtomicUMax:
+      case spv::Op::OpAtomicAnd:
+      case spv::Op::OpAtomicOr:
+      case spv::Op::OpAtomicXor:
         if (use_in_operand_index == 1 || use_in_operand_index == 2) {
           return false;
         }
         break;
-      case SpvOpAtomicCompareExchange:
+      case spv::Op::OpAtomicCompareExchange:
         if (use_in_operand_index == 1 || use_in_operand_index == 2 ||
             use_in_operand_index == 3) {
           return false;
         }
         break;
-      case SpvOpAtomicCompareExchangeWeak:
-      case SpvOpAtomicFlagTestAndSet:
-      case SpvOpAtomicFlagClear:
-      case SpvOpAtomicFAddEXT:
+      case spv::Op::OpAtomicCompareExchangeWeak:
+      case spv::Op::OpAtomicFlagTestAndSet:
+      case spv::Op::OpAtomicFlagClear:
+      case spv::Op::OpAtomicFAddEXT:
         assert(false && "Not allowed with the Shader capability.");
       default:
         break;
@@ -1715,17 +1722,17 @@
 bool MembersHaveBuiltInDecoration(opt::IRContext* ir_context,
                                   uint32_t struct_type_id) {
   const auto* type_inst = ir_context->get_def_use_mgr()->GetDef(struct_type_id);
-  assert(type_inst && type_inst->opcode() == SpvOpTypeStruct &&
+  assert(type_inst && type_inst->opcode() == spv::Op::OpTypeStruct &&
          "|struct_type_id| is not a result id of an OpTypeStruct");
 
   uint32_t builtin_count = 0;
   ir_context->get_def_use_mgr()->ForEachUser(
       type_inst,
       [struct_type_id, &builtin_count](const opt::Instruction* user) {
-        if (user->opcode() == SpvOpMemberDecorate &&
+        if (user->opcode() == spv::Op::OpMemberDecorate &&
             user->GetSingleWordInOperand(0) == struct_type_id &&
-            static_cast<SpvDecoration>(user->GetSingleWordInOperand(2)) ==
-                SpvDecorationBuiltIn) {
+            static_cast<spv::Decoration>(user->GetSingleWordInOperand(2)) ==
+                spv::Decoration::BuiltIn) {
           ++builtin_count;
         }
       });
@@ -1738,9 +1745,11 @@
 }
 
 bool HasBlockOrBufferBlockDecoration(opt::IRContext* ir_context, uint32_t id) {
-  for (auto decoration : {SpvDecorationBlock, SpvDecorationBufferBlock}) {
+  for (auto decoration :
+       {spv::Decoration::Block, spv::Decoration::BufferBlock}) {
     if (!ir_context->get_decoration_mgr()->WhileEachDecoration(
-            id, decoration, [](const opt::Instruction & /*unused*/) -> bool {
+            id, uint32_t(decoration),
+            [](const opt::Instruction & /*unused*/) -> bool {
               return false;
             })) {
       return true;
@@ -1762,7 +1771,7 @@
     if (before_split) {
       // If the instruction comes before the split and its opcode is
       // OpSampledImage, record its result id.
-      if (instruction.opcode() == SpvOpSampledImage) {
+      if (instruction.opcode() == spv::Op::OpSampledImage) {
         sampled_image_result_ids.insert(instruction.result_id());
       }
     } else {
@@ -1784,110 +1793,110 @@
 
 bool InstructionHasNoSideEffects(const opt::Instruction& instruction) {
   switch (instruction.opcode()) {
-    case SpvOpUndef:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpArrayLength:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpCopyLogical:
-    case SpvOpPhi:
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
+    case spv::Op::OpUndef:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpArrayLength:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpCopyLogical:
+    case spv::Op::OpPhi:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
       return true;
     default:
       return false;
@@ -1975,7 +1984,7 @@
 
     for (const auto& inst : block) {
       for (uint32_t i = 0; i < inst.NumInOperands();
-           i += inst.opcode() == SpvOpPhi ? 2 : 1) {
+           i += inst.opcode() == spv::Op::OpPhi ? 2 : 1) {
         const auto& operand = inst.GetInOperand(i);
         if (!spvIsInIdType(operand.type)) {
           continue;
@@ -1994,7 +2003,7 @@
           continue;
         }
 
-        auto domination_target_id = inst.opcode() == SpvOpPhi
+        auto domination_target_id = inst.opcode() == spv::Op::OpPhi
                                         ? inst.GetSingleWordInOperand(i + 1)
                                         : block.id();
 
@@ -2021,68 +2030,68 @@
 // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3582): Add all
 //  opcodes that are agnostic to signedness of operands to function.
 //  This is not exhaustive yet.
-bool IsAgnosticToSignednessOfOperand(SpvOp opcode,
+bool IsAgnosticToSignednessOfOperand(spv::Op opcode,
                                      uint32_t use_in_operand_index) {
   switch (opcode) {
-    case SpvOpSNegate:
-    case SpvOpNot:
-    case SpvOpIAdd:
-    case SpvOpISub:
-    case SpvOpIMul:
-    case SpvOpSDiv:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpNot:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
       return true;
 
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFAddEXT:  // Capability AtomicFloat32AddEXT,
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFAddEXT:  // Capability AtomicFloat32AddEXT,
       // AtomicFloat64AddEXT.
       assert(use_in_operand_index != 0 &&
              "Signedness check should not occur on a pointer operand.");
       return use_in_operand_index == 1 || use_in_operand_index == 2;
 
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:  // Capability Kernel.
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:  // Capability Kernel.
       assert(use_in_operand_index != 0 &&
              "Signedness check should not occur on a pointer operand.");
       return use_in_operand_index >= 1 && use_in_operand_index <= 3;
 
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicFlagTestAndSet:  // Capability Kernel.
-    case SpvOpAtomicFlagClear:       // Capability Kernel.
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicFlagTestAndSet:  // Capability Kernel.
+    case spv::Op::OpAtomicFlagClear:       // Capability Kernel.
       assert(use_in_operand_index != 0 &&
              "Signedness check should not occur on a pointer operand.");
       return use_in_operand_index >= 1;
 
-    case SpvOpAccessChain:
+    case spv::Op::OpAccessChain:
       // The signedness of indices does not matter.
       return use_in_operand_index > 0;
 
@@ -2093,7 +2102,7 @@
   }
 }
 
-bool TypesAreCompatible(opt::IRContext* ir_context, SpvOp opcode,
+bool TypesAreCompatible(opt::IRContext* ir_context, spv::Op opcode,
                         uint32_t use_in_operand_index, uint32_t type_id_1,
                         uint32_t type_id_2) {
   assert(ir_context->get_type_mgr()->GetType(type_id_1) &&
diff --git a/third_party/SPIRV-Tools/source/fuzz/fuzzer_util.h b/third_party/SPIRV-Tools/source/fuzz/fuzzer_util.h
index 54aa14a..374e32e 100644
--- a/third_party/SPIRV-Tools/source/fuzz/fuzzer_util.h
+++ b/third_party/SPIRV-Tools/source/fuzz/fuzzer_util.h
@@ -111,7 +111,7 @@
 // Determines whether it is OK to insert an instruction with opcode |opcode|
 // before |instruction_in_block|.
 bool CanInsertOpcodeBeforeInstruction(
-    SpvOp opcode, const opt::BasicBlock::iterator& instruction_in_block);
+    spv::Op opcode, const opt::BasicBlock::iterator& instruction_in_block);
 
 // Determines whether it is OK to make a synonym of |inst|.
 // |transformation_context| is used to verify that the result id of |inst|
@@ -170,8 +170,8 @@
                                    opt::IRContext* ir_context);
 
 // Returns memory semantics mask for specific storage class.
-SpvMemorySemanticsMask GetMemorySemanticsForStorageClass(
-    SpvStorageClass storage_class);
+spv::MemorySemanticsMask GetMemorySemanticsForStorageClass(
+    spv::StorageClass storage_class);
 
 // Returns true if and only if |context| is valid, according to the validator
 // instantiated with |validator_options|.  |consumer| is used for error
@@ -258,18 +258,18 @@
 
 // Given |pointer_type_inst|, which must be an OpTypePointer instruction,
 // returns the associated storage class.
-SpvStorageClass GetStorageClassFromPointerType(
+spv::StorageClass GetStorageClassFromPointerType(
     opt::Instruction* pointer_type_inst);
 
 // Given |pointer_type_id|, which must be the id of a pointer type, returns the
 // associated storage class.
-SpvStorageClass GetStorageClassFromPointerType(opt::IRContext* context,
-                                               uint32_t pointer_type_id);
+spv::StorageClass GetStorageClassFromPointerType(opt::IRContext* context,
+                                                 uint32_t pointer_type_id);
 
 // Returns the id of a pointer with pointee type |pointee_type_id| and storage
 // class |storage_class|, if it exists, and 0 otherwise.
 uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id,
-                             SpvStorageClass storage_class);
+                             spv::StorageClass storage_class);
 
 // Given an instruction |inst| and an operand absolute index |absolute_index|,
 // returns the index of the operand restricted to the input operands.
@@ -309,7 +309,7 @@
 // Returns a pointer to the new global variable instruction.
 opt::Instruction* AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
                                     uint32_t type_id,
-                                    SpvStorageClass storage_class,
+                                    spv::StorageClass storage_class,
                                     uint32_t initializer_id);
 
 // Adds an instruction to the start of |function_id|, of the form:
@@ -541,7 +541,7 @@
 // opcode |opcode| can be inserted, or nullptr if there is no such instruction.
 opt::Instruction* GetLastInsertBeforeInstruction(opt::IRContext* ir_context,
                                                  uint32_t block_id,
-                                                 SpvOp opcode);
+                                                 spv::Op opcode);
 
 // Checks whether various conditions hold related to the acceptability of
 // replacing the id use at |use_in_operand_index| of |use_instruction| with a
@@ -608,14 +608,14 @@
 // behaviour depending on the signedness of the operand at
 // |use_in_operand_index|.
 // Assumes that the operand must be the id of an integer scalar or vector.
-bool IsAgnosticToSignednessOfOperand(SpvOp opcode,
+bool IsAgnosticToSignednessOfOperand(spv::Op opcode,
                                      uint32_t use_in_operand_index);
 
 // Returns true if |type_id_1| and |type_id_2| represent compatible types
 // given the context of the instruction with |opcode| (i.e. we can replace
 // an operand of |opcode| of the first type with an id of the second type
 // and vice-versa).
-bool TypesAreCompatible(opt::IRContext* ir_context, SpvOp opcode,
+bool TypesAreCompatible(opt::IRContext* ir_context, spv::Op opcode,
                         uint32_t use_in_operand_index, uint32_t type_id_1,
                         uint32_t type_id_2);
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/instruction_descriptor.cpp b/third_party/SPIRV-Tools/source/fuzz/instruction_descriptor.cpp
index fb1ff76..120d8f8 100644
--- a/third_party/SPIRV-Tools/source/fuzz/instruction_descriptor.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/instruction_descriptor.cpp
@@ -40,8 +40,9 @@
              "The skipped instruction count should only be incremented "
              "after the instruction base has been found.");
     }
-    if (found_base && instruction.opcode() ==
-                          instruction_descriptor.target_instruction_opcode()) {
+    if (found_base &&
+        instruction.opcode() ==
+            spv::Op(instruction_descriptor.target_instruction_opcode())) {
       if (num_ignored == instruction_descriptor.num_opcodes_to_ignore()) {
         return &instruction;
       }
@@ -52,11 +53,11 @@
 }
 
 protobufs::InstructionDescriptor MakeInstructionDescriptor(
-    uint32_t base_instruction_result_id, SpvOp target_instruction_opcode,
+    uint32_t base_instruction_result_id, spv::Op target_instruction_opcode,
     uint32_t num_opcodes_to_ignore) {
   protobufs::InstructionDescriptor result;
   result.set_base_instruction_result_id(base_instruction_result_id);
-  result.set_target_instruction_opcode(target_instruction_opcode);
+  result.set_target_instruction_opcode(uint32_t(target_instruction_opcode));
   result.set_num_opcodes_to_ignore(num_opcodes_to_ignore);
   return result;
 }
@@ -64,7 +65,7 @@
 protobufs::InstructionDescriptor MakeInstructionDescriptor(
     const opt::BasicBlock& block,
     const opt::BasicBlock::const_iterator& inst_it) {
-  const SpvOp opcode =
+  const spv::Op opcode =
       inst_it->opcode();    // The opcode of the instruction being described.
   uint32_t skip_count = 0;  // The number of these opcodes we have skipped when
   // searching backwards.
diff --git a/third_party/SPIRV-Tools/source/fuzz/instruction_descriptor.h b/third_party/SPIRV-Tools/source/fuzz/instruction_descriptor.h
index 2ccd15a..063cad4 100644
--- a/third_party/SPIRV-Tools/source/fuzz/instruction_descriptor.h
+++ b/third_party/SPIRV-Tools/source/fuzz/instruction_descriptor.h
@@ -32,7 +32,7 @@
 // components.  See the protobuf definition for details of what these
 // components mean.
 protobufs::InstructionDescriptor MakeInstructionDescriptor(
-    uint32_t base_instruction_result_id, SpvOp target_instruction_opcode,
+    uint32_t base_instruction_result_id, spv::Op target_instruction_opcode,
     uint32_t num_opcodes_to_ignore);
 
 // Returns an instruction descriptor that describing the instruction at
diff --git a/third_party/SPIRV-Tools/source/fuzz/instruction_message.cpp b/third_party/SPIRV-Tools/source/fuzz/instruction_message.cpp
index 9503932..7e8ac71 100644
--- a/third_party/SPIRV-Tools/source/fuzz/instruction_message.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/instruction_message.cpp
@@ -20,10 +20,10 @@
 namespace fuzz {
 
 protobufs::Instruction MakeInstructionMessage(
-    SpvOp opcode, uint32_t result_type_id, uint32_t result_id,
+    spv::Op opcode, uint32_t result_type_id, uint32_t result_id,
     const opt::Instruction::OperandList& input_operands) {
   protobufs::Instruction result;
-  result.set_opcode(opcode);
+  result.set_opcode(uint32_t(opcode));
   result.set_result_type_id(result_type_id);
   result.set_result_id(result_id);
   for (auto& operand : input_operands) {
@@ -71,7 +71,7 @@
   }
   // Create and return the instruction.
   return MakeUnique<opt::Instruction>(
-      ir_context, static_cast<SpvOp>(instruction_message.opcode()),
+      ir_context, static_cast<spv::Op>(instruction_message.opcode()),
       instruction_message.result_type_id(), instruction_message.result_id(),
       in_operands);
 }
diff --git a/third_party/SPIRV-Tools/source/fuzz/instruction_message.h b/third_party/SPIRV-Tools/source/fuzz/instruction_message.h
index fcbb4c7..e1312f4 100644
--- a/third_party/SPIRV-Tools/source/fuzz/instruction_message.h
+++ b/third_party/SPIRV-Tools/source/fuzz/instruction_message.h
@@ -26,7 +26,7 @@
 
 // Creates an Instruction protobuf message from its component parts.
 protobufs::Instruction MakeInstructionMessage(
-    SpvOp opcode, uint32_t result_type_id, uint32_t result_id,
+    spv::Op opcode, uint32_t result_type_id, uint32_t result_id,
     const opt::Instruction::OperandList& input_operands);
 
 // Creates an Instruction protobuf message from a parsed instruction.
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_access_chain.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_access_chain.cpp
index 3fe9e65..1e7f87b 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_access_chain.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_access_chain.cpp
@@ -63,7 +63,7 @@
   }
   // The type must indeed be a pointer.
   auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
-  if (pointer_type->opcode() != SpvOpTypePointer) {
+  if (pointer_type->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
@@ -75,7 +75,7 @@
     return false;
   }
   if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-          SpvOpAccessChain, instruction_to_insert_before)) {
+          spv::Op::OpAccessChain, instruction_to_insert_before)) {
     return false;
   }
 
@@ -83,8 +83,8 @@
   // we do not want to allow accessing such pointers.  This might be acceptable
   // in dead blocks, but we conservatively avoid it.
   switch (pointer->opcode()) {
-    case SpvOpConstantNull:
-    case SpvOpUndef:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpUndef:
       assert(
           false &&
           "Access chains should not be created from null/undefined pointers");
@@ -117,7 +117,7 @@
 
     // Check whether the object is a struct.
     if (ir_context->get_def_use_mgr()->GetDef(subobject_type_id)->opcode() ==
-        SpvOpTypeStruct) {
+        spv::Op::OpTypeStruct) {
       // It is a struct: we need to retrieve the integer value.
 
       bool successful;
@@ -202,7 +202,7 @@
   // associated with pointers to isomorphic structs being regarded as the same.
   return fuzzerutil::MaybeGetPointerType(
              ir_context, subobject_type_id,
-             static_cast<SpvStorageClass>(
+             static_cast<spv::StorageClass>(
                  pointer_type->GetSingleWordInOperand(0))) != 0;
 }
 
@@ -243,7 +243,7 @@
 
     // Check whether the object is a struct.
     if (ir_context->get_def_use_mgr()->GetDef(subobject_type_id)->opcode() ==
-        SpvOpTypeStruct) {
+        spv::Op::OpTypeStruct) {
       // It is a struct: we need to retrieve the integer value.
 
       index_value =
@@ -290,7 +290,8 @@
       //   %fresh_ids.first = OpULessThanEqual %bool %int_id %bound_minus_one.
       fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.first());
       auto comparison_instruction = MakeUnique<opt::Instruction>(
-          ir_context, SpvOpULessThanEqual, bool_type_id, fresh_ids.first(),
+          ir_context, spv::Op::OpULessThanEqual, bool_type_id,
+          fresh_ids.first(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {index_instruction->result_id()}},
                {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}}));
@@ -306,7 +307,7 @@
       //                           %bound_minus_one
       fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.second());
       auto select_instruction = MakeUnique<opt::Instruction>(
-          ir_context, SpvOpSelect, int_type_inst->result_id(),
+          ir_context, spv::Op::OpSelect, int_type_inst->result_id(),
           fresh_ids.second(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {fresh_ids.first()}},
@@ -334,13 +335,14 @@
   // of the original pointer.
   uint32_t result_type = fuzzerutil::MaybeGetPointerType(
       ir_context, subobject_type_id,
-      static_cast<SpvStorageClass>(pointer_type->GetSingleWordInOperand(0)));
+      static_cast<spv::StorageClass>(pointer_type->GetSingleWordInOperand(0)));
 
   // Add the access chain instruction to the module, and update the module's
   // id bound.
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
-  auto access_chain_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpAccessChain, result_type, message_.fresh_id(), operands);
+  auto access_chain_instruction =
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpAccessChain,
+                                   result_type, message_.fresh_id(), operands);
   auto access_chain_instruction_ptr = access_chain_instruction.get();
   instruction_to_insert_before->InsertBefore(
       std::move(access_chain_instruction));
@@ -367,7 +369,7 @@
     opt::IRContext* ir_context, uint32_t index_id,
     uint32_t object_type_id) const {
   assert(ir_context->get_def_use_mgr()->GetDef(object_type_id)->opcode() ==
-             SpvOpTypeStruct &&
+             spv::Op::OpTypeStruct &&
          "Precondition: the type must be a struct type.");
   if (!ValidIndexToComposite(ir_context, index_id, object_type_id)) {
     return {false, 0};
@@ -408,14 +410,14 @@
   // The index type must be 32-bit integer.
   auto index_type =
       ir_context->get_def_use_mgr()->GetDef(index_instruction->type_id());
-  if (index_type->opcode() != SpvOpTypeInt ||
+  if (index_type->opcode() != spv::Op::OpTypeInt ||
       index_type->GetSingleWordInOperand(0) != 32) {
     return false;
   }
 
   // If the object being traversed is a struct, the id must correspond to an
   // in-bound constant.
-  if (object_type_def->opcode() == SpvOpTypeStruct) {
+  if (object_type_def->opcode() == spv::Op::OpTypeStruct) {
     if (!spvOpcodeIsConstant(index_instruction->opcode())) {
       return false;
     }
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_bit_instruction_synonym.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_bit_instruction_synonym.cpp
index 636c0a3..4b26c2b 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_bit_instruction_synonym.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_bit_instruction_synonym.cpp
@@ -87,10 +87,10 @@
   // synonym fact.  The helper function should take care of invalidating
   // analyses before adding facts.
   switch (bit_instruction->opcode()) {
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
       AddOpBitwiseOrOpNotSynonym(ir_context, transformation_context,
                                  bit_instruction);
       break;
@@ -106,10 +106,10 @@
   //  Right now we only support certain operations. When this issue is addressed
   //  the following conditional can use the function |spvOpcodeIsBit|.
   // |instruction| must be defined and must be a supported bit instruction.
-  if (!instruction || (instruction->opcode() != SpvOpBitwiseOr &&
-                       instruction->opcode() != SpvOpBitwiseXor &&
-                       instruction->opcode() != SpvOpBitwiseAnd &&
-                       instruction->opcode() != SpvOpNot)) {
+  if (!instruction || (instruction->opcode() != spv::Op::OpBitwiseOr &&
+                       instruction->opcode() != spv::Op::OpBitwiseXor &&
+                       instruction->opcode() != spv::Op::OpBitwiseAnd &&
+                       instruction->opcode() != spv::Op::OpNot)) {
     return false;
   }
 
@@ -119,7 +119,7 @@
     return false;
   }
 
-  if (instruction->opcode() == SpvOpNot) {
+  if (instruction->opcode() == spv::Op::OpNot) {
     auto operand = instruction->GetInOperand(0).words[0];
     auto operand_inst = ir_context->get_def_use_mgr()->GetDef(operand);
     auto operand_type =
@@ -171,10 +171,10 @@
   // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3557):
   //  Right now, only certain operations are supported.
   switch (bit_instruction->opcode()) {
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
       return (2 + bit_instruction->NumInOperands()) *
                  ir_context->get_type_mgr()
                      ->GetType(bit_instruction->type_id())
@@ -220,7 +220,7 @@
     for (auto operand = bit_instruction->begin() + 2;
          operand != bit_instruction->end(); operand++) {
       auto bit_extract =
-          opt::Instruction(ir_context, SpvOpBitFieldUExtract,
+          opt::Instruction(ir_context, spv::Op::OpBitFieldUExtract,
                            bit_instruction->type_id(), *fresh_id++,
                            {{SPV_OPERAND_TYPE_ID, operand->words},
                             {SPV_OPERAND_TYPE_ID, {offset}},
@@ -246,12 +246,13 @@
   // first two bits of the result.
   uint32_t offset = fuzzerutil::MaybeGetIntegerConstant(
       ir_context, *transformation_context, {1}, 32, false, false);
-  auto bit_insert = opt::Instruction(
-      ir_context, SpvOpBitFieldInsert, bit_instruction->type_id(), *fresh_id++,
-      {{SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[0]}},
-       {SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[1]}},
-       {SPV_OPERAND_TYPE_ID, {offset}},
-       {SPV_OPERAND_TYPE_ID, {count}}});
+  auto bit_insert =
+      opt::Instruction(ir_context, spv::Op::OpBitFieldInsert,
+                       bit_instruction->type_id(), *fresh_id++,
+                       {{SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[0]}},
+                        {SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[1]}},
+                        {SPV_OPERAND_TYPE_ID, {offset}},
+                        {SPV_OPERAND_TYPE_ID, {count}}});
   bit_instruction->InsertBefore(MakeUnique<opt::Instruction>(bit_insert));
   fuzzerutil::UpdateModuleIdBound(ir_context, bit_insert.result_id());
 
@@ -260,7 +261,7 @@
     offset = fuzzerutil::MaybeGetIntegerConstant(
         ir_context, *transformation_context, {i}, 32, false, false);
     bit_insert = opt::Instruction(
-        ir_context, SpvOpBitFieldInsert, bit_instruction->type_id(),
+        ir_context, spv::Op::OpBitFieldInsert, bit_instruction->type_id(),
         *fresh_id++,
         {{SPV_OPERAND_TYPE_ID, {bit_insert.result_id()}},
          {SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[i]}},
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_boolean.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_boolean.cpp
index 3935432..89c2e57 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_boolean.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_boolean.cpp
@@ -43,7 +43,8 @@
   // Add the boolean constant to the module, ensuring the module's id bound is
   // high enough.
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, message_.is_true() ? SpvOpConstantTrue : SpvOpConstantFalse,
+      ir_context,
+      message_.is_true() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse,
       fuzzerutil::MaybeGetBoolType(ir_context), message_.fresh_id(),
       opt::Instruction::OperandList());
   auto new_instruction_ptr = new_instruction.get();
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_composite.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_composite.cpp
index 89007ab..b8ee8be 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_composite.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_composite.cpp
@@ -53,7 +53,7 @@
   // struct - whether its decorations are OK.
   std::vector<uint32_t> constituent_type_ids;
   switch (composite_type_instruction->opcode()) {
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       for (uint32_t index = 0;
            index <
            fuzzerutil::GetArraySize(*composite_type_instruction, ir_context);
@@ -62,8 +62,8 @@
             composite_type_instruction->GetSingleWordInOperand(0));
       }
       break;
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       for (uint32_t index = 0;
            index < composite_type_instruction->GetSingleWordInOperand(1);
            index++) {
@@ -71,7 +71,7 @@
             composite_type_instruction->GetSingleWordInOperand(0));
       }
       break;
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       // We do not create constants of structs decorated with Block nor
       // BufferBlock.  The SPIR-V spec does not explicitly disallow this, but it
       // seems like a strange thing to do, so we disallow it to avoid triggering
@@ -120,7 +120,7 @@
     in_operands.push_back({SPV_OPERAND_TYPE_ID, {constituent_id}});
   }
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpConstantComposite, message_.type_id(),
+      ir_context, spv::Op::OpConstantComposite, message_.type_id(),
       message_.fresh_id(), in_operands);
   auto new_instruction_ptr = new_instruction.get();
   ir_context->module()->AddGlobalValue(std::move(new_instruction));
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_null.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_null.cpp
index c0f7367..7b83bae 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_null.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_null.cpp
@@ -48,8 +48,8 @@
 void TransformationAddConstantNull::Apply(
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpConstantNull, message_.type_id(), message_.fresh_id(),
-      opt::Instruction::OperandList());
+      ir_context, spv::Op::OpConstantNull, message_.type_id(),
+      message_.fresh_id(), opt::Instruction::OperandList());
   auto new_instruction_ptr = new_instruction.get();
   ir_context->module()->AddGlobalValue(std::move(new_instruction));
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_scalar.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_scalar.cpp
index a2d95fb..45989d4 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_scalar.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_constant_scalar.cpp
@@ -65,7 +65,7 @@
     opt::IRContext* ir_context,
     TransformationContext* transformation_context) const {
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpConstant, message_.type_id(), message_.fresh_id(),
+      ir_context, spv::Op::OpConstant, message_.type_id(), message_.fresh_id(),
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_LITERAL_INTEGER,
             std::vector<uint32_t>(message_.word().begin(),
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_copy_memory.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_copy_memory.cpp
index 5eb4bdc..9d1f325 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_copy_memory.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_copy_memory.cpp
@@ -27,12 +27,12 @@
 
 TransformationAddCopyMemory::TransformationAddCopyMemory(
     const protobufs::InstructionDescriptor& instruction_descriptor,
-    uint32_t fresh_id, uint32_t source_id, SpvStorageClass storage_class,
+    uint32_t fresh_id, uint32_t source_id, spv::StorageClass storage_class,
     uint32_t initializer_id) {
   *message_.mutable_instruction_descriptor() = instruction_descriptor;
   message_.set_fresh_id(fresh_id);
   message_.set_source_id(source_id);
-  message_.set_storage_class(storage_class);
+  message_.set_storage_class(uint32_t(storage_class));
   message_.set_initializer_id(initializer_id);
 }
 
@@ -53,7 +53,8 @@
   // Check that we can insert OpCopyMemory before |instruction_descriptor|.
   auto iter = fuzzerutil::GetIteratorForInstruction(
       ir_context->get_instr_block(inst), inst);
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyMemory, iter)) {
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyMemory,
+                                                    iter)) {
     return false;
   }
 
@@ -65,8 +66,10 @@
   }
 
   // |storage_class| is either Function or Private.
-  if (message_.storage_class() != SpvStorageClassFunction &&
-      message_.storage_class() != SpvStorageClassPrivate) {
+  if (spv::StorageClass(message_.storage_class()) !=
+          spv::StorageClass::Function &&
+      spv::StorageClass(message_.storage_class()) !=
+          spv::StorageClass::Private) {
     return false;
   }
 
@@ -76,7 +79,7 @@
   // OpTypePointer with |message_.storage_class| exists.
   if (!fuzzerutil::MaybeGetPointerType(
           ir_context, pointee_type_id,
-          static_cast<SpvStorageClass>(message_.storage_class()))) {
+          static_cast<spv::StorageClass>(message_.storage_class()))) {
     return false;
   }
 
@@ -103,20 +106,20 @@
       ir_context->get_instr_block(insert_before_inst);
 
   // Add global or local variable to copy memory into.
-  auto storage_class = static_cast<SpvStorageClass>(message_.storage_class());
+  auto storage_class = static_cast<spv::StorageClass>(message_.storage_class());
   auto type_id = fuzzerutil::MaybeGetPointerType(
       ir_context,
       fuzzerutil::GetPointeeTypeIdFromPointerType(
           ir_context, fuzzerutil::GetTypeId(ir_context, message_.source_id())),
       storage_class);
 
-  if (storage_class == SpvStorageClassPrivate) {
+  if (storage_class == spv::StorageClass::Private) {
     opt::Instruction* new_global =
         fuzzerutil::AddGlobalVariable(ir_context, message_.fresh_id(), type_id,
                                       storage_class, message_.initializer_id());
     ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_global);
   } else {
-    assert(storage_class == SpvStorageClassFunction &&
+    assert(storage_class == spv::StorageClass::Function &&
            "Storage class can be either Private or Function");
     opt::Function* enclosing_function = enclosing_block->GetParent();
     opt::Instruction* new_local = fuzzerutil::AddLocalVariable(
@@ -130,7 +133,7 @@
       enclosing_block, insert_before_inst);
 
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCopyMemory, 0, 0,
+      ir_context, spv::Op::OpCopyMemory, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}},
           {SPV_OPERAND_TYPE_ID, {message_.source_id()}}});
@@ -160,7 +163,8 @@
 bool TransformationAddCopyMemory::IsInstructionSupported(
     opt::IRContext* ir_context, opt::Instruction* inst) {
   if (!inst->result_id() || !inst->type_id() ||
-      inst->opcode() == SpvOpConstantNull || inst->opcode() == SpvOpUndef) {
+      inst->opcode() == spv::Op::OpConstantNull ||
+      inst->opcode() == spv::Op::OpUndef) {
     return false;
   }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_copy_memory.h b/third_party/SPIRV-Tools/source/fuzz/transformation_add_copy_memory.h
index b25652f..053b629 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_copy_memory.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_copy_memory.h
@@ -30,7 +30,7 @@
 
   TransformationAddCopyMemory(
       const protobufs::InstructionDescriptor& instruction_descriptor,
-      uint32_t fresh_id, uint32_t source_id, SpvStorageClass storage_class,
+      uint32_t fresh_id, uint32_t source_id, spv::StorageClass storage_class,
       uint32_t initializer_id);
 
   // - |instruction_descriptor| must point to a valid instruction in the module.
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_block.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_block.cpp
index df700ce..930adc1 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_block.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_block.cpp
@@ -61,7 +61,7 @@
   }
 
   // It must end with OpBranch.
-  if (existing_block->terminator()->opcode() != SpvOpBranch) {
+  if (existing_block->terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
@@ -122,27 +122,27 @@
   auto enclosing_function = existing_block->GetParent();
   std::unique_ptr<opt::BasicBlock> new_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.fresh_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.fresh_id(),
           opt::Instruction::OperandList()));
   new_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {successor_block_id}}})));
 
   // Turn the original block into a selection merge, with its original successor
   // as the merge block.
   existing_block->terminator()->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {successor_block_id}},
            {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-            {SpvSelectionControlMaskNone}}})));
+            {uint32_t(spv::SelectionControlMask::MaskNone)}}})));
 
   // Change the original block's terminator to be a conditional branch on the
   // given boolean, with the original successor and the new successor as branch
   // targets, and such that at runtime control will always transfer to the
   // original successor.
-  existing_block->terminator()->SetOpcode(SpvOpBranchConditional);
+  existing_block->terminator()->SetOpcode(spv::Op::OpBranchConditional);
   existing_block->terminator()->SetInOperands(
       {{SPV_OPERAND_TYPE_ID, {bool_id}},
        {SPV_OPERAND_TYPE_ID,
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_break.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_break.cpp
index 32080ca..07ed4dc 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_break.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_break.cpp
@@ -142,7 +142,7 @@
   }
 
   // Check that |message_.from_block| ends with an unconditional branch.
-  if (bb_from->terminator()->opcode() != SpvOpBranch) {
+  if (bb_from->terminator()->opcode() != spv::Op::OpBranch) {
     // The block associated with the id does not end with an unconditional
     // branch.
     return false;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_continue.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_continue.cpp
index f2b9ab3..c534801 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_continue.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_dead_continue.cpp
@@ -55,7 +55,7 @@
   }
 
   // Check that |message_.from_block| ends with an unconditional branch.
-  if (bb_from->terminator()->opcode() != SpvOpBranch) {
+  if (bb_from->terminator()->opcode() != spv::Op::OpBranch) {
     // The block associated with the id does not end with an unconditional
     // branch.
     return false;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_early_terminator_wrapper.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_early_terminator_wrapper.cpp
index 547398a..28e0186 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_early_terminator_wrapper.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_early_terminator_wrapper.cpp
@@ -28,17 +28,17 @@
 TransformationAddEarlyTerminatorWrapper::
     TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id,
                                             uint32_t label_fresh_id,
-                                            SpvOp opcode) {
+                                            spv::Op opcode) {
   message_.set_function_fresh_id(function_fresh_id);
   message_.set_label_fresh_id(label_fresh_id);
-  message_.set_opcode(opcode);
+  message_.set_opcode(uint32_t(opcode));
 }
 
 bool TransformationAddEarlyTerminatorWrapper::IsApplicable(
     opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
-  assert((message_.opcode() == SpvOpKill ||
-          message_.opcode() == SpvOpUnreachable ||
-          message_.opcode() == SpvOpTerminateInvocation) &&
+  assert((spv::Op(message_.opcode()) == spv::Op::OpKill ||
+          spv::Op(message_.opcode()) == spv::Op::OpUnreachable ||
+          spv::Op(message_.opcode()) == spv::Op::OpTerminateInvocation) &&
          "Invalid opcode.");
 
   if (!fuzzerutil::IsFreshId(ir_context, message_.function_fresh_id())) {
@@ -66,26 +66,29 @@
   // %label_fresh_id = OpLabel
   //                   OpKill|Unreachable|TerminateInvocation
   auto basic_block = MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLabel, 0, message_.label_fresh_id(),
+      ir_context, spv::Op::OpLabel, 0, message_.label_fresh_id(),
       opt::Instruction::OperandList()));
   basic_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, static_cast<SpvOp>(message_.opcode()), 0, 0,
+      ir_context, static_cast<spv::Op>(message_.opcode()), 0, 0,
       opt::Instruction::OperandList()));
 
   // Create a zero-argument void function.
   auto void_type_id = fuzzerutil::MaybeGetVoidType(ir_context);
   auto function = MakeUnique<opt::Function>(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunction, void_type_id, message_.function_fresh_id(),
+      ir_context, spv::Op::OpFunction, void_type_id,
+      message_.function_fresh_id(),
       opt::Instruction::OperandList(
-          {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
+          {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+            {uint32_t(spv::FunctionControlMask::MaskNone)}},
            {SPV_OPERAND_TYPE_TYPE_ID,
             {fuzzerutil::FindFunctionType(ir_context, {void_type_id})}}})));
 
   // Add the basic block to the function as the sole block, and add the function
   // to the module.
   function->AddBasicBlock(std::move(basic_block));
-  function->SetFunctionEnd(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionEnd, 0, 0, opt::Instruction::OperandList()));
+  function->SetFunctionEnd(
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpFunctionEnd, 0, 0,
+                                   opt::Instruction::OperandList()));
   ir_context->module()->AddFunction(std::move(function));
 
   ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_early_terminator_wrapper.h b/third_party/SPIRV-Tools/source/fuzz/transformation_add_early_terminator_wrapper.h
index 97cc527..5d0201d 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_early_terminator_wrapper.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_early_terminator_wrapper.h
@@ -30,7 +30,7 @@
 
   TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id,
                                           uint32_t label_fresh_id,
-                                          SpvOp opcode);
+                                          spv::Op opcode);
 
   // - |message_.function_fresh_id| and |message_.label_fresh_id| must be fresh
   //   and distinct.
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_function.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_function.cpp
index 06cd657..1f61ede 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_function.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_function.cpp
@@ -178,7 +178,7 @@
   }
   ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 
-  assert(message_.instruction(0).opcode() == SpvOpFunction &&
+  assert(spv::Op(message_.instruction(0).opcode()) == spv::Op::OpFunction &&
          "The first instruction of an 'add function' transformation must be "
          "OpFunction.");
 
@@ -189,7 +189,7 @@
   } else {
     // Inform the fact manager that all blocks in the function are dead.
     for (auto& inst : message_.instruction()) {
-      if (inst.opcode() == SpvOpLabel) {
+      if (spv::Op(inst.opcode()) == spv::Op::OpLabel) {
         transformation_context->GetFactManager()->AddFactBlockIsDead(
             inst.result_id());
       }
@@ -202,16 +202,16 @@
   // parameters to other functions knowing that it is OK if they get
   // over-written.
   for (auto& instruction : message_.instruction()) {
-    switch (instruction.opcode()) {
-      case SpvOpFunctionParameter:
+    switch (spv::Op(instruction.opcode())) {
+      case spv::Op::OpFunctionParameter:
         if (ir_context->get_def_use_mgr()
                 ->GetDef(instruction.result_type_id())
-                ->opcode() == SpvOpTypePointer) {
+                ->opcode() == spv::Op::OpTypePointer) {
           transformation_context->GetFactManager()
               ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
         }
         break;
-      case SpvOpVariable:
+      case spv::Op::OpVariable:
         transformation_context->GetFactManager()
             ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
         break;
@@ -239,7 +239,7 @@
 
   // A function must start with OpFunction.
   auto function_begin = message_.instruction(0);
-  if (function_begin.opcode() != SpvOpFunction) {
+  if (spv::Op(function_begin.opcode()) != spv::Op::OpFunction) {
     return false;
   }
 
@@ -256,8 +256,8 @@
   // Iterate through all function parameter instructions, adding parameters to
   // the new function.
   while (instruction_index < num_instructions &&
-         message_.instruction(instruction_index).opcode() ==
-             SpvOpFunctionParameter) {
+         spv::Op(message_.instruction(instruction_index).opcode()) ==
+             spv::Op::OpFunctionParameter) {
     new_function->AddParameter(InstructionFromMessage(
         ir_context, message_.instruction(instruction_index)));
     instruction_index++;
@@ -265,16 +265,19 @@
 
   // After the parameters, there needs to be a label.
   if (instruction_index == num_instructions ||
-      message_.instruction(instruction_index).opcode() != SpvOpLabel) {
+      spv::Op(message_.instruction(instruction_index).opcode()) !=
+          spv::Op::OpLabel) {
     return false;
   }
 
   // Iterate through the instructions block by block until the end of the
   // function is reached.
   while (instruction_index < num_instructions &&
-         message_.instruction(instruction_index).opcode() != SpvOpFunctionEnd) {
+         spv::Op(message_.instruction(instruction_index).opcode()) !=
+             spv::Op::OpFunctionEnd) {
     // Invariant: we should always be at a label instruction at this point.
-    assert(message_.instruction(instruction_index).opcode() == SpvOpLabel);
+    assert(spv::Op(message_.instruction(instruction_index).opcode()) ==
+           spv::Op::OpLabel);
 
     // Make a basic block using the label instruction.
     std::unique_ptr<opt::BasicBlock> block =
@@ -285,9 +288,10 @@
     // of the function, adding each such instruction to the block.
     instruction_index++;
     while (instruction_index < num_instructions &&
-           message_.instruction(instruction_index).opcode() !=
-               SpvOpFunctionEnd &&
-           message_.instruction(instruction_index).opcode() != SpvOpLabel) {
+           spv::Op(message_.instruction(instruction_index).opcode()) !=
+               spv::Op::OpFunctionEnd &&
+           spv::Op(message_.instruction(instruction_index).opcode()) !=
+               spv::Op::OpLabel) {
       block->AddInstruction(InstructionFromMessage(
           ir_context, message_.instruction(instruction_index)));
       instruction_index++;
@@ -298,7 +302,8 @@
   // Having considered all the blocks, we should be at the last instruction and
   // it needs to be OpFunctionEnd.
   if (instruction_index != num_instructions - 1 ||
-      message_.instruction(instruction_index).opcode() != SpvOpFunctionEnd) {
+      spv::Op(message_.instruction(instruction_index).opcode()) !=
+          spv::Op::OpFunctionEnd) {
     return false;
   }
   // Set the function's final instruction, add the function to the module and
@@ -339,20 +344,20 @@
   for (auto& block : *added_function) {
     for (auto& inst : block) {
       switch (inst.opcode()) {
-        case SpvOpKill:
-        case SpvOpUnreachable:
+        case spv::Op::OpKill:
+        case spv::Op::OpUnreachable:
           if (!TryToTurnKillOrUnreachableIntoReturn(ir_context, added_function,
                                                     &inst)) {
             return false;
           }
           break;
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain:
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain:
           if (!TryToClampAccessChainIndices(ir_context, &inst)) {
             return false;
           }
           break;
-        case SpvOpFunctionCall:
+        case spv::Op::OpFunctionCall:
           // A livesafe function my only call other livesafe functions.
           if (!transformation_context.GetFactManager()->FunctionIsLivesafe(
                   inst.GetSingleWordInOperand(0))) {
@@ -404,7 +409,7 @@
   auto loop_limit_constant_id_instr =
       ir_context->get_def_use_mgr()->GetDef(message_.loop_limit_constant_id());
   if (!loop_limit_constant_id_instr ||
-      loop_limit_constant_id_instr->opcode() != SpvOpConstant) {
+      loop_limit_constant_id_instr->opcode() != spv::Op::OpConstant) {
     // The loop limit constant id instruction must exist and have an
     // appropriate opcode.
     return false;
@@ -412,7 +417,7 @@
 
   auto loop_limit_type = ir_context->get_def_use_mgr()->GetDef(
       loop_limit_constant_id_instr->type_id());
-  if (loop_limit_type->opcode() != SpvOpTypeInt ||
+  if (loop_limit_type->opcode() != spv::Op::OpTypeInt ||
       loop_limit_type->GetSingleWordInOperand(0) != 32) {
     // The type of the loop limit constant must be 32-bit integer.  It
     // doesn't actually matter whether the integer is signed or not.
@@ -457,7 +462,7 @@
 
   // Look for pointer-to-unsigned int type.
   opt::analysis::Pointer pointer_to_unsigned_int_type(
-      registered_unsigned_int_type, SpvStorageClassFunction);
+      registered_unsigned_int_type, spv::StorageClass::Function);
   uint32_t pointer_to_unsigned_int_type_id =
       ir_context->get_type_mgr()->GetId(&pointer_to_unsigned_int_type);
   if (!pointer_to_unsigned_int_type_id) {
@@ -477,13 +482,13 @@
 
   // Declare the loop limiter variable at the start of the function's entry
   // block, via an instruction of the form:
-  //   %loop_limiter_var = SpvOpVariable %ptr_to_uint Function %zero
+  //   %loop_limiter_var = spv::Op::OpVariable %ptr_to_uint Function %zero
   added_function->begin()->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpVariable, pointer_to_unsigned_int_type_id,
+      ir_context, spv::Op::OpVariable, pointer_to_unsigned_int_type_id,
       message_.loop_limiter_variable_id(),
-      opt::Instruction::OperandList(
-          {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
-           {SPV_OPERAND_TYPE_ID, {zero_id}}})));
+      opt::Instruction::OperandList({{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                      {uint32_t(spv::StorageClass::Function)}},
+                                     {SPV_OPERAND_TYPE_ID, {zero_id}}})));
   // Update the module's id bound since we have added the loop limiter
   // variable id.
   fuzzerutil::UpdateModuleIdBound(ir_context,
@@ -589,10 +594,11 @@
     auto back_edge_block = ir_context->cfg()->block(back_edge_block_id);
     auto back_edge_block_terminator = back_edge_block->terminator();
     bool compare_using_greater_than_equal;
-    if (back_edge_block_terminator->opcode() == SpvOpBranch) {
+    if (back_edge_block_terminator->opcode() == spv::Op::OpBranch) {
       compare_using_greater_than_equal = true;
     } else {
-      assert(back_edge_block_terminator->opcode() == SpvOpBranchConditional);
+      assert(back_edge_block_terminator->opcode() ==
+             spv::Op::OpBranchConditional);
       assert(((back_edge_block_terminator->GetSingleWordInOperand(1) ==
                    loop_header->id() &&
                back_edge_block_terminator->GetSingleWordInOperand(2) ==
@@ -613,7 +619,7 @@
     // Add a load from the loop limiter variable, of the form:
     //   %t1 = OpLoad %uint32 %loop_limiter
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpLoad, unsigned_int_type_id,
+        ir_context, spv::Op::OpLoad, unsigned_int_type_id,
         loop_limiter_info.load_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}}})));
@@ -621,7 +627,7 @@
     // Increment the loaded value:
     //   %t2 = OpIAdd %uint32 %t1 %one
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpIAdd, unsigned_int_type_id,
+        ir_context, spv::Op::OpIAdd, unsigned_int_type_id,
         loop_limiter_info.increment_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}},
@@ -630,7 +636,7 @@
     // Store the incremented value back to the loop limiter variable:
     //   OpStore %loop_limiter %t2
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpStore, 0, 0,
+        ir_context, spv::Op::OpStore, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}},
              {SPV_OPERAND_TYPE_ID, {loop_limiter_info.increment_id()}}})));
@@ -641,17 +647,18 @@
     //   %t3 = OpULessThan %bool %t1 %loop_limit
     new_instructions.push_back(MakeUnique<opt::Instruction>(
         ir_context,
-        compare_using_greater_than_equal ? SpvOpUGreaterThanEqual
-                                         : SpvOpULessThan,
+        compare_using_greater_than_equal ? spv::Op::OpUGreaterThanEqual
+                                         : spv::Op::OpULessThan,
         bool_type_id, loop_limiter_info.compare_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}},
              {SPV_OPERAND_TYPE_ID, {message_.loop_limit_constant_id()}}})));
 
-    if (back_edge_block_terminator->opcode() == SpvOpBranchConditional) {
+    if (back_edge_block_terminator->opcode() == spv::Op::OpBranchConditional) {
       new_instructions.push_back(MakeUnique<opt::Instruction>(
           ir_context,
-          compare_using_greater_than_equal ? SpvOpLogicalOr : SpvOpLogicalAnd,
+          compare_using_greater_than_equal ? spv::Op::OpLogicalOr
+                                           : spv::Op::OpLogicalAnd,
           bool_type_id, loop_limiter_info.logical_op_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID,
@@ -669,11 +676,11 @@
       back_edge_block_terminator->InsertBefore(std::move(new_instructions));
     }
 
-    if (back_edge_block_terminator->opcode() == SpvOpBranchConditional) {
+    if (back_edge_block_terminator->opcode() == spv::Op::OpBranchConditional) {
       back_edge_block_terminator->SetInOperand(
           0, {loop_limiter_info.logical_op_id()});
     } else {
-      assert(back_edge_block_terminator->opcode() == SpvOpBranch &&
+      assert(back_edge_block_terminator->opcode() == spv::Op::OpBranch &&
              "Back-edge terminator must be OpBranch or OpBranchConditional");
 
       // Check that, if the merge block starts with OpPhi instructions, suitable
@@ -689,7 +696,7 @@
       // Augment OpPhi instructions at the loop merge with the given ids.
       uint32_t phi_index = 0;
       for (auto& inst : *merge_block) {
-        if (inst.opcode() != SpvOpPhi) {
+        if (inst.opcode() != spv::Op::OpPhi) {
           break;
         }
         assert(phi_index <
@@ -702,7 +709,7 @@
       }
 
       // Add the new edge, by changing OpBranch to OpBranchConditional.
-      back_edge_block_terminator->SetOpcode(SpvOpBranchConditional);
+      back_edge_block_terminator->SetOpcode(spv::Op::OpBranchConditional);
       back_edge_block_terminator->SetInOperands(opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.compare_id()}},
            {SPV_OPERAND_TYPE_ID, {loop_header->MergeBlockId()}},
@@ -724,18 +731,18 @@
 bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
     opt::IRContext* ir_context, opt::Function* added_function,
     opt::Instruction* kill_or_unreachable_inst) const {
-  assert((kill_or_unreachable_inst->opcode() == SpvOpKill ||
-          kill_or_unreachable_inst->opcode() == SpvOpUnreachable) &&
+  assert((kill_or_unreachable_inst->opcode() == spv::Op::OpKill ||
+          kill_or_unreachable_inst->opcode() == spv::Op::OpUnreachable) &&
          "Precondition: instruction must be OpKill or OpUnreachable.");
 
   // Get the function's return type.
   auto function_return_type_inst =
       ir_context->get_def_use_mgr()->GetDef(added_function->type_id());
 
-  if (function_return_type_inst->opcode() == SpvOpTypeVoid) {
+  if (function_return_type_inst->opcode() == spv::Op::OpTypeVoid) {
     // The function has void return type, so change this instruction to
     // OpReturn.
-    kill_or_unreachable_inst->SetOpcode(SpvOpReturn);
+    kill_or_unreachable_inst->SetOpcode(spv::Op::OpReturn);
   } else {
     // The function has non-void return type, so change this instruction
     // to OpReturnValue, using the value id provided with the
@@ -749,7 +756,7 @@
             ->type_id() != function_return_type_inst->result_id()) {
       return false;
     }
-    kill_or_unreachable_inst->SetOpcode(SpvOpReturnValue);
+    kill_or_unreachable_inst->SetOpcode(spv::Op::OpReturnValue);
     kill_or_unreachable_inst->SetInOperands(
         {{SPV_OPERAND_TYPE_ID, {message_.kill_unreachable_return_value_id()}}});
   }
@@ -758,8 +765,8 @@
 
 bool TransformationAddFunction::TryToClampAccessChainIndices(
     opt::IRContext* ir_context, opt::Instruction* access_chain_inst) const {
-  assert((access_chain_inst->opcode() == SpvOpAccessChain ||
-          access_chain_inst->opcode() == SpvOpInBoundsAccessChain) &&
+  assert((access_chain_inst->opcode() == spv::Op::OpAccessChain ||
+          access_chain_inst->opcode() == spv::Op::OpInBoundsAccessChain) &&
          "Precondition: instruction must be OpAccessChain or "
          "OpInBoundsAccessChain.");
 
@@ -793,7 +800,7 @@
   assert(base_object && "The base object must exist.");
   auto pointer_type =
       ir_context->get_def_use_mgr()->GetDef(base_object->type_id());
-  assert(pointer_type && pointer_type->opcode() == SpvOpTypePointer &&
+  assert(pointer_type && pointer_type->opcode() == spv::Op::OpTypePointer &&
          "The base object must have pointer type.");
   auto should_be_composite_type = ir_context->get_def_use_mgr()->GetDef(
       pointer_type->GetSingleWordInOperand(1));
@@ -824,18 +831,18 @@
     auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id);
     auto index_type_inst =
         ir_context->get_def_use_mgr()->GetDef(index_inst->type_id());
-    assert(index_type_inst->opcode() == SpvOpTypeInt);
+    assert(index_type_inst->opcode() == spv::Op::OpTypeInt);
     assert(index_type_inst->GetSingleWordInOperand(0) == 32);
     opt::analysis::Integer* index_int_type =
         ir_context->get_type_mgr()
             ->GetType(index_type_inst->result_id())
             ->AsInteger();
 
-    if (index_inst->opcode() != SpvOpConstant ||
+    if (index_inst->opcode() != spv::Op::OpConstant ||
         index_inst->GetSingleWordInOperand(0) >= bound) {
       // The index is either non-constant or an out-of-bounds constant, so we
       // need to clamp it.
-      assert(should_be_composite_type->opcode() != SpvOpTypeStruct &&
+      assert(should_be_composite_type->opcode() != spv::Op::OpTypeStruct &&
              "Access chain indices into structures are required to be "
              "constants.");
       opt::analysis::IntConstant bound_minus_one(index_int_type, {bound - 1});
@@ -866,7 +873,7 @@
       // Compare the index with the bound via an instruction of the form:
       //   %t1 = OpULessThanEqual %bool %index %bound_minus_one
       new_instructions.push_back(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpULessThanEqual, bool_type_id, compare_id,
+          ir_context, spv::Op::OpULessThanEqual, bool_type_id, compare_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
                {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}})));
@@ -874,7 +881,8 @@
       // Select the index if in-bounds, otherwise one less than the bound:
       //   %t2 = OpSelect %int_type %t1 %index %bound_minus_one
       new_instructions.push_back(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpSelect, index_type_inst->result_id(), select_id,
+          ir_context, spv::Op::OpSelect, index_type_inst->result_id(),
+          select_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {compare_id}},
                {SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
@@ -899,20 +907,20 @@
     uint32_t index_id) {
   uint32_t sub_object_type_id;
   switch (composite_type_inst.opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0);
       break;
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0);
       break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id);
-      assert(index_inst->opcode() == SpvOpConstant);
+      assert(index_inst->opcode() == spv::Op::OpConstant);
       assert(ir_context->get_def_use_mgr()
                  ->GetDef(index_inst->type_id())
-                 ->opcode() == SpvOpTypeInt);
+                 ->opcode() == spv::Op::OpTypeInt);
       assert(ir_context->get_def_use_mgr()
                  ->GetDef(index_inst->type_id())
                  ->GetSingleWordInOperand(0) == 32);
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_undef.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_undef.cpp
index ec0574a..5aca19d 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_undef.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_undef.cpp
@@ -39,14 +39,14 @@
   auto type = ir_context->get_def_use_mgr()->GetDef(message_.type_id());
   // The type must exist, and must not be a function or pointer type.
   return type != nullptr && opt::IsTypeInst(type->opcode()) &&
-         type->opcode() != SpvOpTypeFunction &&
-         type->opcode() != SpvOpTypePointer;
+         type->opcode() != spv::Op::OpTypeFunction &&
+         type->opcode() != spv::Op::OpTypePointer;
 }
 
 void TransformationAddGlobalUndef::Apply(
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpUndef, message_.type_id(), message_.fresh_id(),
+      ir_context, spv::Op::OpUndef, message_.type_id(), message_.fresh_id(),
       opt::Instruction::OperandList());
   auto new_instruction_ptr = new_instruction.get();
   ir_context->module()->AddGlobalValue(std::move(new_instruction));
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_variable.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_variable.cpp
index 814d01b..6e82d59 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_variable.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_variable.cpp
@@ -24,11 +24,11 @@
     : message_(std::move(message)) {}
 
 TransformationAddGlobalVariable::TransformationAddGlobalVariable(
-    uint32_t fresh_id, uint32_t type_id, SpvStorageClass storage_class,
+    uint32_t fresh_id, uint32_t type_id, spv::StorageClass storage_class,
     uint32_t initializer_id, bool value_is_irrelevant) {
   message_.set_fresh_id(fresh_id);
   message_.set_type_id(type_id);
-  message_.set_storage_class(storage_class);
+  message_.set_storage_class(uint32_t(storage_class));
   message_.set_initializer_id(initializer_id);
   message_.set_value_is_irrelevant(value_is_irrelevant);
 }
@@ -41,10 +41,10 @@
   }
 
   // The storage class must be Private or Workgroup.
-  auto storage_class = static_cast<SpvStorageClass>(message_.storage_class());
+  auto storage_class = static_cast<spv::StorageClass>(message_.storage_class());
   switch (storage_class) {
-    case SpvStorageClassPrivate:
-    case SpvStorageClassWorkgroup:
+    case spv::StorageClass::Private:
+    case spv::StorageClass::Workgroup:
       break;
     default:
       assert(false && "Unsupported storage class.");
@@ -66,7 +66,7 @@
   }
   if (message_.initializer_id()) {
     // An initializer is not allowed if the storage class is Workgroup.
-    if (storage_class == SpvStorageClassWorkgroup) {
+    if (storage_class == spv::StorageClass::Workgroup) {
       assert(false &&
              "By construction this transformation should not have an "
              "initializer when Workgroup storage class is used.");
@@ -95,7 +95,7 @@
     TransformationContext* transformation_context) const {
   opt::Instruction* new_instruction = fuzzerutil::AddGlobalVariable(
       ir_context, message_.fresh_id(), message_.type_id(),
-      static_cast<SpvStorageClass>(message_.storage_class()),
+      static_cast<spv::StorageClass>(message_.storage_class()),
       message_.initializer_id());
 
   // Inform the def-use manager about the new instruction.
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_variable.h b/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_variable.h
index d74d48a..0178219 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_variable.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_global_variable.h
@@ -29,7 +29,7 @@
       protobufs::TransformationAddGlobalVariable message);
 
   TransformationAddGlobalVariable(uint32_t fresh_id, uint32_t type_id,
-                                  SpvStorageClass storage_class,
+                                  spv::StorageClass storage_class,
                                   uint32_t initializer_id,
                                   bool value_is_irrelevant);
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_image_sample_unused_components.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_image_sample_unused_components.cpp
index 1ead82b..018fed4 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_image_sample_unused_components.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_image_sample_unused_components.cpp
@@ -73,7 +73,7 @@
   // It must be an OpCompositeConstruct instruction such that it can be checked
   // that the original components are present.
   if (coordinate_with_unused_components_instruction->opcode() !=
-      SpvOpCompositeConstruct) {
+      spv::Op::OpCompositeConstruct) {
     return false;
   }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_local_variable.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_local_variable.cpp
index 21768d2..9ee210c 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_local_variable.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_local_variable.cpp
@@ -43,8 +43,10 @@
   // function storage class.
   auto type_instruction =
       ir_context->get_def_use_mgr()->GetDef(message_.type_id());
-  if (!type_instruction || type_instruction->opcode() != SpvOpTypePointer ||
-      type_instruction->GetSingleWordInOperand(0) != SpvStorageClassFunction) {
+  if (!type_instruction ||
+      type_instruction->opcode() != spv::Op::OpTypePointer ||
+      spv::StorageClass(type_instruction->GetSingleWordInOperand(0)) !=
+          spv::StorageClass::Function) {
     return false;
   }
   // The initializer must...
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_loop_preheader.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_loop_preheader.cpp
index 71ab18d..4b66b69 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_loop_preheader.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_loop_preheader.cpp
@@ -120,8 +120,8 @@
         // If |use_inst| is not a branch or merge instruction, it should not be
         // changed.
         if (!use_inst->IsBranch() &&
-            use_inst->opcode() != SpvOpSelectionMerge &&
-            use_inst->opcode() != SpvOpLoopMerge) {
+            use_inst->opcode() != spv::Op::OpSelectionMerge &&
+            use_inst->opcode() != spv::Op::OpLoopMerge) {
           return;
         }
 
@@ -134,7 +134,7 @@
   // Make a new block for the preheader.
   std::unique_ptr<opt::BasicBlock> preheader = MakeUnique<opt::BasicBlock>(
       std::unique_ptr<opt::Instruction>(new opt::Instruction(
-          ir_context, SpvOpLabel, 0, message_.fresh_id(), {})));
+          ir_context, spv::Op::OpLabel, 0, message_.fresh_id(), {})));
 
   uint32_t phi_ids_used = 0;
 
@@ -183,7 +183,7 @@
       fuzzerutil::UpdateModuleIdBound(ir_context, fresh_phi_id);
 
       preheader->AddInstruction(std::unique_ptr<opt::Instruction>(
-          new opt::Instruction(ir_context, SpvOpPhi, phi_inst->type_id(),
+          new opt::Instruction(ir_context, spv::Op::OpPhi, phi_inst->type_id(),
                                fresh_phi_id, preheader_in_operands)));
 
       // Update the OpPhi instruction in the header so that it refers to the
@@ -202,7 +202,7 @@
   // Add an unconditional branch from the preheader to the header.
   preheader->AddInstruction(
       std::unique_ptr<opt::Instruction>(new opt::Instruction(
-          ir_context, SpvOpBranch, 0, 0,
+          ir_context, spv::Op::OpBranch, 0, 0,
           std::initializer_list<opt::Operand>{opt::Operand(
               spv_operand_type_t::SPV_OPERAND_TYPE_ID, {loop_header->id()})})));
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp
index 657fafa..00030e7 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp
@@ -262,13 +262,13 @@
   // Create the loop header block.
   std::unique_ptr<opt::BasicBlock> loop_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.loop_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.loop_id(),
           opt::Instruction::OperandList{}));
 
   // Add OpPhi instructions to retrieve the current value of the counter and of
   // the temporary variable that will be decreased at each operation.
   loop_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpPhi, const_0_def->type_id(), message_.ctr_id(),
+      ir_context, spv::Op::OpPhi, const_0_def->type_id(), message_.ctr_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {const_0_id}},
           {SPV_OPERAND_TYPE_ID, {pred_id}},
@@ -276,7 +276,8 @@
           {SPV_OPERAND_TYPE_ID, {last_loop_block_id}}}));
 
   loop_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpPhi, initial_val_def->type_id(), message_.temp_id(),
+      ir_context, spv::Op::OpPhi, initial_val_def->type_id(),
+      message_.temp_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.initial_val_id()}},
           {SPV_OPERAND_TYPE_ID, {pred_id}},
@@ -291,7 +292,7 @@
   // Add an instruction to subtract the step value from the temporary value.
   // The value of this id will converge to the constant in the last iteration.
   other_instructions.push_back(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpISub, initial_val_def->type_id(),
+      ir_context, spv::Op::OpISub, initial_val_def->type_id(),
       message_.eventual_syn_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.temp_id()}},
@@ -299,15 +300,15 @@
 
   // Add an instruction to increment the counter.
   other_instructions.push_back(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpIAdd, const_0_def->type_id(),
+      ir_context, spv::Op::OpIAdd, const_0_def->type_id(),
       message_.incremented_ctr_id(),
       opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {message_.ctr_id()}},
                                     {SPV_OPERAND_TYPE_ID, {const_1_id}}}));
 
   // Add an instruction to decide whether the condition holds.
   other_instructions.push_back(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSLessThan, fuzzerutil::MaybeGetBoolType(ir_context),
-      message_.cond_id(),
+      ir_context, spv::Op::OpSLessThan,
+      fuzzerutil::MaybeGetBoolType(ir_context), message_.cond_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.incremented_ctr_id()}},
           {SPV_OPERAND_TYPE_ID, {message_.num_iterations_id()}}}));
@@ -316,18 +317,19 @@
   // the existing block, the continue block is the last block in the loop
   // (either the loop itself or the additional block).
   std::unique_ptr<opt::Instruction> merge_inst = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLoopMerge, 0, 0,
+      ir_context, spv::Op::OpLoopMerge, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.block_after_loop_id()}},
           {SPV_OPERAND_TYPE_ID, {last_loop_block_id}},
-          {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}});
+          {SPV_OPERAND_TYPE_LOOP_CONTROL,
+           {uint32_t(spv::LoopControlMask::MaskNone)}}});
 
   // Define a conditional branch instruction, branching to the loop header if
   // the condition holds, and to the existing block otherwise. This instruction
   // will be added to the last block in the loop.
   std::unique_ptr<opt::Instruction> conditional_branch =
       MakeUnique<opt::Instruction>(
-          ir_context, SpvOpBranchConditional, 0, 0,
+          ir_context, spv::Op::OpBranchConditional, 0, 0,
           opt::Instruction::OperandList{
               {SPV_OPERAND_TYPE_ID, {message_.cond_id()}},
               {SPV_OPERAND_TYPE_ID, {message_.loop_id()}},
@@ -340,7 +342,7 @@
 
     std::unique_ptr<opt::BasicBlock> additional_block =
         MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpLabel, 0, message_.additional_block_id(),
+            ir_context, spv::Op::OpLabel, 0, message_.additional_block_id(),
             opt::Instruction::OperandList{}));
 
     for (auto& instruction : other_instructions) {
@@ -354,7 +356,7 @@
 
     // Add an unconditional branch from the header to the additional block.
     loop_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpBranch, 0, 0,
+        ir_context, spv::Op::OpBranch, 0, 0,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {message_.additional_block_id()}}}));
 
@@ -384,14 +386,14 @@
   ir_context->get_def_use_mgr()->ForEachUse(
       message_.block_after_loop_id(),
       [this](opt::Instruction* instruction, uint32_t operand_index) {
-        assert(instruction->opcode() != SpvOpLoopMerge &&
-               instruction->opcode() != SpvOpSelectionMerge &&
+        assert(instruction->opcode() != spv::Op::OpLoopMerge &&
+               instruction->opcode() != spv::Op::OpSelectionMerge &&
                "The block should not be referenced by OpLoopMerge or "
                "OpSelectionMerge, by construction.");
         // Replace all uses of the label inside branch instructions.
-        if (instruction->opcode() == SpvOpBranch ||
-            instruction->opcode() == SpvOpBranchConditional ||
-            instruction->opcode() == SpvOpSwitch) {
+        if (instruction->opcode() == spv::Op::OpBranch ||
+            instruction->opcode() == spv::Op::OpBranchConditional ||
+            instruction->opcode() == spv::Op::OpSwitch) {
           instruction->SetOperand(operand_index, {message_.loop_id()});
         }
       });
@@ -410,7 +412,7 @@
   // |message_.initial_value_id|, since this is the value that is decremented in
   // the loop.
   block_after_loop->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpPhi, initial_val_def->type_id(), message_.syn_id(),
+      ir_context, spv::Op::OpPhi, initial_val_def->type_id(), message_.syn_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.eventual_syn_id()}},
           {SPV_OPERAND_TYPE_ID, {last_loop_block_id}}}));
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_no_contraction_decoration.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_no_contraction_decoration.cpp
index 992a216..07a31e5 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_no_contraction_decoration.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_no_contraction_decoration.cpp
@@ -43,8 +43,8 @@
 void TransformationAddNoContractionDecoration::Apply(
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Add a NoContraction decoration targeting |message_.result_id|.
-  ir_context->get_decoration_mgr()->AddDecoration(message_.result_id(),
-                                                  SpvDecorationNoContraction);
+  ir_context->get_decoration_mgr()->AddDecoration(
+      message_.result_id(), uint32_t(spv::Decoration::NoContraction));
 }
 
 protobufs::Transformation TransformationAddNoContractionDecoration::ToMessage()
@@ -54,50 +54,50 @@
   return result;
 }
 
-bool TransformationAddNoContractionDecoration::IsArithmetic(uint32_t opcode) {
+bool TransformationAddNoContractionDecoration::IsArithmetic(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
       return true;
     default:
       return false;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_no_contraction_decoration.h b/third_party/SPIRV-Tools/source/fuzz/transformation_add_no_contraction_decoration.h
index 2f78d42..4235dc1 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_no_contraction_decoration.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_no_contraction_decoration.h
@@ -50,7 +50,7 @@
 
   // Returns true if and only if |opcode| is the opcode of an arithmetic
   // instruction, as defined by the SPIR-V specification.
-  static bool IsArithmetic(uint32_t opcode);
+  static bool IsArithmetic(spv::Op opcode);
 
  private:
   protobufs::TransformationAddNoContractionDecoration message_;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_opphi_synonym.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_opphi_synonym.cpp
index 3c4698a..31c56b6 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_opphi_synonym.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_opphi_synonym.cpp
@@ -142,8 +142,8 @@
   // Add a new OpPhi instructions at the beginning of the block.
   ir_context->get_instr_block(message_.block_id())
       ->begin()
-      .InsertBefore(MakeUnique<opt::Instruction>(ir_context, SpvOpPhi, type_id,
-                                                 message_.fresh_id(),
+      .InsertBefore(MakeUnique<opt::Instruction>(ir_context, spv::Op::OpPhi,
+                                                 type_id, message_.fresh_id(),
                                                  std::move(operand_list)));
 
   // Update the module id bound.
@@ -186,9 +186,9 @@
   if (type->AsPointer()) {
     auto storage_class = type->AsPointer()->storage_class();
     return ir_context->get_feature_mgr()->HasCapability(
-               SpvCapabilityVariablePointers) &&
-           (storage_class == SpvStorageClassWorkgroup ||
-            storage_class == SpvStorageClassStorageBuffer);
+               spv::Capability::VariablePointers) &&
+           (storage_class == spv::StorageClass::Workgroup ||
+            storage_class == spv::StorageClass::StorageBuffer);
   }
 
   // We do not allow other types.
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_parameter.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_parameter.cpp
index 48de3e8..8bd2ed7 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_parameter.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_parameter.cpp
@@ -112,7 +112,7 @@
 
   // Add new parameters to the function.
   function->AddParameter(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionParameter, new_parameter_type_id,
+      ir_context, spv::Op::OpFunctionParameter, new_parameter_type_id,
       message_.parameter_fresh_id(), opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.parameter_fresh_id());
@@ -178,16 +178,16 @@
   //  Think about other type instructions we can add here.
   opt::Instruction* type_inst = ir_context->get_def_use_mgr()->GetDef(type_id);
   switch (type_inst->opcode()) {
-    case SpvOpTypeBool:
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       return true;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       return IsParameterTypeSupported(ir_context,
                                       type_inst->GetSingleWordInOperand(0));
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       if (fuzzerutil::HasBlockOrBufferBlockDecoration(ir_context, type_id)) {
         return false;
       }
@@ -198,13 +198,13 @@
         }
       }
       return true;
-    case SpvOpTypePointer: {
-      SpvStorageClass storage_class =
-          static_cast<SpvStorageClass>(type_inst->GetSingleWordInOperand(0));
+    case spv::Op::OpTypePointer: {
+      spv::StorageClass storage_class =
+          static_cast<spv::StorageClass>(type_inst->GetSingleWordInOperand(0));
       switch (storage_class) {
-        case SpvStorageClassPrivate:
-        case SpvStorageClassFunction:
-        case SpvStorageClassWorkgroup: {
+        case spv::StorageClass::Private:
+        case spv::StorageClass::Function:
+        case spv::StorageClass::Workgroup: {
           return IsParameterTypeSupported(ir_context,
                                           type_inst->GetSingleWordInOperand(1));
         }
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_relaxed_decoration.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_relaxed_decoration.cpp
index b66a1a8..6cd4ecb 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_relaxed_decoration.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_relaxed_decoration.cpp
@@ -54,7 +54,7 @@
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Add a RelaxedPrecision decoration targeting |message_.result_id|.
   ir_context->get_decoration_mgr()->AddDecoration(
-      message_.result_id(), SpvDecorationRelaxedPrecision);
+      message_.result_id(), uint32_t(spv::Decoration::RelaxedPrecision));
 }
 
 protobufs::Transformation TransformationAddRelaxedDecoration::ToMessage()
@@ -64,77 +64,77 @@
   return result;
 }
 
-bool TransformationAddRelaxedDecoration::IsNumeric(uint32_t opcode) {
+bool TransformationAddRelaxedDecoration::IsNumeric(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpConvertPtrToU:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpTranspose:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpConvertPtrToU:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
       return true;
     default:
       return false;
@@ -147,4 +147,4 @@
 }
 
 }  // namespace fuzz
-}  // namespace spvtools
\ No newline at end of file
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_relaxed_decoration.h b/third_party/SPIRV-Tools/source/fuzz/transformation_add_relaxed_decoration.h
index c016349..e13594e 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_relaxed_decoration.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_relaxed_decoration.h
@@ -52,7 +52,7 @@
   // Returns true if and only if |opcode| is the opcode of an instruction
   // that operates on 32-bit integers and 32-bit floats
   // as defined by the SPIR-V specification.
-  static bool IsNumeric(uint32_t opcode);
+  static bool IsNumeric(spv::Op opcode);
 
  private:
   protobufs::TransformationAddRelaxedDecoration message_;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_spec_constant_op.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_spec_constant_op.cpp
index 19c5e85..685f0a4 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_spec_constant_op.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_spec_constant_op.cpp
@@ -26,11 +26,11 @@
     : message_(std::move(message)) {}
 
 TransformationAddSpecConstantOp::TransformationAddSpecConstantOp(
-    uint32_t fresh_id, uint32_t type_id, SpvOp opcode,
+    uint32_t fresh_id, uint32_t type_id, spv::Op opcode,
     const opt::Instruction::OperandList& operands) {
   message_.set_fresh_id(fresh_id);
   message_.set_type_id(type_id);
-  message_.set_opcode(opcode);
+  message_.set_opcode(uint32_t(opcode));
   for (const auto& operand : operands) {
     auto* op = message_.add_operand();
     op->set_operand_type(operand.type);
@@ -70,8 +70,8 @@
   }
 
   ir_context->AddGlobalValue(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSpecConstantOp, message_.type_id(), message_.fresh_id(),
-      std::move(operands)));
+      ir_context, spv::Op::OpSpecConstantOp, message_.type_id(),
+      message_.fresh_id(), std::move(operands)));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 }
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_spec_constant_op.h b/third_party/SPIRV-Tools/source/fuzz/transformation_add_spec_constant_op.h
index 29851fd..665f66a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_spec_constant_op.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_spec_constant_op.h
@@ -29,7 +29,7 @@
       protobufs::TransformationAddSpecConstantOp message);
 
   TransformationAddSpecConstantOp(
-      uint32_t fresh_id, uint32_t type_id, SpvOp opcode,
+      uint32_t fresh_id, uint32_t type_id, spv::Op opcode,
       const opt::Instruction::OperandList& operands);
 
   // - |fresh_id| is a fresh result id in the module.
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_synonym.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_synonym.cpp
index 69269e5..00df9cf 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_synonym.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_synonym.cpp
@@ -82,7 +82,7 @@
   // Check that we can insert |message._synonymous_instruction| before
   // |message_.insert_before| instruction. We use OpIAdd to represent some
   // instruction that can produce a synonym.
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd,
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
                                                     insert_before_inst)) {
     return false;
   }
@@ -147,7 +147,8 @@
   // Instruction must have a result id, type id. We skip OpUndef and
   // OpConstantNull.
   if (!inst || !inst->result_id() || !inst->type_id() ||
-      inst->opcode() == SpvOpUndef || inst->opcode() == SpvOpConstantNull) {
+      inst->opcode() == spv::Op::OpUndef ||
+      inst->opcode() == spv::Op::OpConstantNull) {
     return false;
   }
 
@@ -208,7 +209,7 @@
   auto synonym_type_id =
       fuzzerutil::GetTypeId(ir_context, message_.result_id());
   assert(synonym_type_id && "Synonym has invalid type id");
-  auto opcode = SpvOpNop;
+  auto opcode = spv::Op::OpNop;
   const auto* synonym_type =
       ir_context->get_type_mgr()->GetType(synonym_type_id);
   assert(synonym_type && "Synonym has invalid type");
@@ -219,30 +220,30 @@
 
   switch (message_.synonym_type()) {
     case protobufs::TransformationAddSynonym::SUB_ZERO:
-      opcode = is_integral ? SpvOpISub : SpvOpFSub;
+      opcode = is_integral ? spv::Op::OpISub : spv::Op::OpFSub;
       break;
     case protobufs::TransformationAddSynonym::MUL_ONE:
-      opcode = is_integral ? SpvOpIMul : SpvOpFMul;
+      opcode = is_integral ? spv::Op::OpIMul : spv::Op::OpFMul;
       break;
     case protobufs::TransformationAddSynonym::ADD_ZERO:
-      opcode = is_integral ? SpvOpIAdd : SpvOpFAdd;
+      opcode = is_integral ? spv::Op::OpIAdd : spv::Op::OpFAdd;
       break;
     case protobufs::TransformationAddSynonym::LOGICAL_OR:
-      opcode = SpvOpLogicalOr;
+      opcode = spv::Op::OpLogicalOr;
       break;
     case protobufs::TransformationAddSynonym::LOGICAL_AND:
-      opcode = SpvOpLogicalAnd;
+      opcode = spv::Op::OpLogicalAnd;
       break;
     case protobufs::TransformationAddSynonym::BITWISE_OR:
-      opcode = SpvOpBitwiseOr;
+      opcode = spv::Op::OpBitwiseOr;
       break;
     case protobufs::TransformationAddSynonym::BITWISE_XOR:
-      opcode = SpvOpBitwiseXor;
+      opcode = spv::Op::OpBitwiseXor;
       break;
 
     case protobufs::TransformationAddSynonym::COPY_OBJECT:
       return MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCopyObject, synonym_type_id,
+          ir_context, spv::Op::OpCopyObject, synonym_type_id,
           message_.synonym_fresh_id(),
           opt::Instruction::OperandList{
               {SPV_OPERAND_TYPE_ID, {message_.result_id()}}});
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_array.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_array.cpp
index 45bc8df..d00d0e4 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_array.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_array.cpp
@@ -72,7 +72,7 @@
   in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.element_type_id()}});
   in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.size_id()}});
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands);
+      ir_context, spv::Op::OpTypeArray, 0, message_.fresh_id(), in_operands);
   auto type_instruction_ptr = type_instruction.get();
   ir_context->module()->AddType(std::move(type_instruction));
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_boolean.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_boolean.cpp
index 30ff43e..47fc744 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_boolean.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_boolean.cpp
@@ -43,7 +43,7 @@
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList empty_operands;
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeBool, 0, message_.fresh_id(), empty_operands);
+      ir_context, spv::Op::OpTypeBool, 0, message_.fresh_id(), empty_operands);
   auto type_instruction_ptr = type_instruction.get();
   ir_context->module()->AddType(std::move(type_instruction));
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_float.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_float.cpp
index 1b88b25..1943ffa 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_float.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_float.cpp
@@ -40,7 +40,8 @@
   switch (message_.width()) {
     case 16:
       // The Float16 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityFloat16)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Float16)) {
         return false;
       }
       break;
@@ -49,7 +50,8 @@
       break;
     case 64:
       // The Float64 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityFloat64)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Float64)) {
         return false;
       }
       break;
@@ -66,7 +68,7 @@
 void TransformationAddTypeFloat::Apply(
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeFloat, 0, message_.fresh_id(),
+      ir_context, spv::Op::OpTypeFloat, 0, message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}}});
   auto type_instruction_ptr = type_instruction.get();
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_int.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_int.cpp
index d4ef981..35663f9 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_int.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_int.cpp
@@ -42,13 +42,15 @@
   switch (message_.width()) {
     case 8:
       // The Int8 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt8)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Int8)) {
         return false;
       }
       break;
     case 16:
       // The Int16 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt16)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Int16)) {
         return false;
       }
       break;
@@ -57,7 +59,8 @@
       break;
     case 64:
       // The Int64 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt64)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Int64)) {
         return false;
       }
       break;
@@ -75,7 +78,7 @@
 void TransformationAddTypeInt::Apply(opt::IRContext* ir_context,
                                      TransformationContext* /*unused*/) const {
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeInt, 0, message_.fresh_id(),
+      ir_context, spv::Op::OpTypeInt, 0, message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}},
           {SPV_OPERAND_TYPE_LITERAL_INTEGER,
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_matrix.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_matrix.cpp
index b574b01..e3f1786 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_matrix.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_matrix.cpp
@@ -53,7 +53,7 @@
   in_operands.push_back(
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.column_count()}});
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands);
+      ir_context, spv::Op::OpTypeMatrix, 0, message_.fresh_id(), in_operands);
   auto type_instruction_ptr = type_instruction.get();
   ir_context->module()->AddType(std::move(type_instruction));
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_pointer.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_pointer.cpp
index c6c3945..c112615 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_pointer.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_pointer.cpp
@@ -24,9 +24,9 @@
     : message_(std::move(message)) {}
 
 TransformationAddTypePointer::TransformationAddTypePointer(
-    uint32_t fresh_id, SpvStorageClass storage_class, uint32_t base_type_id) {
+    uint32_t fresh_id, spv::StorageClass storage_class, uint32_t base_type_id) {
   message_.set_fresh_id(fresh_id);
-  message_.set_storage_class(storage_class);
+  message_.set_storage_class(uint32_t(storage_class));
   message_.set_base_type_id(base_type_id);
 }
 
@@ -48,7 +48,7 @@
       {SPV_OPERAND_TYPE_STORAGE_CLASS, {message_.storage_class()}},
       {SPV_OPERAND_TYPE_ID, {message_.base_type_id()}}};
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypePointer, 0, message_.fresh_id(), in_operands);
+      ir_context, spv::Op::OpTypePointer, 0, message_.fresh_id(), in_operands);
   auto type_instruction_ptr = type_instruction.get();
   ir_context->module()->AddType(std::move(type_instruction));
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_pointer.h b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_pointer.h
index 8468c14..e4ef9d8 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_pointer.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_pointer.h
@@ -28,7 +28,8 @@
   explicit TransformationAddTypePointer(
       protobufs::TransformationAddTypePointer message);
 
-  TransformationAddTypePointer(uint32_t fresh_id, SpvStorageClass storage_class,
+  TransformationAddTypePointer(uint32_t fresh_id,
+                               spv::StorageClass storage_class,
                                uint32_t base_type_id);
 
   // - |message_.fresh_id| must not be used by the module
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_struct.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_struct.cpp
index d7f0711..95fbbba 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_struct.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_struct.cpp
@@ -79,8 +79,9 @@
     operands.push_back({SPV_OPERAND_TYPE_ID, {type_id}});
   }
 
-  auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeStruct, 0, message_.fresh_id(), std::move(operands));
+  auto type_instruction =
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpTypeStruct, 0,
+                                   message_.fresh_id(), std::move(operands));
   auto type_instruction_ptr = type_instruction.get();
   ir_context->AddType(std::move(type_instruction));
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_vector.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_vector.cpp
index 4da0ff0..a7b0fa7 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_vector.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_add_type_vector.cpp
@@ -57,7 +57,7 @@
          "Precondition: component count must be in range [2, 4].");
 
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeVector, 0, message_.fresh_id(),
+      ir_context, spv::Op::OpTypeVector, 0, message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.component_type_id()}},
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.component_count()}}});
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_adjust_branch_weights.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_adjust_branch_weights.cpp
index 21fef25..2651938 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_adjust_branch_weights.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_adjust_branch_weights.cpp
@@ -47,7 +47,7 @@
     return false;
   }
 
-  SpvOp opcode = static_cast<SpvOp>(
+  spv::Op opcode = static_cast<spv::Op>(
       message_.instruction_descriptor().target_instruction_opcode());
 
   assert(instruction->opcode() == opcode &&
@@ -55,7 +55,7 @@
          "descriptor.");
 
   // Must be an OpBranchConditional instruction.
-  if (opcode != SpvOpBranchConditional) {
+  if (opcode != spv::Op::OpBranchConditional) {
     return false;
   }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_composite_construct.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_composite_construct.cpp
index 2d8e599..075b33d 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_composite_construct.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_composite_construct.cpp
@@ -121,7 +121,7 @@
 
   // Insert an OpCompositeConstruct instruction.
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCompositeConstruct, message_.composite_type_id(),
+      ir_context, spv::Op::OpCompositeConstruct, message_.composite_type_id(),
       message_.fresh_id(), in_operands);
   auto new_instruction_ptr = new_instruction.get();
   insert_before.InsertBefore(std::move(new_instruction));
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_composite_extract.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_composite_extract.cpp
index 0fbd4e1..7118432 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_composite_extract.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_composite_extract.cpp
@@ -67,7 +67,7 @@
   }
 
   if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-          SpvOpCompositeExtract, instruction_to_insert_before)) {
+          spv::Op::OpCompositeExtract, instruction_to_insert_before)) {
     return false;
   }
 
@@ -93,7 +93,7 @@
       FindInstruction(message_.instruction_to_insert_before(), ir_context);
   opt::Instruction* new_instruction =
       insert_before->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract, extracted_type,
+          ir_context, spv::Op::OpCompositeExtract, extracted_type,
           message_.fresh_id(), extract_operands));
   ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction);
   ir_context->set_instr_block(new_instruction,
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_composite_insert.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_composite_insert.cpp
index 60fa562..2f69c95 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_composite_insert.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_composite_insert.cpp
@@ -102,7 +102,7 @@
   // It must be possible to insert an OpCompositeInsert before this
   // instruction.
   return fuzzerutil::CanInsertOpcodeBeforeInstruction(
-      SpvOpCompositeInsert, instruction_to_insert_before);
+      spv::Op::OpCompositeInsert, instruction_to_insert_before);
 }
 
 void TransformationCompositeInsert::Apply(
@@ -126,8 +126,8 @@
   auto insert_before =
       FindInstruction(message_.instruction_to_insert_before(), ir_context);
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCompositeInsert, composite_type_id, message_.fresh_id(),
-      std::move(in_operands));
+      ir_context, spv::Op::OpCompositeInsert, composite_type_id,
+      message_.fresh_id(), std::move(in_operands));
   auto new_instruction_ptr = new_instruction.get();
   insert_before->InsertBefore(std::move(new_instruction));
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.cpp
index db88610..9176bf7 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_duplicate_region_with_selection.cpp
@@ -77,7 +77,7 @@
   // The entry and exit block ids must refer to blocks.
   for (auto block_id : {message_.entry_block_id(), message_.exit_block_id()}) {
     auto block_label = ir_context->get_def_use_mgr()->GetDef(block_id);
-    if (!block_label || block_label->opcode() != SpvOpLabel) {
+    if (!block_label || block_label->opcode() != spv::Op::OpLabel) {
       return false;
     }
   }
@@ -297,7 +297,7 @@
   // in the same function.
   std::unique_ptr<opt::BasicBlock> new_entry_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.new_entry_fresh_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.new_entry_fresh_id(),
           opt::Instruction::OperandList()));
   auto entry_block = ir_context->cfg()->block(message_.entry_block_id());
   auto enclosing_function = entry_block->GetParent();
@@ -310,7 +310,7 @@
   // Construct the merge block.
   std::unique_ptr<opt::BasicBlock> merge_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.merge_label_fresh_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.merge_label_fresh_id(),
           opt::Instruction::OperandList()));
 
   // Get the maps from the protobuf.
@@ -361,7 +361,7 @@
   exit_block->ForEachSuccessorLabel([this, ir_context](uint32_t label_id) {
     auto block = ir_context->cfg()->block(label_id);
     for (auto& instr : *block) {
-      if (instr.opcode() == SpvOpPhi) {
+      if (instr.opcode() == spv::Op::OpPhi) {
         instr.ForEachId([this](uint32_t* id) {
           if (*id == message_.exit_block_id()) {
             *id = message_.merge_label_fresh_id();
@@ -390,7 +390,7 @@
   // occurrence of |entry_block_pred_id| to the id of |new_entry|, because we
   // will insert |new_entry| before |entry_block|.
   for (auto& instr : *entry_block) {
-    if (instr.opcode() == SpvOpPhi) {
+    if (instr.opcode() == spv::Op::OpPhi) {
       instr.ForEachId([this, entry_block_pred_id](uint32_t* id) {
         if (*id == entry_block_pred_id) {
           *id = message_.new_entry_fresh_id();
@@ -421,7 +421,7 @@
 
     std::unique_ptr<opt::BasicBlock> duplicated_block =
         MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpLabel, 0,
+            ir_context, spv::Op::OpLabel, 0,
             original_label_to_duplicate_label.at(block->id()),
             opt::Instruction::OperandList()));
 
@@ -430,12 +430,12 @@
       // handled separately.
       if (block == exit_block && instr.IsBlockTerminator()) {
         switch (instr.opcode()) {
-          case SpvOpBranch:
-          case SpvOpBranchConditional:
-          case SpvOpReturn:
-          case SpvOpReturnValue:
-          case SpvOpUnreachable:
-          case SpvOpKill:
+          case spv::Op::OpBranch:
+          case spv::Op::OpBranchConditional:
+          case spv::Op::OpReturn:
+          case spv::Op::OpReturnValue:
+          case spv::Op::OpUnreachable:
+          case spv::Op::OpKill:
             continue;
           default:
             assert(false &&
@@ -497,7 +497,7 @@
         // the end of the region, as long as the result id is valid for use
         // with OpPhi.
         merge_block->AddInstruction(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpPhi, instr.type_id(),
+            ir_context, spv::Op::OpPhi, instr.type_id(),
             original_id_to_phi_id.at(instr.result_id()),
             opt::Instruction::OperandList({
                 {SPV_OPERAND_TYPE_ID, {instr.result_id()}},
@@ -537,14 +537,14 @@
   // false, the execution proceeds in the first block of the
   // duplicated region.
   new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {message_.merge_label_fresh_id()}},
            {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-            {SpvSelectionControlMaskNone}}})));
+            {uint32_t(spv::SelectionControlMask::MaskNone)}}})));
 
   new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranchConditional, 0, 0,
+      ir_context, spv::Op::OpBranchConditional, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {message_.condition_id()}},
            {SPV_OPERAND_TYPE_ID, {message_.entry_block_id()}},
@@ -563,7 +563,7 @@
   // |exit_block| and at the end of |duplicated_exit_block|, so that
   // the execution proceeds in the |merge_block|.
   opt::Instruction merge_branch_instr = opt::Instruction(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {message_.merge_label_fresh_id()}}}));
   exit_block->AddInstruction(MakeUnique<opt::Instruction>(merge_branch_instr));
@@ -584,14 +584,14 @@
           return;
         }
         switch (user->opcode()) {
-          case SpvOpSwitch:
-          case SpvOpBranch:
-          case SpvOpBranchConditional:
-          case SpvOpLoopMerge:
-          case SpvOpSelectionMerge: {
+          case spv::Op::OpSwitch:
+          case spv::Op::OpBranch:
+          case spv::Op::OpBranchConditional:
+          case spv::Op::OpLoopMerge:
+          case spv::Op::OpSelectionMerge: {
             user->SetOperand(operand_index, {message_.new_entry_fresh_id()});
           } break;
-          case SpvOpName:
+          case spv::Op::OpName:
             break;
           default:
             assert(false &&
@@ -605,8 +605,8 @@
 
   opt::Instruction* merge_block_terminator = merge_block->terminator();
   switch (merge_block_terminator->opcode()) {
-    case SpvOpReturnValue:
-    case SpvOpBranchConditional: {
+    case spv::Op::OpReturnValue:
+    case spv::Op::OpBranchConditional: {
       uint32_t operand = merge_block_terminator->GetSingleWordInOperand(0);
       if (original_id_to_phi_id.count(operand)) {
         merge_block_terminator->SetInOperand(
@@ -699,19 +699,19 @@
       ir_context->get_def_use_mgr()->GetDef(instr.type_id());
 
   // It is invalid to apply OpPhi to void-typed values.
-  if (instr_type->opcode() == SpvOpTypeVoid) {
+  if (instr_type->opcode() == spv::Op::OpTypeVoid) {
     return false;
   }
 
   // Using pointers with OpPhi requires capability VariablePointers.
-  if (instr_type->opcode() == SpvOpTypePointer &&
+  if (instr_type->opcode() == spv::Op::OpTypePointer &&
       !ir_context->get_feature_mgr()->HasCapability(
-          SpvCapabilityVariablePointers)) {
+          spv::Capability::VariablePointers)) {
     return false;
   }
 
   // OpTypeSampledImage cannot be the result type of an OpPhi instruction.
-  if (instr_type->opcode() == SpvOpTypeSampledImage) {
+  if (instr_type->opcode() == spv::Op::OpTypeSampledImage) {
     return false;
   }
   return true;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_equation_instruction.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_equation_instruction.cpp
index 1e5dae9..72487a8 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_equation_instruction.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_equation_instruction.cpp
@@ -25,10 +25,11 @@
     : message_(std::move(message)) {}
 
 TransformationEquationInstruction::TransformationEquationInstruction(
-    uint32_t fresh_id, SpvOp opcode, const std::vector<uint32_t>& in_operand_id,
+    uint32_t fresh_id, spv::Op opcode,
+    const std::vector<uint32_t>& in_operand_id,
     const protobufs::InstructionDescriptor& instruction_to_insert_before) {
   message_.set_fresh_id(fresh_id);
-  message_.set_opcode(opcode);
+  message_.set_opcode(uint32_t(opcode));
   for (auto id : in_operand_id) {
     message_.add_in_operand_id(id);
   }
@@ -57,7 +58,7 @@
     if (!inst) {
       return false;
     }
-    if (inst->opcode() == SpvOpUndef) {
+    if (inst->opcode() == spv::Op::OpUndef) {
       return false;
     }
     if (transformation_context.GetFactManager()->IdIsIrrelevant(id)) {
@@ -88,7 +89,7 @@
       FindInstruction(message_.instruction_to_insert_before(), ir_context);
   opt::Instruction* new_instruction =
       insert_before->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, static_cast<SpvOp>(message_.opcode()),
+          ir_context, static_cast<spv::Op>(message_.opcode()),
           MaybeGetResultTypeId(ir_context), message_.fresh_id(),
           std::move(in_operands)));
 
@@ -101,7 +102,7 @@
   if (!transformation_context->GetFactManager()->IdIsIrrelevant(
           message_.fresh_id())) {
     transformation_context->GetFactManager()->AddFactIdEquation(
-        message_.fresh_id(), static_cast<SpvOp>(message_.opcode()), rhs_id);
+        message_.fresh_id(), static_cast<spv::Op>(message_.opcode()), rhs_id);
   }
 }
 
@@ -113,10 +114,10 @@
 
 uint32_t TransformationEquationInstruction::MaybeGetResultTypeId(
     opt::IRContext* ir_context) const {
-  auto opcode = static_cast<SpvOp>(message_.opcode());
+  auto opcode = static_cast<spv::Op>(message_.opcode());
   switch (opcode) {
-    case SpvOpConvertUToF:
-    case SpvOpConvertSToF: {
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpConvertSToF: {
       if (message_.in_operand_id_size() != 1) {
         return 0;
       }
@@ -148,7 +149,7 @@
                                              type->AsInteger()->width());
       }
     }
-    case SpvOpBitcast: {
+    case spv::Op::OpBitcast: {
       if (message_.in_operand_id_size() != 1) {
         return 0;
       }
@@ -210,8 +211,8 @@
         return 0;
       }
     }
-    case SpvOpIAdd:
-    case SpvOpISub: {
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub: {
       if (message_.in_operand_id_size() != 2) {
         return 0;
       }
@@ -249,7 +250,7 @@
              "A type must have been found for the first operand.");
       return first_operand_type_id;
     }
-    case SpvOpLogicalNot: {
+    case spv::Op::OpLogicalNot: {
       if (message_.in_operand_id().size() != 1) {
         return 0;
       }
@@ -267,7 +268,7 @@
       }
       return operand_inst->type_id();
     }
-    case SpvOpSNegate: {
+    case spv::Op::OpSNegate: {
       if (message_.in_operand_id().size() != 1) {
         return 0;
       }
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_equation_instruction.h b/third_party/SPIRV-Tools/source/fuzz/transformation_equation_instruction.h
index ae32a1a..40118d9 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_equation_instruction.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_equation_instruction.h
@@ -31,7 +31,7 @@
       protobufs::TransformationEquationInstruction message);
 
   TransformationEquationInstruction(
-      uint32_t fresh_id, SpvOp opcode,
+      uint32_t fresh_id, spv::Op opcode,
       const std::vector<uint32_t>& in_operand_id,
       const protobufs::InstructionDescriptor& instruction_to_insert_before);
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_expand_vector_reduction.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_expand_vector_reduction.cpp
index bafcf92..4c13ec1 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_expand_vector_reduction.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_expand_vector_reduction.cpp
@@ -44,7 +44,8 @@
   }
 
   // |instruction| must be OpAny or OpAll.
-  if (instruction->opcode() != SpvOpAny && instruction->opcode() != SpvOpAll) {
+  if (instruction->opcode() != spv::Op::OpAny &&
+      instruction->opcode() != spv::Op::OpAll) {
     return false;
   }
 
@@ -92,10 +93,11 @@
 
   for (uint32_t i = 0; i < vector_component_count; i++) {
     // Extracts the i-th |vector| component.
-    auto vector_component = opt::Instruction(
-        ir_context, SpvOpCompositeExtract, instruction->type_id(), *fresh_id++,
-        {{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
-         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}});
+    auto vector_component =
+        opt::Instruction(ir_context, spv::Op::OpCompositeExtract,
+                         instruction->type_id(), *fresh_id++,
+                         {{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
+                          {SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}});
     instruction->InsertBefore(MakeUnique<opt::Instruction>(vector_component));
     fuzzerutil::UpdateModuleIdBound(ir_context, vector_component.result_id());
     vector_components.push_back(vector_component.result_id());
@@ -104,7 +106,8 @@
   // The first two |vector| components are used in the first logical operation.
   auto logical_instruction = opt::Instruction(
       ir_context,
-      instruction->opcode() == SpvOpAny ? SpvOpLogicalOr : SpvOpLogicalAnd,
+      instruction->opcode() == spv::Op::OpAny ? spv::Op::OpLogicalOr
+                                              : spv::Op::OpLogicalAnd,
       instruction->type_id(), *fresh_id++,
       {{SPV_OPERAND_TYPE_ID, {vector_components[0]}},
        {SPV_OPERAND_TYPE_ID, {vector_components[1]}}});
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_flatten_conditional_branch.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_flatten_conditional_branch.cpp
index 127e762..f8d1c33 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_flatten_conditional_branch.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_flatten_conditional_branch.cpp
@@ -48,12 +48,12 @@
 
   // The block must have been found and it must be a selection header.
   if (!header_block || !header_block->GetMergeInst() ||
-      header_block->GetMergeInst()->opcode() != SpvOpSelectionMerge) {
+      header_block->GetMergeInst()->opcode() != spv::Op::OpSelectionMerge) {
     return false;
   }
 
   // The header block must end with an OpBranchConditional instruction.
-  if (header_block->terminator()->opcode() != SpvOpBranchConditional) {
+  if (header_block->terminator()->opcode() != spv::Op::OpBranchConditional) {
     return false;
   }
 
@@ -164,14 +164,14 @@
                opt::Instruction* phi_result_type =
                    ir_context->get_def_use_mgr()->GetDef(inst->type_id());
                switch (phi_result_type->opcode()) {
-                 case SpvOpTypeBool:
-                 case SpvOpTypeInt:
-                 case SpvOpTypeFloat:
-                 case SpvOpTypePointer:
+                 case spv::Op::OpTypeBool:
+                 case spv::Op::OpTypeInt:
+                 case spv::Op::OpTypeFloat:
+                 case spv::Op::OpTypePointer:
                    // Fine: OpSelect can work directly on scalar and pointer
                    // types.
                    return true;
-                 case SpvOpTypeVector: {
+                 case spv::Op::OpTypeVector: {
                    // In its restricted form, OpSelect can only select between
                    // vectors if the condition of the select is a boolean
                    // boolean vector.  We thus require the appropriate boolean
@@ -288,8 +288,8 @@
 
       current_block->ForEachInst(
           [&problematic_instructions](opt::Instruction* instruction) {
-            if (instruction->opcode() != SpvOpLabel &&
-                instruction->opcode() != SpvOpBranch &&
+            if (instruction->opcode() != spv::Op::OpLabel &&
+                instruction->opcode() != spv::Op::OpBranch &&
                 !fuzzerutil::InstructionHasNoSideEffects(*instruction)) {
               problematic_instructions.push_back(instruction);
             }
@@ -381,7 +381,7 @@
   // Add a new, unconditional, branch instruction from the current header to
   // |after_header|.
   header_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {after_header}}}));
 
   // If the first branch to be laid out exists, change the branch instruction so
@@ -437,8 +437,8 @@
         std::set<opt::Instruction*>* instructions_that_need_ids) {
   uint32_t merge_block_id = header->MergeBlockIdIfAny();
   assert(merge_block_id &&
-         header->GetMergeInst()->opcode() == SpvOpSelectionMerge &&
-         header->terminator()->opcode() == SpvOpBranchConditional &&
+         header->GetMergeInst()->opcode() == spv::Op::OpSelectionMerge &&
+         header->terminator()->opcode() == spv::Op::OpBranchConditional &&
          "|header| must be the header of a conditional.");
 
   // |header| must be reachable.
@@ -508,7 +508,7 @@
     }
 
     // The terminator instruction for the block must be OpBranch.
-    if (block->terminator()->opcode() != SpvOpBranch) {
+    if (block->terminator()->opcode() != spv::Op::OpBranch) {
       return false;
     }
 
@@ -524,7 +524,7 @@
         [ir_context, instructions_that_need_ids,
          &synonym_base_objects](opt::Instruction* instruction) {
           // We can ignore OpLabel instructions.
-          if (instruction->opcode() == SpvOpLabel) {
+          if (instruction->opcode() == spv::Op::OpLabel) {
             return true;
           }
 
@@ -539,7 +539,7 @@
 
           // If the instruction is a branch, it must be an unconditional branch.
           if (instruction->IsBranch()) {
-            return instruction->opcode() == SpvOpBranch;
+            return instruction->opcode() == spv::Op::OpBranch;
           }
 
           // We cannot go ahead if we encounter an instruction that cannot be
@@ -644,7 +644,7 @@
 
   // Add an unconditional branch from |execute_block| to |merge_block|.
   execute_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {merge_block->id()}}}));
 
@@ -668,10 +668,10 @@
     }
 
     // Create a new block using |fresh_ids.alternative_block_id| for its label.
-    auto alternative_block_temp =
-        MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpLabel, 0, wrapper_info.alternative_block_id(),
-            opt::Instruction::OperandList{}));
+    auto alternative_block_temp = MakeUnique<opt::BasicBlock>(
+        MakeUnique<opt::Instruction>(ir_context, spv::Op::OpLabel, 0,
+                                     wrapper_info.alternative_block_id(),
+                                     opt::Instruction::OperandList{}));
 
     // Keep the original result id of the instruction in a variable.
     uint32_t original_result_id = instruction->result_id();
@@ -685,14 +685,14 @@
       // If there is an available id to copy from, the placeholder instruction
       // will be %placeholder_result_id = OpCopyObject %type %value_to_copy_id
       alternative_block_temp->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCopyObject, instruction->type_id(),
+          ir_context, spv::Op::OpCopyObject, instruction->type_id(),
           wrapper_info.placeholder_result_id(),
           opt::Instruction::OperandList{
               {SPV_OPERAND_TYPE_ID, {wrapper_info.value_to_copy_id()}}}));
     } else {
       // If there is no such id, use an OpUndef instruction.
       alternative_block_temp->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpUndef, instruction->type_id(),
+          ir_context, spv::Op::OpUndef, instruction->type_id(),
           wrapper_info.placeholder_result_id(),
           opt::Instruction::OperandList{}));
     }
@@ -702,7 +702,7 @@
 
     // Add an unconditional branch from the new block to the merge block.
     alternative_block_temp->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpBranch, 0, 0,
+        ir_context, spv::Op::OpBranch, 0, 0,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {merge_block->id()}}}));
 
@@ -714,7 +714,7 @@
     // merge block, which will either take the value of the result of the
     // instruction or the placeholder value defined in the alternative block.
     merge_block->begin().InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpPhi, instruction->type_id(), original_result_id,
+        ir_context, spv::Op::OpPhi, instruction->type_id(), original_result_id,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {instruction->result_id()}},
             {SPV_OPERAND_TYPE_ID, {execute_block->id()}},
@@ -738,16 +738,17 @@
 
   // Add an OpSelectionMerge instruction to the block.
   block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
-      opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {merge_block->id()}},
-                                    {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-                                     {SpvSelectionControlMaskNone}}}));
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
+      opt::Instruction::OperandList{
+          {SPV_OPERAND_TYPE_ID, {merge_block->id()}},
+          {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+           {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
 
   // Add an OpBranchConditional, to the block, using |condition_id| as the
   // condition and branching to |if_block_id| if the condition is true and to
   // |else_block_id| if the condition is false.
   block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranchConditional, 0, 0,
+      ir_context, spv::Op::OpBranchConditional, 0, 0,
       opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {condition_id}},
                                     {SPV_OPERAND_TYPE_ID, {if_block_id}},
                                     {SPV_OPERAND_TYPE_ID, {else_block_id}}}));
@@ -764,26 +765,26 @@
 
   // We cannot handle barrier instructions, while we should be able to handle
   // all other instructions by enclosing them inside a conditional.
-  if (instruction.opcode() == SpvOpControlBarrier ||
-      instruction.opcode() == SpvOpMemoryBarrier ||
-      instruction.opcode() == SpvOpNamedBarrierInitialize ||
-      instruction.opcode() == SpvOpMemoryNamedBarrier ||
-      instruction.opcode() == SpvOpTypeNamedBarrier) {
+  if (instruction.opcode() == spv::Op::OpControlBarrier ||
+      instruction.opcode() == spv::Op::OpMemoryBarrier ||
+      instruction.opcode() == spv::Op::OpNamedBarrierInitialize ||
+      instruction.opcode() == spv::Op::OpMemoryNamedBarrier ||
+      instruction.opcode() == spv::Op::OpTypeNamedBarrier) {
     return false;
   }
 
   // We cannot handle OpSampledImage instructions, as they need to be in the
   // same block as their use.
-  if (instruction.opcode() == SpvOpSampledImage) {
+  if (instruction.opcode() == spv::Op::OpSampledImage) {
     return false;
   }
 
   // We cannot handle a sampled image load, because we re-work loads using
   // conditional branches and OpPhi instructions, and the result type of OpPhi
   // cannot be OpTypeSampledImage.
-  if (instruction.opcode() == SpvOpLoad &&
+  if (instruction.opcode() == spv::Op::OpLoad &&
       ir_context->get_def_use_mgr()->GetDef(instruction.type_id())->opcode() ==
-          SpvOpTypeSampledImage) {
+          spv::Op::OpTypeSampledImage) {
     return false;
   }
 
@@ -863,7 +864,7 @@
     in_operands.emplace_back(branch_condition_operand);
   }
   block->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCompositeConstruct,
+      ir_context, spv::Op::OpCompositeConstruct,
       fuzzerutil::MaybeGetVectorType(
           ir_context, fuzzerutil::MaybeGetBoolType(ir_context), dimension),
       fresh_id, in_operands));
@@ -906,7 +907,7 @@
         opt::Operand selector_operand = branch_condition_operand;
         opt::Instruction* type_inst =
             ir_context->get_def_use_mgr()->GetDef(phi_inst->type_id());
-        if (type_inst->opcode() == SpvOpTypeVector) {
+        if (type_inst->opcode() == spv::Op::OpTypeVector) {
           uint32_t dimension = type_inst->GetSingleWordInOperand(1);
           switch (dimension) {
             case 2:
@@ -1012,7 +1013,7 @@
           operands.emplace_back(phi_inst->GetInOperand(2));
           operands.emplace_back(phi_inst->GetInOperand(0));
         }
-        phi_inst->SetOpcode(SpvOpSelect);
+        phi_inst->SetOpcode(spv::Op::OpSelect);
         phi_inst->SetInOperands(std::move(operands));
       });
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_function_call.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_function_call.cpp
index 0f88ce5..e96a230 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_function_call.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_function_call.cpp
@@ -49,7 +49,7 @@
   // The function must exist
   auto callee_inst =
       ir_context->get_def_use_mgr()->GetDef(message_.callee_id());
-  if (!callee_inst || callee_inst->opcode() != SpvOpFunction) {
+  if (!callee_inst || callee_inst->opcode() != spv::Op::OpFunction) {
     return false;
   }
 
@@ -60,7 +60,7 @@
 
   auto callee_type_inst = ir_context->get_def_use_mgr()->GetDef(
       callee_inst->GetSingleWordInOperand(1));
-  assert(callee_type_inst->opcode() == SpvOpTypeFunction &&
+  assert(callee_type_inst->opcode() == spv::Op::OpTypeFunction &&
          "Bad function type.");
 
   // The number of expected function arguments must match the number of given
@@ -78,7 +78,7 @@
   if (!insert_before) {
     return false;
   }
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall,
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpFunctionCall,
                                                     insert_before)) {
     return false;
   }
@@ -116,10 +116,10 @@
     }
     opt::Instruction* arg_type_inst =
         ir_context->get_def_use_mgr()->GetDef(arg_inst->type_id());
-    if (arg_type_inst->opcode() == SpvOpTypePointer) {
+    if (arg_type_inst->opcode() == spv::Op::OpTypePointer) {
       switch (arg_inst->opcode()) {
-        case SpvOpFunctionParameter:
-        case SpvOpVariable:
+        case spv::Op::OpFunctionParameter:
+        case spv::Op::OpVariable:
           // These are OK
           break;
         default:
@@ -173,7 +173,7 @@
   // Insert the function call before the instruction specified in the message.
   FindInstruction(message_.instruction_to_insert_before(), ir_context)
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFunctionCall, return_type, message_.fresh_id(),
+          ir_context, spv::Op::OpFunctionCall, return_type, message_.fresh_id(),
           operands));
   // Invalidate all analyses since we have changed the module.
   ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_inline_function.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_inline_function.cpp
index a48b817..69e88fd 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_inline_function.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_inline_function.cpp
@@ -62,7 +62,8 @@
       ir_context->get_instr_block(function_call_instruction);
   if (function_call_instruction !=
           &*--function_call_instruction_block->tail() ||
-      function_call_instruction_block->terminator()->opcode() != SpvOpBranch) {
+      function_call_instruction_block->terminator()->opcode() !=
+          spv::Op::OpBranch) {
     return false;
   }
 
@@ -143,7 +144,7 @@
   for (auto& entry_block_instruction : *called_function->entry()) {
     opt::Instruction* inlined_instruction;
 
-    if (entry_block_instruction.opcode() == SpvOpVariable) {
+    if (entry_block_instruction.opcode() == spv::Op::OpVariable) {
       // All OpVariable instructions in a function must be in the first block
       // in the function.
       inlined_instruction = caller_function->begin()->begin()->InsertBefore(
@@ -206,7 +207,7 @@
         block_containing_function_call->id(),
         [ir_context, new_return_block_id, successor_block](
             opt::Instruction* use_instruction, uint32_t operand_index) {
-          if (use_instruction->opcode() == SpvOpPhi &&
+          if (use_instruction->opcode() == spv::Op::OpPhi &&
               ir_context->get_instr_block(use_instruction) == successor_block) {
             use_instruction->SetOperand(operand_index, {new_return_block_id});
           }
@@ -234,7 +235,7 @@
   // |function_call_instruction| must be defined and must be an OpFunctionCall
   // instruction.
   if (!function_call_instruction ||
-      function_call_instruction->opcode() != SpvOpFunctionCall) {
+      function_call_instruction->opcode() != spv::Op::OpFunctionCall) {
     return false;
   }
 
@@ -331,13 +332,14 @@
             ->terminator()
             ->GetSingleWordInOperand(0);
     switch (instruction_to_be_inlined->opcode()) {
-      case SpvOpReturn:
+      case spv::Op::OpReturn:
         instruction_to_be_inlined->AddOperand(
             {SPV_OPERAND_TYPE_ID, {successor_block_id}});
         break;
-      case SpvOpReturnValue: {
+      case spv::Op::OpReturnValue: {
         instruction_to_be_inlined->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpCopyObject, function_call_instruction->type_id(),
+            ir_context, spv::Op::OpCopyObject,
+            function_call_instruction->type_id(),
             function_call_instruction->result_id(),
             opt::Instruction::OperandList(
                 {{SPV_OPERAND_TYPE_ID,
@@ -348,7 +350,7 @@
       default:
         break;
     }
-    instruction_to_be_inlined->SetOpcode(SpvOpBranch);
+    instruction_to_be_inlined->SetOpcode(spv::Op::OpBranch);
   }
 }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_invert_comparison_operator.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_invert_comparison_operator.cpp
index ed7358f..49801e3 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_invert_comparison_operator.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_invert_comparison_operator.cpp
@@ -47,7 +47,8 @@
   auto iter = fuzzerutil::GetIteratorForInstruction(block, inst);
   ++iter;
   assert(iter != block->end() && "Instruction can't be the last in the block");
-  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLogicalNot, iter) &&
+  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLogicalNot,
+                                                      iter) &&
          "Can't insert negation after comparison operator");
 
   // |message_.fresh_id| must be fresh.
@@ -65,7 +66,7 @@
   ++iter;
 
   iter.InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLogicalNot, inst->type_id(), inst->result_id(),
+      ir_context, spv::Op::OpLogicalNot, inst->type_id(), inst->result_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}}));
 
@@ -82,88 +83,88 @@
 }
 
 bool TransformationInvertComparisonOperator::IsInversionSupported(
-    SpvOp opcode) {
+    spv::Op opcode) {
   switch (opcode) {
-    case SpvOpSGreaterThan:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpSLessThan:
-    case SpvOpSLessThanEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
       return true;
     default:
       return false;
   }
 }
 
-SpvOp TransformationInvertComparisonOperator::InvertOpcode(SpvOp opcode) {
+spv::Op TransformationInvertComparisonOperator::InvertOpcode(spv::Op opcode) {
   assert(IsInversionSupported(opcode) && "Inversion must be supported");
 
   switch (opcode) {
-    case SpvOpSGreaterThan:
-      return SpvOpSLessThanEqual;
-    case SpvOpSGreaterThanEqual:
-      return SpvOpSLessThan;
-    case SpvOpSLessThan:
-      return SpvOpSGreaterThanEqual;
-    case SpvOpSLessThanEqual:
-      return SpvOpSGreaterThan;
-    case SpvOpUGreaterThan:
-      return SpvOpULessThanEqual;
-    case SpvOpUGreaterThanEqual:
-      return SpvOpULessThan;
-    case SpvOpULessThan:
-      return SpvOpUGreaterThanEqual;
-    case SpvOpULessThanEqual:
-      return SpvOpUGreaterThan;
-    case SpvOpIEqual:
-      return SpvOpINotEqual;
-    case SpvOpINotEqual:
-      return SpvOpIEqual;
-    case SpvOpFOrdEqual:
-      return SpvOpFUnordNotEqual;
-    case SpvOpFUnordEqual:
-      return SpvOpFOrdNotEqual;
-    case SpvOpFOrdNotEqual:
-      return SpvOpFUnordEqual;
-    case SpvOpFUnordNotEqual:
-      return SpvOpFOrdEqual;
-    case SpvOpFOrdLessThan:
-      return SpvOpFUnordGreaterThanEqual;
-    case SpvOpFUnordLessThan:
-      return SpvOpFOrdGreaterThanEqual;
-    case SpvOpFOrdLessThanEqual:
-      return SpvOpFUnordGreaterThan;
-    case SpvOpFUnordLessThanEqual:
-      return SpvOpFOrdGreaterThan;
-    case SpvOpFOrdGreaterThan:
-      return SpvOpFUnordLessThanEqual;
-    case SpvOpFUnordGreaterThan:
-      return SpvOpFOrdLessThanEqual;
-    case SpvOpFOrdGreaterThanEqual:
-      return SpvOpFUnordLessThan;
-    case SpvOpFUnordGreaterThanEqual:
-      return SpvOpFOrdLessThan;
+    case spv::Op::OpSGreaterThan:
+      return spv::Op::OpSLessThanEqual;
+    case spv::Op::OpSGreaterThanEqual:
+      return spv::Op::OpSLessThan;
+    case spv::Op::OpSLessThan:
+      return spv::Op::OpSGreaterThanEqual;
+    case spv::Op::OpSLessThanEqual:
+      return spv::Op::OpSGreaterThan;
+    case spv::Op::OpUGreaterThan:
+      return spv::Op::OpULessThanEqual;
+    case spv::Op::OpUGreaterThanEqual:
+      return spv::Op::OpULessThan;
+    case spv::Op::OpULessThan:
+      return spv::Op::OpUGreaterThanEqual;
+    case spv::Op::OpULessThanEqual:
+      return spv::Op::OpUGreaterThan;
+    case spv::Op::OpIEqual:
+      return spv::Op::OpINotEqual;
+    case spv::Op::OpINotEqual:
+      return spv::Op::OpIEqual;
+    case spv::Op::OpFOrdEqual:
+      return spv::Op::OpFUnordNotEqual;
+    case spv::Op::OpFUnordEqual:
+      return spv::Op::OpFOrdNotEqual;
+    case spv::Op::OpFOrdNotEqual:
+      return spv::Op::OpFUnordEqual;
+    case spv::Op::OpFUnordNotEqual:
+      return spv::Op::OpFOrdEqual;
+    case spv::Op::OpFOrdLessThan:
+      return spv::Op::OpFUnordGreaterThanEqual;
+    case spv::Op::OpFUnordLessThan:
+      return spv::Op::OpFOrdGreaterThanEqual;
+    case spv::Op::OpFOrdLessThanEqual:
+      return spv::Op::OpFUnordGreaterThan;
+    case spv::Op::OpFUnordLessThanEqual:
+      return spv::Op::OpFOrdGreaterThan;
+    case spv::Op::OpFOrdGreaterThan:
+      return spv::Op::OpFUnordLessThanEqual;
+    case spv::Op::OpFUnordGreaterThan:
+      return spv::Op::OpFOrdLessThanEqual;
+    case spv::Op::OpFOrdGreaterThanEqual:
+      return spv::Op::OpFUnordLessThan;
+    case spv::Op::OpFUnordGreaterThanEqual:
+      return spv::Op::OpFOrdLessThan;
     default:
       // The program will fail in the debug mode because of the assertion
       // at the beginning of the function.
-      return SpvOpNop;
+      return spv::Op::OpNop;
   }
 }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_invert_comparison_operator.h b/third_party/SPIRV-Tools/source/fuzz/transformation_invert_comparison_operator.h
index f00f62b..39c2fe0 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_invert_comparison_operator.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_invert_comparison_operator.h
@@ -50,11 +50,11 @@
   protobufs::Transformation ToMessage() const override;
 
   // Returns true if |opcode| is supported by this transformation.
-  static bool IsInversionSupported(SpvOp opcode);
+  static bool IsInversionSupported(spv::Op opcode);
 
  private:
   // Returns an inverted |opcode| (e.g. < becomes >=, == becomes != etc.)
-  static SpvOp InvertOpcode(SpvOp opcode);
+  static spv::Op InvertOpcode(spv::Op opcode);
 
   protobufs::TransformationInvertComparisonOperator message_;
 };
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_load.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_load.cpp
index bf48d99..1cfde77 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_load.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_load.cpp
@@ -52,15 +52,15 @@
   // The type must indeed be a pointer type.
   auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
   assert(pointer_type && "Type id must be defined.");
-  if (pointer_type->opcode() != SpvOpTypePointer) {
+  if (pointer_type->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
   // We do not want to allow loading from null or undefined pointers, as it is
   // not clear how punishing the consequences of doing so are from a semantics
   // point of view.
   switch (pointer->opcode()) {
-    case SpvOpConstantNull:
-    case SpvOpUndef:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpUndef:
       return false;
     default:
       break;
@@ -74,13 +74,13 @@
     return false;
   }
   // ... and it must be legitimate to insert a load before it.
-  if (!message_.is_atomic() &&
-      !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, insert_before)) {
+  if (!message_.is_atomic() && !fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                                   spv::Op::OpLoad, insert_before)) {
     return false;
   }
 
   if (message_.is_atomic() && !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                                  SpvOpAtomicLoad, insert_before)) {
+                                  spv::Op::OpAtomicLoad, insert_before)) {
     return false;
   }
 
@@ -99,10 +99,10 @@
     }
     // The memory scope and memory semantics instructions must have the
     // 'OpConstant' opcode.
-    if (memory_scope_instruction->opcode() != SpvOpConstant) {
+    if (memory_scope_instruction->opcode() != spv::Op::OpConstant) {
       return false;
     }
-    if (memory_semantics_instruction->opcode() != SpvOpConstant) {
+    if (memory_semantics_instruction->opcode() != spv::Op::OpConstant) {
       return false;
     }
     // The memory scope and memory semantics need to be available before
@@ -119,12 +119,12 @@
     // operand type with signedness does not matters.
     if (ir_context->get_def_use_mgr()
             ->GetDef(memory_scope_instruction->type_id())
-            ->opcode() != SpvOpTypeInt) {
+            ->opcode() != spv::Op::OpTypeInt) {
       return false;
     }
     if (ir_context->get_def_use_mgr()
             ->GetDef(memory_semantics_instruction->type_id())
-            ->opcode() != SpvOpTypeInt) {
+            ->opcode() != spv::Op::OpTypeInt) {
       return false;
     }
 
@@ -146,20 +146,20 @@
       return false;
     }
 
-    // The memory scope constant value must be that of SpvScopeInvocation.
+    // The memory scope constant value must be that of spv::Scope::Invocation.
     auto memory_scope_const_value =
-        memory_scope_instruction->GetSingleWordInOperand(0);
-    if (memory_scope_const_value != SpvScopeInvocation) {
+        spv::Scope(memory_scope_instruction->GetSingleWordInOperand(0));
+    if (memory_scope_const_value != spv::Scope::Invocation) {
       return false;
     }
 
     // The memory semantics constant value must match the storage class of the
     // pointer being loaded from.
-    auto memory_semantics_const_value = static_cast<SpvMemorySemanticsMask>(
+    auto memory_semantics_const_value = static_cast<spv::MemorySemanticsMask>(
         memory_semantics_instruction->GetSingleWordInOperand(0));
     if (memory_semantics_const_value !=
         fuzzerutil::GetMemorySemanticsForStorageClass(
-            static_cast<SpvStorageClass>(
+            static_cast<spv::StorageClass>(
                 pointer_type->GetSingleWordInOperand(0)))) {
       return false;
     }
@@ -180,7 +180,7 @@
     auto insert_before =
         FindInstruction(message_.instruction_to_insert_before(), ir_context);
     auto new_instruction = MakeUnique<opt::Instruction>(
-        ir_context, SpvOpAtomicLoad, result_type, message_.fresh_id(),
+        ir_context, spv::Op::OpAtomicLoad, result_type, message_.fresh_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
              {SPV_OPERAND_TYPE_SCOPE_ID, {message_.memory_scope_id()}},
@@ -201,7 +201,7 @@
     auto insert_before =
         FindInstruction(message_.instruction_to_insert_before(), ir_context);
     auto new_instruction = MakeUnique<opt::Instruction>(
-        ir_context, SpvOpLoad, result_type, message_.fresh_id(),
+        ir_context, spv::Op::OpLoad, result_type, message_.fresh_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}}));
     auto new_instruction_ptr = new_instruction.get();
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_load.h b/third_party/SPIRV-Tools/source/fuzz/transformation_load.h
index 57b4a53..6622918 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_load.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_load.h
@@ -37,7 +37,7 @@
   // - |message_.is_atomic| must be true if want to work with OpAtomicLoad
   // - If |is_atomic| is true then |message_memory_scope_id| must be the id of
   //   an OpConstant 32 bit integer instruction with the value
-  //   SpvScopeInvocation.
+  //   spv::Scope::Invocation.
   // - If |is_atomic| is true then |message_.memory_semantics_id| must be the id
   //   of an OpConstant 32 bit integer instruction with the values
   //   SpvMemorySemanticsWorkgroupMemoryMask or
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_make_vector_operation_dynamic.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_make_vector_operation_dynamic.cpp
index bd0664c..ecc8dca 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_make_vector_operation_dynamic.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_make_vector_operation_dynamic.cpp
@@ -62,19 +62,19 @@
   // The OpVectorInsertDynamic instruction has the vector and component operands
   // in reverse order in relation to the OpCompositeInsert corresponding
   // operands.
-  if (instruction->opcode() == SpvOpCompositeInsert) {
+  if (instruction->opcode() == spv::Op::OpCompositeInsert) {
     std::swap(instruction->GetInOperand(0), instruction->GetInOperand(1));
   }
 
   // Sets the literal operand to the equivalent constant.
   instruction->SetInOperand(
-      instruction->opcode() == SpvOpCompositeExtract ? 1 : 2,
+      instruction->opcode() == spv::Op::OpCompositeExtract ? 1 : 2,
       {message_.constant_index_id()});
 
   // Sets the |instruction| opcode to the corresponding vector dynamic opcode.
-  instruction->SetOpcode(instruction->opcode() == SpvOpCompositeExtract
-                             ? SpvOpVectorExtractDynamic
-                             : SpvOpVectorInsertDynamic);
+  instruction->SetOpcode(instruction->opcode() == spv::Op::OpCompositeExtract
+                             ? spv::Op::OpVectorExtractDynamic
+                             : spv::Op::OpVectorInsertDynamic);
 }
 
 protobufs::Transformation TransformationMakeVectorOperationDynamic::ToMessage()
@@ -88,15 +88,15 @@
     opt::IRContext* ir_context, opt::Instruction* instruction) {
   // |instruction| must be defined and must be an OpCompositeExtract/Insert
   // instruction.
-  if (!instruction || (instruction->opcode() != SpvOpCompositeExtract &&
-                       instruction->opcode() != SpvOpCompositeInsert)) {
+  if (!instruction || (instruction->opcode() != spv::Op::OpCompositeExtract &&
+                       instruction->opcode() != spv::Op::OpCompositeInsert)) {
     return false;
   }
 
   // The composite must be a vector.
   auto composite_instruction =
       ir_context->get_def_use_mgr()->GetDef(instruction->GetSingleWordInOperand(
-          instruction->opcode() == SpvOpCompositeExtract ? 0 : 1));
+          instruction->opcode() == spv::Op::OpCompositeExtract ? 0 : 1));
   if (!ir_context->get_type_mgr()
            ->GetType(composite_instruction->type_id())
            ->AsVector()) {
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_merge_function_returns.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_merge_function_returns.cpp
index 022e1b6..b35e358 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_merge_function_returns.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_merge_function_returns.cpp
@@ -50,7 +50,7 @@
   }
 
   // The entry block must end in an unconditional branch.
-  if (function->entry()->terminator()->opcode() != SpvOpBranch) {
+  if (function->entry()->terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
@@ -134,9 +134,9 @@
     bool all_instructions_allowed =
         ir_context->get_instr_block(merge_block)
             ->WhileEachInst([](opt::Instruction* inst) {
-              return inst->opcode() == SpvOpLabel ||
-                     inst->opcode() == SpvOpPhi ||
-                     inst->opcode() == SpvOpBranch;
+              return inst->opcode() == spv::Op::OpLabel ||
+                     inst->opcode() == spv::Op::OpPhi ||
+                     inst->opcode() == spv::Op::OpBranch;
             });
     if (!all_instructions_allowed) {
       return false;
@@ -286,7 +286,7 @@
     }
 
     // Replace the return instruction with an unconditional branch.
-    ret_block->terminator()->SetOpcode(SpvOpBranch);
+    ret_block->terminator()->SetOpcode(spv::Op::OpBranch);
     ret_block->terminator()->SetInOperands(
         {{SPV_OPERAND_TYPE_ID, {merge_block_id}}});
   }
@@ -410,7 +410,7 @@
 
       // Insert the instruction.
       merge_block->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpPhi, function->type_id(), maybe_return_val_id,
+          ir_context, spv::Op::OpPhi, function->type_id(), maybe_return_val_id,
           std::move(operand_list)));
 
       fuzzerutil::UpdateModuleIdBound(ir_context, maybe_return_val_id);
@@ -448,14 +448,14 @@
 
       // Insert the instruction.
       merge_block->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpPhi, bool_type, is_returning_id,
+          ir_context, spv::Op::OpPhi, bool_type, is_returning_id,
           std::move(operand_list)));
 
       fuzzerutil::UpdateModuleIdBound(ir_context, is_returning_id);
     }
 
     // Change the branching instruction of the block.
-    assert(merge_block->terminator()->opcode() == SpvOpBranch &&
+    assert(merge_block->terminator()->opcode() == spv::Op::OpBranch &&
            "Each block should branch unconditionally to the next.");
 
     // Add a new entry to the map corresponding to the merge block of the
@@ -483,14 +483,14 @@
 
     // The block should branch to |enclosing_merge| if |is_returning_id| is
     // true, to |original_succ| otherwise.
-    merge_block->terminator()->SetOpcode(SpvOpBranchConditional);
+    merge_block->terminator()->SetOpcode(spv::Op::OpBranchConditional);
     merge_block->terminator()->SetInOperands(
         {{SPV_OPERAND_TYPE_ID, {is_returning_id}},
          {SPV_OPERAND_TYPE_ID, {enclosing_merge}},
          {SPV_OPERAND_TYPE_ID, {original_succ}}});
   }
 
-  assert(function->entry()->terminator()->opcode() == SpvOpBranch &&
+  assert(function->entry()->terminator()->opcode() == spv::Op::OpBranch &&
          "The entry block should branch unconditionally to another block.");
   uint32_t block_after_entry =
       function->entry()->terminator()->GetSingleWordInOperand(0);
@@ -498,7 +498,7 @@
   // Create the header for the new outer loop.
   auto outer_loop_header =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.outer_header_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.outer_header_id(),
           opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.outer_header_id());
@@ -506,15 +506,16 @@
   // Add the instruction:
   //   OpLoopMerge %outer_return_id %unreachable_continue_id None
   outer_loop_header->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLoopMerge, 0, 0,
+      ir_context, spv::Op::OpLoopMerge, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.outer_return_id()}},
           {SPV_OPERAND_TYPE_ID, {message_.unreachable_continue_id()}},
-          {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));
+          {SPV_OPERAND_TYPE_LOOP_CONTROL,
+           {uint32_t(spv::LoopControlMask::MaskNone)}}}));
 
   // Add unconditional branch to %block_after_entry.
   outer_loop_header->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {block_after_entry}}}));
 
@@ -531,7 +532,7 @@
   ir_context->get_def_use_mgr()->ForEachUse(
       function->entry()->id(),
       [this](opt::Instruction* use_instruction, uint32_t use_operand_index) {
-        if (use_instruction->opcode() == SpvOpPhi) {
+        if (use_instruction->opcode() == spv::Op::OpPhi) {
           use_instruction->SetOperand(use_operand_index,
                                       {message_.outer_header_id()});
         }
@@ -540,7 +541,7 @@
   // Create the merge block for the loop (and return block for the function).
   auto outer_return_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.outer_return_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.outer_return_id(),
           opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.outer_return_id());
@@ -561,20 +562,20 @@
 
     // Insert the OpPhi instruction.
     outer_return_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpPhi, function->type_id(), message_.return_val_id(),
-        std::move(operand_list)));
+        ir_context, spv::Op::OpPhi, function->type_id(),
+        message_.return_val_id(), std::move(operand_list)));
 
     fuzzerutil::UpdateModuleIdBound(ir_context, message_.return_val_id());
 
     // Insert the OpReturnValue instruction.
     outer_return_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpReturnValue, 0, 0,
+        ir_context, spv::Op::OpReturnValue, 0, 0,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {message_.return_val_id()}}}));
   } else {
     // Insert an OpReturn instruction (the function is void).
     outer_return_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpReturn, 0, 0, opt::Instruction::OperandList{}));
+        ir_context, spv::Op::OpReturn, 0, 0, opt::Instruction::OperandList{}));
   }
 
   // Insert the new return block at the end of the function.
@@ -583,7 +584,7 @@
   // Create the unreachable continue block associated with the enclosing loop.
   auto unreachable_continue_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.unreachable_continue_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.unreachable_continue_id(),
           opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context,
@@ -591,7 +592,7 @@
 
   // Insert an branch back to the loop header, to create a back edge.
   unreachable_continue_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.outer_header_id()}}}));
 
@@ -751,7 +752,7 @@
                   // The usage is OK if it is inside an OpPhi instruction in the
                   // merge block.
                   return block_use == merge_block &&
-                         inst_use->opcode() == SpvOpPhi;
+                         inst_use->opcode() == spv::Op::OpPhi;
                 });
           });
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_move_instruction_down.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_move_instruction_down.cpp
index c8139e7..4d5d9f0 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_move_instruction_down.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_move_instruction_down.cpp
@@ -26,7 +26,7 @@
 
 std::string GetExtensionSet(opt::IRContext* ir_context,
                             const opt::Instruction& op_ext_inst) {
-  assert(op_ext_inst.opcode() == SpvOpExtInst && "Wrong opcode");
+  assert(op_ext_inst.opcode() == spv::Op::OpExtInst && "Wrong opcode");
 
   const auto* ext_inst_import = ir_context->get_def_use_mgr()->GetDef(
       op_ext_inst.GetSingleWordInOperand(0));
@@ -142,112 +142,112 @@
 bool TransformationMoveInstructionDown::IsSimpleInstruction(
     opt::IRContext* ir_context, const opt::Instruction& inst) {
   switch (inst.opcode()) {
-    case SpvOpNop:
-    case SpvOpUndef:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
+    case spv::Op::OpNop:
+    case spv::Op::OpUndef:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
       // OpAccessChain and OpInBoundsAccessChain are considered simple
       // instructions since they result in a pointer to the object in memory,
       // not the object itself.
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpCopyLogical:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpCopyLogical:
       return true;
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       const auto* ext_inst_import =
           ir_context->get_def_use_mgr()->GetDef(inst.GetSingleWordInOperand(0));
 
@@ -346,53 +346,53 @@
     opt::IRContext* ir_context, const opt::Instruction& inst) {
   switch (inst.opcode()) {
       // Some simple instructions.
-    case SpvOpLoad:
-    case SpvOpCopyMemory:
+    case spv::Op::OpLoad:
+    case spv::Op::OpCopyMemory:
       // Image instructions.
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageRead:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseRead:
       // Atomic instructions.
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return true;
       // Extensions.
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       if (GetExtensionSet(ir_context, inst) != kExtensionSetName) {
         return false;
       }
@@ -419,53 +419,53 @@
 
   switch (inst.opcode()) {
       // Simple instructions.
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       // Image instructions.
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageRead:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseRead:
       // Atomic instructions.
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return inst.GetSingleWordInOperand(0);
-    case SpvOpCopyMemory:
+    case spv::Op::OpCopyMemory:
       return inst.GetSingleWordInOperand(1);
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       assert(GetExtensionSet(ir_context, inst) == kExtensionSetName &&
              "Extension set is not supported");
 
@@ -493,31 +493,31 @@
     opt::IRContext* ir_context, const opt::Instruction& inst) {
   switch (inst.opcode()) {
       // Simple Instructions.
-    case SpvOpStore:
-    case SpvOpCopyMemory:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
       // Image instructions.
-    case SpvOpImageWrite:
+    case spv::Op::OpImageWrite:
       // Atomic instructions.
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
-    case SpvOpAtomicFlagClear:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicFlagClear:
       return true;
       // Extensions.
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       if (GetExtensionSet(ir_context, inst) != kExtensionSetName) {
         return false;
       }
@@ -537,28 +537,28 @@
          "|inst| is not a memory write instruction");
 
   switch (inst.opcode()) {
-    case SpvOpStore:
-    case SpvOpCopyMemory:
-    case SpvOpImageWrite:
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
-    case SpvOpAtomicFlagClear:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpImageWrite:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicFlagClear:
       return inst.GetSingleWordInOperand(0);
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       assert(GetExtensionSet(ir_context, inst) == kExtensionSetName &&
              "Extension set is not supported");
 
@@ -590,9 +590,9 @@
 bool TransformationMoveInstructionDown::IsBarrierInstruction(
     const opt::Instruction& inst) {
   switch (inst.opcode()) {
-    case SpvOpMemoryBarrier:
-    case SpvOpControlBarrier:
-    case SpvOpMemoryNamedBarrier:
+    case spv::Op::OpMemoryBarrier:
+    case spv::Op::OpControlBarrier:
+    case spv::Op::OpMemoryNamedBarrier:
       return true;
     default:
       return false;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_mutate_pointer.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_mutate_pointer.cpp
index 516a0d6..a1620cc 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_mutate_pointer.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_mutate_pointer.cpp
@@ -51,7 +51,7 @@
   // Check that it is possible to insert OpLoad and OpStore before
   // |insert_before_inst|. We are only using OpLoad here since the result does
   // not depend on the opcode.
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad,
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
                                                     insert_before_inst)) {
     return false;
   }
@@ -100,7 +100,7 @@
 
   // Back up the original value.
   auto backup_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLoad, pointee_type_id, message_.fresh_id(),
+      ir_context, spv::Op::OpLoad, pointee_type_id, message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}});
   auto backup_instruction_ptr = backup_instruction.get();
@@ -110,7 +110,7 @@
 
   // Insert a new value.
   auto new_value_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpStore, 0, 0,
+      ir_context, spv::Op::OpStore, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
           {SPV_OPERAND_TYPE_ID,
@@ -123,7 +123,7 @@
 
   // Restore the original value.
   auto restore_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpStore, 0, 0,
+      ir_context, spv::Op::OpStore, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
           {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}});
@@ -145,8 +145,9 @@
     opt::IRContext* ir_context, const opt::Instruction& inst) {
   // |inst| must have both result id and type id and it may not cause undefined
   // behaviour.
-  if (!inst.result_id() || !inst.type_id() || inst.opcode() == SpvOpUndef ||
-      inst.opcode() == SpvOpConstantNull) {
+  if (!inst.result_id() || !inst.type_id() ||
+      inst.opcode() == spv::Op::OpUndef ||
+      inst.opcode() == spv::Op::OpConstantNull) {
     return false;
   }
 
@@ -155,15 +156,16 @@
   assert(type_inst != nullptr && "|inst| has invalid type id");
 
   // |inst| must be a pointer.
-  if (type_inst->opcode() != SpvOpTypePointer) {
+  if (type_inst->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
   // |inst| must have a supported storage class.
-  switch (static_cast<SpvStorageClass>(type_inst->GetSingleWordInOperand(0))) {
-    case SpvStorageClassFunction:
-    case SpvStorageClassPrivate:
-    case SpvStorageClassWorkgroup:
+  switch (
+      static_cast<spv::StorageClass>(type_inst->GetSingleWordInOperand(0))) {
+    case spv::StorageClass::Function:
+    case spv::StorageClass::Private:
+    case spv::StorageClass::Workgroup:
       break;
     default:
       return false;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_outline_function.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_outline_function.cpp
index 3140fa6..4ab68d0 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_outline_function.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_outline_function.cpp
@@ -107,7 +107,7 @@
   // The entry and exit block ids must indeed refer to blocks.
   for (auto block_id : {message_.entry_block(), message_.exit_block()}) {
     auto block_label = ir_context->get_def_use_mgr()->GetDef(block_id);
-    if (!block_label || block_label->opcode() != SpvOpLabel) {
+    if (!block_label || block_label->opcode() != spv::Op::OpLabel) {
       return false;
     }
   }
@@ -118,7 +118,7 @@
   // The entry block cannot start with OpVariable - this would mean that
   // outlining would remove a variable from the function containing the region
   // being outlined.
-  if (entry_block->begin()->opcode() == SpvOpVariable) {
+  if (entry_block->begin()->opcode() == spv::Op::OpVariable) {
     return false;
   }
 
@@ -136,7 +136,7 @@
   // The entry block cannot start with OpPhi.  This is to keep the
   // transformation logic simple.  (Another transformation to split the OpPhis
   // from a block could be applied to avoid this scenario.)
-  if (entry_block->begin()->opcode() == SpvOpPhi) {
+  if (entry_block->begin()->opcode() == spv::Op::OpPhi) {
     return false;
   }
 
@@ -257,10 +257,10 @@
     auto input_id_inst = ir_context->get_def_use_mgr()->GetDef(id);
     if (ir_context->get_def_use_mgr()
             ->GetDef(input_id_inst->type_id())
-            ->opcode() == SpvOpTypePointer) {
+            ->opcode() == spv::Op::OpTypePointer) {
       switch (input_id_inst->opcode()) {
-        case SpvOpFunctionParameter:
-        case SpvOpVariable:
+        case spv::Op::OpFunctionParameter:
+        case spv::Op::OpVariable:
           // These are OK.
           break;
         default:
@@ -286,7 +286,7 @@
         // function)
         || ir_context->get_def_use_mgr()
                    ->GetDef(fuzzerutil::GetTypeId(ir_context, id))
-                   ->opcode() == SpvOpTypePointer) {
+                   ->opcode() == spv::Op::OpTypePointer) {
       return false;
     }
   }
@@ -608,7 +608,7 @@
         auto output_id_type =
             ir_context->get_def_use_mgr()->GetDef(output_id)->type_id();
         if (ir_context->get_def_use_mgr()->GetDef(output_id_type)->opcode() ==
-            SpvOpTypeVoid) {
+            spv::Op::OpTypeVoid) {
           // We cannot add a void field to a struct.  We instead use OpUndef to
           // handle void output ids.
           continue;
@@ -617,7 +617,7 @@
       }
       // Add a new struct type to the module.
       ir_context->module()->AddType(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpTypeStruct, 0,
+          ir_context, spv::Op::OpTypeStruct, 0,
           message_.new_function_struct_return_type_id(),
           std::move(struct_member_types)));
       // The return type for the function is the newly-created struct.
@@ -638,7 +638,7 @@
     // Add a new function type to the module, and record that this is the type
     // id for the new function.
     ir_context->module()->AddType(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpTypeFunction, 0, message_.new_function_type_id(),
+        ir_context, spv::Op::OpTypeFunction, 0, message_.new_function_type_id(),
         function_type_operands));
     function_type_id = message_.new_function_type_id();
   }
@@ -647,10 +647,11 @@
   // and the return type and function type prepared above.
   std::unique_ptr<opt::Function> outlined_function =
       MakeUnique<opt::Function>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFunction, return_type_id, message_.new_function_id(),
+          ir_context, spv::Op::OpFunction, return_type_id,
+          message_.new_function_id(),
           opt::Instruction::OperandList(
               {{spv_operand_type_t ::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                {SpvFunctionControlMaskNone}},
+                {uint32_t(spv::FunctionControlMask::MaskNone)}},
                {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
                 {function_type_id}}})));
 
@@ -659,7 +660,7 @@
   for (auto id : region_input_ids) {
     uint32_t fresh_id = input_id_to_fresh_id_map.at(id);
     outlined_function->AddParameter(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFunctionParameter,
+        ir_context, spv::Op::OpFunctionParameter,
         ir_context->get_def_use_mgr()->GetDef(id)->type_id(), fresh_id,
         opt::Instruction::OperandList()));
 
@@ -788,7 +789,8 @@
   // |message_.new_function_region_entry_block| as its id.
   std::unique_ptr<opt::BasicBlock> outlined_region_entry_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.new_function_region_entry_block(),
+          ir_context, spv::Op::OpLabel, 0,
+          message_.new_function_region_entry_block(),
           opt::Instruction::OperandList()));
 
   if (&original_region_entry_block == &original_region_exit_block) {
@@ -854,8 +856,8 @@
   // the cloned exit block.
   for (auto inst_it = outlined_region_exit_block->begin();
        inst_it != outlined_region_exit_block->end();) {
-    if (inst_it->opcode() == SpvOpLoopMerge ||
-        inst_it->opcode() == SpvOpSelectionMerge) {
+    if (inst_it->opcode() == spv::Op::OpLoopMerge ||
+        inst_it->opcode() == spv::Op::OpSelectionMerge) {
       inst_it = inst_it.Erase();
     } else if (inst_it->IsBlockTerminator()) {
       inst_it = inst_it.Erase();
@@ -870,7 +872,7 @@
     // The case where there are no region output ids is simple: we just add
     // OpReturn.
     outlined_region_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpReturn, 0, 0, opt::Instruction::OperandList()));
+        ir_context, spv::Op::OpReturn, 0, 0, opt::Instruction::OperandList()));
   } else {
     // In the case where there are output ids, we add an OpCompositeConstruct
     // instruction to pack all the non-void output values into a struct, and
@@ -879,23 +881,24 @@
     for (uint32_t id : region_output_ids) {
       if (ir_context->get_def_use_mgr()
               ->GetDef(output_id_to_type_id.at(id))
-              ->opcode() != SpvOpTypeVoid) {
+              ->opcode() != spv::Op::OpTypeVoid) {
         struct_member_operands.push_back(
             {SPV_OPERAND_TYPE_ID, {output_id_to_fresh_id_map.at(id)}});
       }
     }
     outlined_region_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct,
+        ir_context, spv::Op::OpCompositeConstruct,
         message_.new_function_struct_return_type_id(),
         message_.new_callee_result_id(), struct_member_operands));
     outlined_region_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpReturnValue, 0, 0,
+        ir_context, spv::Op::OpReturnValue, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.new_callee_result_id()}}})));
   }
 
-  outlined_function->SetFunctionEnd(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionEnd, 0, 0, opt::Instruction::OperandList()));
+  outlined_function->SetFunctionEnd(
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpFunctionEnd, 0, 0,
+                                   opt::Instruction::OperandList()));
 }
 
 void TransformationOutlineFunction::ShrinkOriginalRegion(
@@ -963,7 +966,7 @@
   }
 
   original_region_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionCall, return_type_id,
+      ir_context, spv::Op::OpFunctionCall, return_type_id,
       message_.new_caller_result_id(), function_call_operands));
 
   // If there are output ids, the function call will return a struct.  For each
@@ -975,15 +978,15 @@
   for (uint32_t output_id : region_output_ids) {
     uint32_t output_type_id = output_id_to_type_id.at(output_id);
     if (ir_context->get_def_use_mgr()->GetDef(output_type_id)->opcode() ==
-        SpvOpTypeVoid) {
+        spv::Op::OpTypeVoid) {
       original_region_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpUndef, output_type_id, output_id,
+          ir_context, spv::Op::OpUndef, output_type_id, output_id,
           opt::Instruction::OperandList()));
       // struct_member_index is not incremented since there was no struct member
       // associated with this void-typed output id.
     } else {
       original_region_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract, output_type_id, output_id,
+          ir_context, spv::Op::OpCompositeExtract, output_type_id, output_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.new_caller_result_id()}},
                {SPV_OPERAND_TYPE_LITERAL_INTEGER, {struct_member_index}}})));
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_permute_function_parameters.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_permute_function_parameters.cpp
index 5663d72..b666cdf 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_permute_function_parameters.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_permute_function_parameters.cpp
@@ -43,7 +43,7 @@
   // Check that function exists
   const auto* function =
       fuzzerutil::FindFunction(ir_context, message_.function_id());
-  if (!function || function->DefInst().opcode() != SpvOpFunction ||
+  if (!function || function->DefInst().opcode() != spv::Op::OpFunction ||
       fuzzerutil::FunctionIsEntryPoint(ir_context, function->result_id())) {
     return false;
   }
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_permute_phi_operands.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_permute_phi_operands.cpp
index 7ee7a82..f2f4057 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_permute_phi_operands.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_permute_phi_operands.cpp
@@ -39,7 +39,7 @@
   // Check that |message_.result_id| is valid.
   const auto* inst =
       ir_context->get_def_use_mgr()->GetDef(message_.result_id());
-  if (!inst || inst->opcode() != SpvOpPhi) {
+  if (!inst || inst->opcode() != spv::Op::OpPhi) {
     return false;
   }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_down.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_down.cpp
index c3b7c4d..4b98784 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_down.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_down.cpp
@@ -144,7 +144,7 @@
         ->block(merge_block_id)
         ->begin()
         ->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpPhi, inst_to_propagate->type_id(),
+            ir_context, spv::Op::OpPhi, inst_to_propagate->type_id(),
             message_.phi_fresh_id(), std::move(in_operands)));
 
     fuzzerutil::UpdateModuleIdBound(ir_context, message_.phi_fresh_id());
@@ -234,115 +234,115 @@
   return result;
 }
 
-bool TransformationPropagateInstructionDown::IsOpcodeSupported(SpvOp opcode) {
+bool TransformationPropagateInstructionDown::IsOpcodeSupported(spv::Op opcode) {
   // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3605):
   //  We only support "simple" instructions that don't work with memory.
   //  We should extend this so that we support the ones that modify the memory
   //  too.
   switch (opcode) {
-    case SpvOpUndef:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpArrayLength:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpCopyLogical:
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
+    case spv::Op::OpUndef:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpArrayLength:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpCopyLogical:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
       return true;
     default:
       return false;
@@ -408,7 +408,7 @@
   // use |inst|.
   for (auto successor_id : successor_ids) {
     for (const auto& maybe_phi_inst : *ir_context->cfg()->block(successor_id)) {
-      if (maybe_phi_inst.opcode() != SpvOpPhi) {
+      if (maybe_phi_inst.opcode() != spv::Op::OpPhi) {
         // OpPhis can be intermixed with OpLine and OpNoLine.
         continue;
       }
@@ -446,7 +446,7 @@
         // |phi_block_id| dominates |user|'s block (or its predecessor if the
         // user is an OpPhi). We can't use fuzzerutil::IdIsAvailableAtUse since
         // the id in question hasn't yet been created in the module.
-        auto block_id_to_dominate = user->opcode() == SpvOpPhi
+        auto block_id_to_dominate = user->opcode() == spv::Op::OpPhi
                                         ? user->GetSingleWordOperand(index + 1)
                                         : user_block->id();
 
@@ -465,7 +465,7 @@
 
 opt::Instruction*
 TransformationPropagateInstructionDown::GetFirstInsertBeforeInstruction(
-    opt::IRContext* ir_context, uint32_t block_id, SpvOp opcode) {
+    opt::IRContext* ir_context, uint32_t block_id, spv::Op opcode) {
   auto* block = ir_context->cfg()->block(block_id);
 
   auto it = block->begin();
@@ -572,7 +572,7 @@
   // OpPhi instructions cannot have operands of pointer types.
   if (propagate_type->AsPointer() &&
       !ir_context->get_feature_mgr()->HasCapability(
-          SpvCapabilityVariablePointersStorageBuffer)) {
+          spv::Capability::VariablePointersStorageBuffer)) {
     return 0;
   }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_down.h b/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_down.h
index 560d7dc..9133928 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_down.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_down.h
@@ -120,12 +120,12 @@
                                                      uint32_t block_id);
 
   // Returns true if |opcode| is supported by this transformation.
-  static bool IsOpcodeSupported(SpvOp opcode);
+  static bool IsOpcodeSupported(spv::Op opcode);
 
   // Returns the first instruction in the |block| that allows us to insert
   // |opcode| above itself. Returns nullptr is no such instruction exists.
   static opt::Instruction* GetFirstInsertBeforeInstruction(
-      opt::IRContext* ir_context, uint32_t block_id, SpvOp opcode);
+      opt::IRContext* ir_context, uint32_t block_id, spv::Op opcode);
 
   // Returns a result id of a basic block, where an OpPhi instruction can be
   // inserted. Returns nullptr if it's not possible to create an OpPhi. The
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_up.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_up.cpp
index bf0e663..f9674fa 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_up.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_up.cpp
@@ -23,7 +23,7 @@
 
 uint32_t GetResultIdFromLabelId(const opt::Instruction& phi_inst,
                                 uint32_t label_id) {
-  assert(phi_inst.opcode() == SpvOpPhi && "|phi_inst| is not an OpPhi");
+  assert(phi_inst.opcode() == spv::Op::OpPhi && "|phi_inst| is not an OpPhi");
 
   for (uint32_t i = 1; i < phi_inst.NumInOperands(); i += 2) {
     if (phi_inst.GetSingleWordInOperand(i) == label_id) {
@@ -66,7 +66,7 @@
     assert(dependency && "Operand has invalid id");
 
     if (ir_context->get_instr_block(dependency) == inst_block &&
-        dependency->opcode() != SpvOpPhi) {
+        dependency->opcode() != spv::Op::OpPhi) {
       // |dependency| is "valid" if it's an OpPhi from the same basic block or
       // an instruction from a different basic block.
       return false;
@@ -173,7 +173,7 @@
         continue;
       }
 
-      assert(dependency_inst->opcode() == SpvOpPhi &&
+      assert(dependency_inst->opcode() == spv::Op::OpPhi &&
              "Propagated instruction can depend only on OpPhis from the same "
              "basic block or instructions from different basic blocks");
 
@@ -191,7 +191,7 @@
 
   // Insert an OpPhi instruction into the basic block of |inst|.
   ir_context->get_instr_block(inst)->begin()->InsertBefore(
-      MakeUnique<opt::Instruction>(ir_context, SpvOpPhi, inst->type_id(),
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpPhi, inst->type_id(),
                                    inst->result_id(),
                                    std::move(op_phi_operands)));
 
@@ -210,115 +210,115 @@
   return result;
 }
 
-bool TransformationPropagateInstructionUp::IsOpcodeSupported(SpvOp opcode) {
+bool TransformationPropagateInstructionUp::IsOpcodeSupported(spv::Op opcode) {
   // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3605):
   //  We only support "simple" instructions that don't work with memory.
   //  We should extend this so that we support the ones that modify the memory
   //  too.
   switch (opcode) {
-    case SpvOpUndef:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpArrayLength:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpCopyLogical:
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
+    case spv::Op::OpUndef:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpArrayLength:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpCopyLogical:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
       return true;
     default:
       return false;
@@ -338,7 +338,7 @@
     // - it must be supported by this transformation
     // - it may depend only on instructions from different basic blocks or on
     //   OpPhi instructions from the same basic block.
-    if (inst.opcode() == SpvOpPhi || !IsOpcodeSupported(inst.opcode()) ||
+    if (inst.opcode() == spv::Op::OpPhi || !IsOpcodeSupported(inst.opcode()) ||
         !inst.type_id() || !inst.result_id()) {
       continue;
     }
@@ -353,7 +353,7 @@
     }
 
     if (!ir_context->get_feature_mgr()->HasCapability(
-            SpvCapabilityVariablePointersStorageBuffer) &&
+            spv::Capability::VariablePointersStorageBuffer) &&
         ContainsPointers(*inst_type)) {
       // OpPhi supports pointer operands only with VariablePointers or
       // VariablePointersStorageBuffer capabilities.
@@ -377,7 +377,7 @@
     opt::IRContext* ir_context, uint32_t block_id) {
   // Check that |block_id| is valid.
   const auto* label_inst = ir_context->get_def_use_mgr()->GetDef(block_id);
-  if (!label_inst || label_inst->opcode() != SpvOpLabel) {
+  if (!label_inst || label_inst->opcode() != spv::Op::OpLabel) {
     return false;
   }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_up.h b/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_up.h
index 0ca051b..93aa365 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_up.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_propagate_instruction_up.h
@@ -80,7 +80,7 @@
                                                      uint32_t block_id);
 
   // Returns true if |opcode| is supported by this transformation.
-  static bool IsOpcodeSupported(SpvOp opcode);
+  static bool IsOpcodeSupported(spv::Op opcode);
 
   protobufs::TransformationPropagateInstructionUp message_;
 };
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_push_id_through_variable.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_push_id_through_variable.cpp
index 55a57a1..2372d70 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_push_id_through_variable.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_push_id_through_variable.cpp
@@ -53,9 +53,9 @@
 
   // It must be valid to insert the OpStore and OpLoad instruction before it.
   if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-          SpvOpStore, instruction_to_insert_before) ||
+          spv::Op::OpStore, instruction_to_insert_before) ||
       !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-          SpvOpLoad, instruction_to_insert_before)) {
+          spv::Op::OpLoad, instruction_to_insert_before)) {
     return false;
   }
 
@@ -75,14 +75,16 @@
   // A pointer type instruction pointing to the value type must be defined.
   auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
       ir_context, value_instruction->type_id(),
-      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+      static_cast<spv::StorageClass>(message_.variable_storage_class()));
   if (!pointer_type_id) {
     return false;
   }
 
   // |message_.variable_storage_class| must be private or function.
-  assert((message_.variable_storage_class() == SpvStorageClassPrivate ||
-          message_.variable_storage_class() == SpvStorageClassFunction) &&
+  assert((message_.variable_storage_class() ==
+              (uint32_t)spv::StorageClass::Private ||
+          message_.variable_storage_class() ==
+              (uint32_t)spv::StorageClass::Function) &&
          "The variable storage class must be private or function.");
 
   // Check that initializer is valid.
@@ -111,14 +113,15 @@
   // A pointer type instruction pointing to the value type must be defined.
   auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
       ir_context, value_instruction->type_id(),
-      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+      static_cast<spv::StorageClass>(message_.variable_storage_class()));
   assert(pointer_type_id && "The required pointer type must be available.");
 
   // Adds whether a global or local variable.
-  if (message_.variable_storage_class() == SpvStorageClassPrivate) {
+  if (spv::StorageClass(message_.variable_storage_class()) ==
+      spv::StorageClass::Private) {
     opt::Instruction* global_variable = fuzzerutil::AddGlobalVariable(
         ir_context, message_.variable_id(), pointer_type_id,
-        SpvStorageClassPrivate, message_.initializer_id());
+        spv::StorageClass::Private, message_.initializer_id());
     ir_context->get_def_use_mgr()->AnalyzeInstDefUse(global_variable);
   } else {
     opt::Function* function =
@@ -138,13 +141,13 @@
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.value_synonym_id());
   opt::Instruction* load_instruction =
       insert_before->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLoad, value_instruction->type_id(),
+          ir_context, spv::Op::OpLoad, value_instruction->type_id(),
           message_.value_synonym_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}}})));
   opt::Instruction* store_instruction =
       load_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpStore, 0, 0,
+          ir_context, spv::Op::OpStore, 0, 0,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}},
                {SPV_OPERAND_TYPE_ID, {message_.value_id()}}})));
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp
index e1977a6..03e9737 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp
@@ -97,20 +97,20 @@
 
   // Determine the opcode of the new instruction that computes the result into a
   // struct.
-  SpvOp new_instruction_opcode;
+  spv::Op new_instruction_opcode;
 
   switch (original_instruction->opcode()) {
-    case SpvOpIAdd:
-      new_instruction_opcode = SpvOpIAddCarry;
+    case spv::Op::OpIAdd:
+      new_instruction_opcode = spv::Op::OpIAddCarry;
       break;
-    case SpvOpISub:
-      new_instruction_opcode = SpvOpISubBorrow;
+    case spv::Op::OpISub:
+      new_instruction_opcode = spv::Op::OpISubBorrow;
       break;
-    case SpvOpIMul:
+    case spv::Op::OpIMul:
       if (!operand_is_signed) {
-        new_instruction_opcode = SpvOpUMulExtended;
+        new_instruction_opcode = spv::Op::OpUMulExtended;
       } else {
-        new_instruction_opcode = SpvOpSMulExtended;
+        new_instruction_opcode = spv::Op::OpSMulExtended;
       }
       break;
     default:
@@ -148,7 +148,7 @@
   // takes the first component of the struct which represents low-order bits of
   // the operation. This is the original result.
   original_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCompositeExtract, original_instruction->type_id(),
+      ir_context, spv::Op::OpCompositeExtract, original_instruction->type_id(),
       message_.result_id(),
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {message_.struct_fresh_id()}},
@@ -168,9 +168,9 @@
 
   // Only instructions OpIAdd, OpISub, OpIMul are supported.
   switch (instruction_opcode) {
-    case SpvOpIAdd:
-    case SpvOpISub:
-    case SpvOpIMul:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIMul:
       break;
     default:
       return false;
@@ -201,8 +201,8 @@
   auto type = ir_context->get_type_mgr()->GetType(instruction.type_id());
 
   switch (instruction_opcode) {
-    case SpvOpIAdd:
-    case SpvOpISub: {
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub: {
       // In case of OpIAdd and OpISub if the operand is a vector, the component
       // type must be unsigned. Otherwise (if the operand is an int), the
       // operand must be unsigned.
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
index 2429351..efd1555 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
@@ -28,7 +28,8 @@
 // operator |binop|, returns true if it is certain that 'lhs binop rhs'
 // evaluates to |required_value|.
 template <typename T>
-bool float_binop_evaluates_to(T lhs, T rhs, SpvOp binop, bool required_value) {
+bool float_binop_evaluates_to(T lhs, T rhs, spv::Op binop,
+                              bool required_value) {
   // Infinity and NaN values are conservatively treated as out of scope.
   if (!std::isfinite(lhs) || !std::isfinite(rhs)) {
     return false;
@@ -37,20 +38,20 @@
   // The following captures the binary operators that spirv-fuzz can actually
   // generate when turning a boolean constant into a binary expression.
   switch (binop) {
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
       binop_result = (lhs >= rhs);
       break;
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
       binop_result = (lhs > rhs);
       break;
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
       binop_result = (lhs <= rhs);
       break;
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
       binop_result = (lhs < rhs);
       break;
     default:
@@ -61,20 +62,20 @@
 
 // Analogous to 'float_binop_evaluates_to', but for signed int values.
 template <typename T>
-bool signed_int_binop_evaluates_to(T lhs, T rhs, SpvOp binop,
+bool signed_int_binop_evaluates_to(T lhs, T rhs, spv::Op binop,
                                    bool required_value) {
   bool binop_result;
   switch (binop) {
-    case SpvOpSGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
       binop_result = (lhs >= rhs);
       break;
-    case SpvOpSGreaterThan:
+    case spv::Op::OpSGreaterThan:
       binop_result = (lhs > rhs);
       break;
-    case SpvOpSLessThanEqual:
+    case spv::Op::OpSLessThanEqual:
       binop_result = (lhs <= rhs);
       break;
-    case SpvOpSLessThan:
+    case spv::Op::OpSLessThan:
       binop_result = (lhs < rhs);
       break;
     default:
@@ -85,20 +86,20 @@
 
 // Analogous to 'float_binop_evaluates_to', but for unsigned int values.
 template <typename T>
-bool unsigned_int_binop_evaluates_to(T lhs, T rhs, SpvOp binop,
+bool unsigned_int_binop_evaluates_to(T lhs, T rhs, spv::Op binop,
                                      bool required_value) {
   bool binop_result;
   switch (binop) {
-    case SpvOpUGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
       binop_result = (lhs >= rhs);
       break;
-    case SpvOpUGreaterThan:
+    case spv::Op::OpUGreaterThan:
       binop_result = (lhs > rhs);
       break;
-    case SpvOpULessThanEqual:
+    case spv::Op::OpULessThanEqual:
       binop_result = (lhs <= rhs);
       break;
-    case SpvOpULessThan:
+    case spv::Op::OpULessThan:
       binop_result = (lhs < rhs);
       break;
     default:
@@ -118,12 +119,12 @@
 TransformationReplaceBooleanConstantWithConstantBinary::
     TransformationReplaceBooleanConstantWithConstantBinary(
         const protobufs::IdUseDescriptor& id_use_descriptor, uint32_t lhs_id,
-        uint32_t rhs_id, SpvOp comparison_opcode,
+        uint32_t rhs_id, spv::Op comparison_opcode,
         uint32_t fresh_id_for_binary_operation) {
   *message_.mutable_id_use_descriptor() = id_use_descriptor;
   message_.set_lhs_id(lhs_id);
   message_.set_rhs_id(rhs_id);
-  message_.set_opcode(comparison_opcode);
+  message_.set_opcode(uint32_t(comparison_opcode));
   message_.set_fresh_id_for_binary_operation(fresh_id_for_binary_operation);
 }
 
@@ -141,8 +142,8 @@
   if (!boolean_constant) {
     return false;
   }
-  if (!(boolean_constant->opcode() == SpvOpConstantFalse ||
-        boolean_constant->opcode() == SpvOpConstantTrue)) {
+  if (!(boolean_constant->opcode() == spv::Op::OpConstantFalse ||
+        boolean_constant->opcode() == spv::Op::OpConstantTrue)) {
     return false;
   }
 
@@ -152,7 +153,7 @@
   if (!lhs_constant_inst) {
     return false;
   }
-  if (lhs_constant_inst->opcode() != SpvOpConstant) {
+  if (lhs_constant_inst->opcode() != spv::Op::OpConstant) {
     return false;
   }
 
@@ -162,7 +163,7 @@
   if (!rhs_constant_inst) {
     return false;
   }
-  if (rhs_constant_inst->opcode() != SpvOpConstant) {
+  if (rhs_constant_inst->opcode() != spv::Op::OpConstant) {
     return false;
   }
 
@@ -176,9 +177,10 @@
       ir_context->get_constant_mgr()->FindDeclaredConstant(message_.lhs_id());
   auto rhs_constant =
       ir_context->get_constant_mgr()->FindDeclaredConstant(message_.rhs_id());
-  bool expected_result = (boolean_constant->opcode() == SpvOpConstantTrue);
+  bool expected_result =
+      (boolean_constant->opcode() == spv::Op::OpConstantTrue);
 
-  const auto binary_opcode = static_cast<SpvOp>(message_.opcode());
+  const auto binary_opcode = static_cast<spv::Op>(message_.opcode());
 
   // We consider the floating point, signed and unsigned integer cases
   // separately.  In each case the logic is very similar.
@@ -247,7 +249,7 @@
   // a binary operator before an OpVariable, but in any case (b) the
   // constant we would be replacing is the initializer constant of the
   // OpVariable, and this cannot be the result of a binary operation.
-  if (instruction->opcode() == SpvOpVariable) {
+  if (instruction->opcode() == spv::Op::OpVariable) {
     return false;
   }
 
@@ -268,7 +270,7 @@
       {SPV_OPERAND_TYPE_ID, {message_.lhs_id()}},
       {SPV_OPERAND_TYPE_ID, {message_.rhs_id()}}};
   auto binary_instruction = MakeUnique<opt::Instruction>(
-      ir_context, static_cast<SpvOp>(message_.opcode()),
+      ir_context, static_cast<spv::Op>(message_.opcode()),
       ir_context->get_type_mgr()->GetId(&bool_type),
       message_.fresh_id_for_binary_operation(), operands);
   opt::Instruction* result = binary_instruction.get();
@@ -279,7 +281,7 @@
   // If |instruction_before_which_to_insert| is an OpPhi instruction,
   // then |binary_instruction| will be inserted into the parent block associated
   // with the OpPhi variable operand.
-  if (instruction_containing_constant_use->opcode() == SpvOpPhi) {
+  if (instruction_containing_constant_use->opcode() == spv::Op::OpPhi) {
     instruction_before_which_to_insert =
         ir_context->cfg()
             ->block(instruction_containing_constant_use->GetSingleWordInOperand(
@@ -293,8 +295,9 @@
   {
     opt::Instruction* previous_node =
         instruction_before_which_to_insert->PreviousNode();
-    if (previous_node && (previous_node->opcode() == SpvOpLoopMerge ||
-                          previous_node->opcode() == SpvOpSelectionMerge)) {
+    if (previous_node &&
+        (previous_node->opcode() == spv::Op::OpLoopMerge ||
+         previous_node->opcode() == spv::Op::OpSelectionMerge)) {
       instruction_before_which_to_insert = previous_node;
     }
   }
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
index 97c66bf..4d48bf2 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
@@ -32,7 +32,7 @@
 
   TransformationReplaceBooleanConstantWithConstantBinary(
       const protobufs::IdUseDescriptor& id_use_descriptor, uint32_t lhs_id,
-      uint32_t rhs_id, SpvOp comparison_opcode,
+      uint32_t rhs_id, spv::Op comparison_opcode,
       uint32_t fresh_id_for_binary_operation);
 
   // - |message_.fresh_id_for_binary_operation| must not already be used by the
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp
index 9ea7cb6..4150bb1 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp
@@ -26,10 +26,10 @@
 
 TransformationReplaceBranchFromDeadBlockWithExit::
     TransformationReplaceBranchFromDeadBlockWithExit(uint32_t block_id,
-                                                     SpvOp opcode,
+                                                     spv::Op opcode,
                                                      uint32_t return_value_id) {
   message_.set_block_id(block_id);
-  message_.set_opcode(opcode);
+  message_.set_opcode(uint32_t(opcode));
   message_.set_return_value_id(return_value_id);
 }
 
@@ -45,11 +45,11 @@
     return false;
   }
   auto function_return_type_id = block->GetParent()->type_id();
-  switch (message_.opcode()) {
-    case SpvOpKill:
+  switch (spv::Op(message_.opcode())) {
+    case spv::Op::OpKill:
       for (auto& entry_point : ir_context->module()->entry_points()) {
-        if (entry_point.GetSingleWordInOperand(0) !=
-            SpvExecutionModelFragment) {
+        if (spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) !=
+            spv::ExecutionModel::Fragment) {
           // OpKill is only allowed in a fragment shader.  This is a
           // conservative check: if the module contains a non-fragment entry
           // point then adding an OpKill might lead to OpKill being used in a
@@ -58,15 +58,15 @@
         }
       }
       break;
-    case SpvOpReturn:
+    case spv::Op::OpReturn:
       if (ir_context->get_def_use_mgr()
               ->GetDef(function_return_type_id)
-              ->opcode() != SpvOpTypeVoid) {
+              ->opcode() != spv::Op::OpTypeVoid) {
         // OpReturn is only allowed in a function with void return type.
         return false;
       }
       break;
-    case SpvOpReturnValue: {
+    case spv::Op::OpReturnValue: {
       // If the terminator is to be changed to OpReturnValue, with
       // |message_.return_value_id| being the value that will be returned, then
       // |message_.return_value_id| must have a compatible type and be available
@@ -83,7 +83,7 @@
       break;
     }
     default:
-      assert(message_.opcode() == SpvOpUnreachable &&
+      assert(spv::Op(message_.opcode()) == spv::Op::OpUnreachable &&
              "Invalid early exit opcode.");
       break;
   }
@@ -95,7 +95,7 @@
   // If the successor block has OpPhi instructions then arguments related to
   // |message_.block_id| need to be removed from these instruction.
   auto block = ir_context->get_instr_block(message_.block_id());
-  assert(block->terminator()->opcode() == SpvOpBranch &&
+  assert(block->terminator()->opcode() == spv::Op::OpBranch &&
          "Precondition: the block must end with OpBranch.");
   auto successor = ir_context->get_instr_block(
       block->terminator()->GetSingleWordInOperand(0));
@@ -114,12 +114,12 @@
 
   // Rewrite the terminator of |message_.block_id|.
   opt::Instruction::OperandList new_terminator_in_operands;
-  if (message_.opcode() == SpvOpReturnValue) {
+  if (spv::Op(message_.opcode()) == spv::Op::OpReturnValue) {
     new_terminator_in_operands.push_back(
         {SPV_OPERAND_TYPE_ID, {message_.return_value_id()}});
   }
   auto terminator = block->terminator();
-  terminator->SetOpcode(static_cast<SpvOp>(message_.opcode()));
+  terminator->SetOpcode(static_cast<spv::Op>(message_.opcode()));
   terminator->SetInOperands(std::move(new_terminator_in_operands));
   ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
@@ -145,7 +145,7 @@
     return false;
   }
   // The block's terminator must be OpBranch.
-  if (block.terminator()->opcode() != SpvOpBranch) {
+  if (block.terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
   if (ir_context->GetStructuredCFGAnalysis()->IsInContinueConstruct(
@@ -164,7 +164,7 @@
   // Make sure that domination rules are satisfied when we remove the branch
   // from the |block| to its |successor|.
   return fuzzerutil::NewTerminatorPreservesDominationRules(
-      ir_context, block.id(), {ir_context, SpvOpUnreachable});
+      ir_context, block.id(), {ir_context, spv::Op::OpUnreachable});
 }
 
 }  // namespace fuzz
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h
index 89667fc..9a5d42e 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h
@@ -30,7 +30,7 @@
       protobufs::TransformationReplaceBranchFromDeadBlockWithExit message);
 
   TransformationReplaceBranchFromDeadBlockWithExit(uint32_t block_id,
-                                                   SpvOp opcode,
+                                                   spv::Op opcode,
                                                    uint32_t return_value_id);
 
   // - |message_.block_id| must be the id of a dead block that is not part of
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_constant_with_uniform.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_constant_with_uniform.cpp
index c6698c0..7174e6a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_constant_with_uniform.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_constant_with_uniform.cpp
@@ -67,15 +67,15 @@
   // The type id for the access chain is a uniform pointer with base type
   // matching the given constant id type.
   auto type_and_pointer_type =
-      ir_context->get_type_mgr()->GetTypeAndPointerType(constant_type_id,
-                                                        SpvStorageClassUniform);
+      ir_context->get_type_mgr()->GetTypeAndPointerType(
+          constant_type_id, spv::StorageClass::Uniform);
   assert(type_and_pointer_type.first != nullptr);
   assert(type_and_pointer_type.second != nullptr);
   auto pointer_to_uniform_constant_type_id =
       ir_context->get_type_mgr()->GetId(type_and_pointer_type.second.get());
 
   return MakeUnique<opt::Instruction>(
-      ir_context, SpvOpAccessChain, pointer_to_uniform_constant_type_id,
+      ir_context, spv::Op::OpAccessChain, pointer_to_uniform_constant_type_id,
       message_.fresh_id_for_access_chain(), operands_for_access_chain);
 }
 
@@ -84,9 +84,9 @@
     spvtools::opt::IRContext* ir_context, uint32_t constant_type_id) const {
   opt::Instruction::OperandList operands_for_load = {
       {SPV_OPERAND_TYPE_ID, {message_.fresh_id_for_access_chain()}}};
-  return MakeUnique<opt::Instruction>(ir_context, SpvOpLoad, constant_type_id,
-                                      message_.fresh_id_for_load(),
-                                      operands_for_load);
+  return MakeUnique<opt::Instruction>(
+      ir_context, spv::Op::OpLoad, constant_type_id,
+      message_.fresh_id_for_load(), operands_for_load);
 }
 
 opt::Instruction*
@@ -99,7 +99,7 @@
   }
 
   // The use might be in an OpPhi instruction.
-  if (result->opcode() == SpvOpPhi) {
+  if (result->opcode() == spv::Op::OpPhi) {
     // OpPhi instructions must be the first instructions in a block. Thus, we
     // can't insert above the OpPhi instruction. Given the predecessor block
     // that corresponds to the id use, get the last instruction in that block
@@ -108,18 +108,19 @@
         ir_context,
         result->GetSingleWordInOperand(
             message_.id_use_descriptor().in_operand_index() + 1),
-        SpvOpLoad);
+        spv::Op::OpLoad);
   }
 
   // The only operand that we could've replaced in the OpBranchConditional is
   // the condition id. But that operand has a boolean type and uniform variables
   // can't store booleans (see the spec on OpTypeBool). Thus, |result| can't be
   // an OpBranchConditional.
-  assert(result->opcode() != SpvOpBranchConditional &&
+  assert(result->opcode() != spv::Op::OpBranchConditional &&
          "OpBranchConditional has no operands to replace");
 
-  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, result) &&
-         "We should be able to insert OpLoad and OpAccessChain at this point");
+  assert(
+      fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad, result) &&
+      "We should be able to insert OpLoad and OpAccessChain at this point");
   return result;
 }
 
@@ -191,15 +192,15 @@
 
   // The use must not be a variable initializer; these are required to be
   // constants, so it would be illegal to replace one with a uniform access.
-  if (instruction_using_constant->opcode() == SpvOpVariable) {
+  if (instruction_using_constant->opcode() == spv::Op::OpVariable) {
     return false;
   }
 
   // The module needs to have a uniform pointer type suitable for indexing into
   // the uniform variable, i.e. matching the type of the constant we wish to
   // replace with a uniform.
-  opt::analysis::Pointer pointer_to_type_of_constant(declared_constant->type(),
-                                                     SpvStorageClassUniform);
+  opt::analysis::Pointer pointer_to_type_of_constant(
+      declared_constant->type(), spv::StorageClass::Uniform);
   if (!ir_context->get_type_mgr()->GetId(&pointer_to_type_of_constant)) {
     return false;
   }
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp
index de9d1fd..8f14145 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp
@@ -45,7 +45,7 @@
   auto copy_memory_instruction = FindInstruction(
       message_.copy_memory_instruction_descriptor(), ir_context);
   if (!copy_memory_instruction ||
-      copy_memory_instruction->opcode() != SpvOpCopyMemory) {
+      copy_memory_instruction->opcode() != spv::Op::OpCopyMemory) {
     return false;
   }
   return true;
@@ -57,7 +57,7 @@
       message_.copy_memory_instruction_descriptor(), ir_context);
   // |copy_memory_instruction| must be defined.
   assert(copy_memory_instruction &&
-         copy_memory_instruction->opcode() == SpvOpCopyMemory &&
+         copy_memory_instruction->opcode() == spv::Op::OpCopyMemory &&
          "The required OpCopyMemory instruction must be defined.");
 
   // Integrity check: Both operands must be pointers.
@@ -78,8 +78,8 @@
   (void)target_type_opcode;
   (void)source_type_opcode;
 
-  assert(target_type_opcode == SpvOpTypePointer &&
-         source_type_opcode == SpvOpTypePointer &&
+  assert(target_type_opcode == spv::Op::OpTypePointer &&
+         source_type_opcode == spv::Op::OpTypePointer &&
          "Operands must be of type OpTypePointer");
 
   // Integrity check: |source| and |target| must point to the same type.
@@ -100,12 +100,12 @@
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   FindInstruction(message_.copy_memory_instruction_descriptor(), ir_context)
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpStore, 0, 0,
+          ir_context, spv::Op::OpStore, 0, 0,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {target->result_id()}},
                {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}})))
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLoad, target_pointee_type, message_.fresh_id(),
+          ir_context, spv::Op::OpLoad, target_pointee_type, message_.fresh_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {source->result_id()}}})));
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_copy_object_with_store_load.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_copy_object_with_store_load.cpp
index e0643bf..f08a734 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_copy_object_with_store_load.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_copy_object_with_store_load.cpp
@@ -46,7 +46,7 @@
 
   // This must be a defined OpCopyObject instruction.
   if (!copy_object_instruction ||
-      copy_object_instruction->opcode() != SpvOpCopyObject) {
+      copy_object_instruction->opcode() != spv::Op::OpCopyObject) {
     return false;
   }
 
@@ -54,14 +54,14 @@
   // because we cannot define a pointer to pointer.
   if (ir_context->get_def_use_mgr()
           ->GetDef(copy_object_instruction->type_id())
-          ->opcode() == SpvOpTypePointer) {
+          ->opcode() == spv::Op::OpTypePointer) {
     return false;
   }
 
   // A pointer type instruction pointing to the value type must be defined.
   auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
       ir_context, copy_object_instruction->type_id(),
-      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+      static_cast<spv::StorageClass>(message_.variable_storage_class()));
   if (!pointer_type_id) {
     return false;
   }
@@ -74,8 +74,10 @@
     return false;
   }
   // |message_.variable_storage_class| must be Private or Function.
-  return message_.variable_storage_class() == SpvStorageClassPrivate ||
-         message_.variable_storage_class() == SpvStorageClassFunction;
+  return spv::StorageClass(message_.variable_storage_class()) ==
+             spv::StorageClass::Private ||
+         spv::StorageClass(message_.variable_storage_class()) ==
+             spv::StorageClass::Function;
 }
 
 void TransformationReplaceCopyObjectWithStoreLoad::Apply(
@@ -85,7 +87,7 @@
       ir_context->get_def_use_mgr()->GetDef(message_.copy_object_result_id());
   // |copy_object_instruction| must be defined.
   assert(copy_object_instruction &&
-         copy_object_instruction->opcode() == SpvOpCopyObject &&
+         copy_object_instruction->opcode() == spv::Op::OpCopyObject &&
          "The required OpCopyObject instruction must be defined.");
 
   opt::BasicBlock* enclosing_block =
@@ -96,14 +98,15 @@
   // A pointer type instruction pointing to the value type must be defined.
   auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
       ir_context, copy_object_instruction->type_id(),
-      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+      static_cast<spv::StorageClass>(message_.variable_storage_class()));
   assert(pointer_type_id && "The required pointer type must be available.");
 
   // Adds a global or local variable (according to the storage class).
-  if (message_.variable_storage_class() == SpvStorageClassPrivate) {
+  if (spv::StorageClass(message_.variable_storage_class()) ==
+      spv::StorageClass::Private) {
     opt::Instruction* new_global = fuzzerutil::AddGlobalVariable(
         ir_context, message_.fresh_variable_id(), pointer_type_id,
-        SpvStorageClassPrivate, message_.variable_initializer_id());
+        spv::StorageClass::Private, message_.variable_initializer_id());
     ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_global);
   } else {
     opt::Function* function =
@@ -120,13 +123,13 @@
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_variable_id());
   opt::Instruction* load_instruction =
       copy_object_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLoad, copy_object_instruction->type_id(),
+          ir_context, spv::Op::OpLoad, copy_object_instruction->type_id(),
           message_.copy_object_result_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.fresh_variable_id()}}})));
   opt::Instruction* store_instruction =
       load_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpStore, 0, 0,
+          ir_context, spv::Op::OpStore, 0, 0,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.fresh_variable_id()}},
                {SPV_OPERAND_TYPE_ID, {src_operand}}})));
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_irrelevant_id.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_irrelevant_id.cpp
index a71f96a..7f64063 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_irrelevant_id.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_irrelevant_id.cpp
@@ -65,7 +65,7 @@
   }
 
   // The replacement id must not be the result of an OpFunction instruction.
-  if (replacement_id_def->opcode() == SpvOpFunction) {
+  if (replacement_id_def->opcode() == spv::Op::OpFunction) {
     return false;
   }
 
@@ -130,7 +130,7 @@
     AttemptsToReplaceVariableInitializerWithNonConstant(
         const opt::Instruction& use_instruction,
         const opt::Instruction& replacement_for_use) {
-  return use_instruction.opcode() == SpvOpVariable &&
+  return use_instruction.opcode() == spv::Op::OpVariable &&
          !spvOpcodeIsConstant(replacement_for_use.opcode());
 }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_linear_algebra_instruction.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_linear_algebra_instruction.cpp
index 2430cca..fb7b294 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_linear_algebra_instruction.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_linear_algebra_instruction.cpp
@@ -68,28 +68,28 @@
       FindInstruction(message_.instruction_descriptor(), ir_context);
 
   switch (linear_algebra_instruction->opcode()) {
-    case SpvOpTranspose:
+    case spv::Op::OpTranspose:
       ReplaceOpTranspose(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpVectorTimesScalar:
+    case spv::Op::OpVectorTimesScalar:
       ReplaceOpVectorTimesScalar(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpMatrixTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
       ReplaceOpMatrixTimesScalar(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpVectorTimesMatrix:
+    case spv::Op::OpVectorTimesMatrix:
       ReplaceOpVectorTimesMatrix(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesVector:
       ReplaceOpMatrixTimesVector(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpMatrixTimesMatrix:
+    case spv::Op::OpMatrixTimesMatrix:
       ReplaceOpMatrixTimesMatrix(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpOuterProduct:
+    case spv::Op::OpOuterProduct:
       ReplaceOpOuterProduct(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpDot:
+    case spv::Op::OpDot:
       ReplaceOpDot(ir_context, linear_algebra_instruction);
       break;
     default:
@@ -112,7 +112,7 @@
   // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3354):
   // Right now we only support certain operations.
   switch (instruction->opcode()) {
-    case SpvOpTranspose: {
+    case spv::Op::OpTranspose: {
       // For each matrix row, |2 * matrix_column_count| OpCompositeExtract and 1
       // OpCompositeConstruct will be inserted.
       auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
@@ -130,7 +130,7 @@
                                       ->element_count();
       return matrix_row_count * (2 * matrix_column_count + 1);
     }
-    case SpvOpVectorTimesScalar:
+    case spv::Op::OpVectorTimesScalar:
       // For each vector component, 1 OpCompositeExtract and 1 OpFMul will be
       // inserted.
       return 2 *
@@ -140,7 +140,7 @@
                                ->type_id())
                  ->AsVector()
                  ->element_count();
-    case SpvOpMatrixTimesScalar: {
+    case spv::Op::OpMatrixTimesScalar: {
       // For each matrix column, |1 + column.size| OpCompositeExtract,
       // |column.size| OpFMul and 1 OpCompositeConstruct instructions will be
       // inserted.
@@ -154,7 +154,7 @@
                       ->AsVector()
                       ->element_count());
     }
-    case SpvOpVectorTimesMatrix: {
+    case spv::Op::OpVectorTimesMatrix: {
       // For each vector component, 1 OpCompositeExtract instruction will be
       // inserted. For each matrix column, |1 + vector_component_count|
       // OpCompositeExtract, |vector_component_count| OpFMul and
@@ -175,7 +175,7 @@
               ->element_count();
       return vector_component_count * (3 * matrix_column_count + 1);
     }
-    case SpvOpMatrixTimesVector: {
+    case spv::Op::OpMatrixTimesVector: {
       // For each matrix column, |1 + matrix_row_count| OpCompositeExtract
       // will be inserted. For each matrix row, |matrix_column_count| OpFMul and
       // |matrix_column_count - 1| OpFAdd instructions will be inserted. For
@@ -197,7 +197,7 @@
       return 3 * matrix_column_count * matrix_row_count +
              2 * matrix_column_count - matrix_row_count;
     }
-    case SpvOpMatrixTimesMatrix: {
+    case spv::Op::OpMatrixTimesMatrix: {
       // For each matrix 2 column, 1 OpCompositeExtract, 1 OpCompositeConstruct,
       // |3 * matrix_1_row_count * matrix_1_column_count| OpCompositeExtract,
       // |matrix_1_row_count * matrix_1_column_count| OpFMul,
@@ -228,7 +228,7 @@
       return matrix_2_column_count *
              (2 + matrix_1_row_count * (5 * matrix_1_column_count - 1));
     }
-    case SpvOpOuterProduct: {
+    case spv::Op::OpOuterProduct: {
       // For each |vector_2| component, |vector_1_component_count + 1|
       // OpCompositeExtract, |vector_1_component_count| OpFMul and 1
       // OpCompositeConstruct instructions will be inserted.
@@ -248,7 +248,7 @@
               ->element_count();
       return 2 * vector_2_component_count * (vector_1_component_count + 1);
     }
-    case SpvOpDot:
+    case spv::Op::OpDot:
       // For each pair of vector components, 2 OpCompositeExtract and 1 OpFMul
       // will be inserted. The first two OpFMul instructions will result the
       // first OpFAdd instruction to be inserted. For each remaining OpFMul, 1
@@ -299,7 +299,7 @@
       // Extracts the matrix column.
       uint32_t matrix_column_id = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(matrix_column_type),
           matrix_column_id,
           opt::Instruction::OperandList(
@@ -309,7 +309,7 @@
       // Extracts the matrix column component.
       column_component_ids[j] = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(matrix_column_component_type),
           column_component_ids[j],
           opt::Instruction::OperandList(
@@ -324,14 +324,14 @@
     }
     result_column_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct,
+        ir_context, spv::Op::OpCompositeConstruct,
         ir_context->get_type_mgr()->GetId(resulting_matrix_column_type),
         result_column_ids[i], opt::Instruction::OperandList(in_operands)));
   }
 
   // The OpTranspose instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_column_ids[0]});
   for (uint32_t i = 1; i < result_column_ids.size(); i++) {
     linear_algebra_instruction->AddOperand(
@@ -363,7 +363,8 @@
     uint32_t vector_extract_id = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, vector_extract_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract, scalar->type_id(), vector_extract_id,
+        ir_context, spv::Op::OpCompositeExtract, scalar->type_id(),
+        vector_extract_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
              {SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
@@ -373,7 +374,7 @@
     float_multiplication_ids[i] = float_multiplication_id;
     fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFMul, scalar->type_id(), float_multiplication_id,
+        ir_context, spv::Op::OpFMul, scalar->type_id(), float_multiplication_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector_extract_id}},
              {SPV_OPERAND_TYPE_ID, {scalar->result_id()}}})));
@@ -381,7 +382,7 @@
 
   // The OpVectorTimesScalar instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {float_multiplication_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {float_multiplication_ids[1]});
   for (uint32_t i = 2; i < float_multiplication_ids.size(); i++) {
@@ -418,7 +419,7 @@
     uint32_t matrix_extract_id = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, matrix_extract_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(matrix_column_type),
         matrix_extract_id,
         opt::Instruction::OperandList(
@@ -432,8 +433,8 @@
       uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
       fuzzerutil::UpdateModuleIdBound(ir_context, column_extract_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract, scalar_instruction->type_id(),
-          column_extract_id,
+          ir_context, spv::Op::OpCompositeExtract,
+          scalar_instruction->type_id(), column_extract_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {matrix_extract_id}},
                {SPV_OPERAND_TYPE_LITERAL_INTEGER, {j}}})));
@@ -442,7 +443,7 @@
       float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
       fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_ids[j]);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFMul, scalar_instruction->type_id(),
+          ir_context, spv::Op::OpFMul, scalar_instruction->type_id(),
           float_multiplication_ids[j],
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {column_extract_id}},
@@ -458,14 +459,14 @@
     composite_construct_ids[i] = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, composite_construct_ids[i]);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct,
+        ir_context, spv::Op::OpCompositeConstruct,
         ir_context->get_type_mgr()->GetId(matrix_column_type),
         composite_construct_ids[i], composite_construct_in_operands));
   }
 
   // The OpMatrixTimesScalar instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {composite_construct_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {composite_construct_ids[1]});
   for (uint32_t i = 2; i < composite_construct_ids.size(); i++) {
@@ -495,7 +496,7 @@
   for (uint32_t i = 0; i < vector_component_count; i++) {
     vector_component_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(vector_component_type),
         vector_component_ids[i],
         opt::Instruction::OperandList(
@@ -520,7 +521,7 @@
     // Extracts matrix column.
     uint32_t matrix_extract_id = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(matrix_column_type),
         matrix_extract_id,
         opt::Instruction::OperandList(
@@ -532,7 +533,7 @@
       // Extracts column component.
       uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           column_extract_id,
           opt::Instruction::OperandList(
@@ -542,7 +543,7 @@
       // Multiplies corresponding vector and column components.
       float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFMul,
+          ir_context, spv::Op::OpFMul,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           float_multiplication_ids[j],
           opt::Instruction::OperandList(
@@ -555,7 +556,7 @@
     uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
     float_add_ids.push_back(float_add_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFAdd,
+        ir_context, spv::Op::OpFAdd,
         ir_context->get_type_mgr()->GetId(vector_component_type), float_add_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
@@ -564,7 +565,7 @@
       float_add_id = message_.fresh_ids(fresh_id_index++);
       float_add_ids.push_back(float_add_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFAdd,
+          ir_context, spv::Op::OpFAdd,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           float_add_id,
           opt::Instruction::OperandList(
@@ -577,7 +578,7 @@
 
   // The OpVectorTimesMatrix instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_component_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {result_component_ids[1]});
   for (uint32_t i = 2; i < result_component_ids.size(); i++) {
@@ -611,7 +612,7 @@
   for (uint32_t i = 0; i < matrix_column_count; i++) {
     matrix_column_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(matrix_column_type),
         matrix_column_ids[i],
         opt::Instruction::OperandList(
@@ -632,7 +633,7 @@
   for (uint32_t i = 0; i < matrix_column_count; i++) {
     vector_component_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(vector_component_type),
         vector_component_ids[i],
         opt::Instruction::OperandList(
@@ -647,7 +648,7 @@
       // Extracts column component.
       uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           column_extract_id,
           opt::Instruction::OperandList(
@@ -657,7 +658,7 @@
       // Multiplies corresponding vector and column components.
       float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFMul,
+          ir_context, spv::Op::OpFMul,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           float_multiplication_ids[j],
           opt::Instruction::OperandList(
@@ -670,7 +671,7 @@
     uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
     float_add_ids.push_back(float_add_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFAdd,
+        ir_context, spv::Op::OpFAdd,
         ir_context->get_type_mgr()->GetId(vector_component_type), float_add_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
@@ -679,7 +680,7 @@
       float_add_id = message_.fresh_ids(fresh_id_index++);
       float_add_ids.push_back(float_add_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFAdd,
+          ir_context, spv::Op::OpFAdd,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           float_add_id,
           opt::Instruction::OperandList(
@@ -692,7 +693,7 @@
 
   // The OpMatrixTimesVector instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_component_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {result_component_ids[1]});
   for (uint32_t i = 2; i < result_component_ids.size(); i++) {
@@ -743,7 +744,7 @@
     // Extracts matrix 2 column.
     uint32_t matrix_2_column_id = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(matrix_2_column_type),
         matrix_2_column_id,
         opt::Instruction::OperandList(
@@ -757,7 +758,7 @@
         // Extracts matrix 1 column.
         uint32_t matrix_1_column_id = message_.fresh_ids(fresh_id_index++);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpCompositeExtract,
+            ir_context, spv::Op::OpCompositeExtract,
             ir_context->get_type_mgr()->GetId(matrix_1_column_type),
             matrix_1_column_id,
             opt::Instruction::OperandList(
@@ -768,7 +769,7 @@
         uint32_t matrix_1_column_component_id =
             message_.fresh_ids(fresh_id_index++);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpCompositeExtract,
+            ir_context, spv::Op::OpCompositeExtract,
             ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
             matrix_1_column_component_id,
             opt::Instruction::OperandList(
@@ -779,7 +780,7 @@
         uint32_t matrix_2_column_component_id =
             message_.fresh_ids(fresh_id_index++);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpCompositeExtract,
+            ir_context, spv::Op::OpCompositeExtract,
             ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
             matrix_2_column_component_id,
             opt::Instruction::OperandList(
@@ -789,7 +790,7 @@
         // Multiplies corresponding matrix 1 and matrix 2 column components.
         float_multiplication_ids[k] = message_.fresh_ids(fresh_id_index++);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpFMul,
+            ir_context, spv::Op::OpFMul,
             ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
             float_multiplication_ids[k],
             opt::Instruction::OperandList(
@@ -802,7 +803,7 @@
       uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
       float_add_ids.push_back(float_add_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFAdd,
+          ir_context, spv::Op::OpFAdd,
           ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
           float_add_id,
           opt::Instruction::OperandList(
@@ -812,7 +813,7 @@
         float_add_id = message_.fresh_ids(fresh_id_index++);
         float_add_ids.push_back(float_add_id);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpFAdd,
+            ir_context, spv::Op::OpFAdd,
             ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
             float_add_id,
             opt::Instruction::OperandList(
@@ -830,14 +831,14 @@
     }
     result_column_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct,
+        ir_context, spv::Op::OpCompositeConstruct,
         ir_context->get_type_mgr()->GetId(matrix_1_column_type),
         result_column_ids[i], opt::Instruction::OperandList(in_operands)));
   }
 
   // The OpMatrixTimesMatrix instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_column_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {result_column_ids[1]});
   for (uint32_t i = 2; i < result_column_ids.size(); i++) {
@@ -880,7 +881,7 @@
     // Extracts |vector_2| component.
     uint32_t vector_2_component_id = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(vector_1_component_type),
         vector_2_component_id,
         opt::Instruction::OperandList(
@@ -892,7 +893,7 @@
       // Extracts |vector_1| component.
       uint32_t vector_1_component_id = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(vector_1_component_type),
           vector_1_component_id,
           opt::Instruction::OperandList(
@@ -902,7 +903,7 @@
       // Multiplies |vector_1| and |vector_2| components.
       column_component_ids[j] = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFMul,
+          ir_context, spv::Op::OpFMul,
           ir_context->get_type_mgr()->GetId(vector_1_component_type),
           column_component_ids[j],
           opt::Instruction::OperandList(
@@ -917,13 +918,13 @@
     }
     result_column_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct, vector_1_instruction->type_id(),
-        result_column_ids[i], in_operands));
+        ir_context, spv::Op::OpCompositeConstruct,
+        vector_1_instruction->type_id(), result_column_ids[i], in_operands));
   }
 
   // The OpOuterProduct instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_column_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {result_column_ids[1]});
   for (uint32_t i = 2; i < result_column_ids.size(); i++) {
@@ -956,7 +957,7 @@
     uint32_t vector_1_extract_id = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, vector_1_extract_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         linear_algebra_instruction->type_id(), vector_1_extract_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector_1->result_id()}},
@@ -966,7 +967,7 @@
     uint32_t vector_2_extract_id = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, vector_2_extract_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         linear_algebra_instruction->type_id(), vector_2_extract_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector_2->result_id()}},
@@ -976,7 +977,7 @@
     float_multiplication_ids[i] = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_ids[i]);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFMul, linear_algebra_instruction->type_id(),
+        ir_context, spv::Op::OpFMul, linear_algebra_instruction->type_id(),
         float_multiplication_ids[i],
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector_1_extract_id}},
@@ -986,7 +987,7 @@
   // If the vector has 2 components, then there will be 2 float multiplication
   // instructions.
   if (vectors_component_count == 2) {
-    linear_algebra_instruction->SetOpcode(SpvOpFAdd);
+    linear_algebra_instruction->SetOpcode(spv::Op::OpFAdd);
     linear_algebra_instruction->SetInOperand(0, {float_multiplication_ids[0]});
     linear_algebra_instruction->SetInOperand(1, {float_multiplication_ids[1]});
   } else {
@@ -997,7 +998,7 @@
     float_add_ids.push_back(float_add_id);
     fuzzerutil::UpdateModuleIdBound(ir_context, float_add_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFAdd, linear_algebra_instruction->type_id(),
+        ir_context, spv::Op::OpFAdd, linear_algebra_instruction->type_id(),
         float_add_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
@@ -1010,7 +1011,7 @@
       fuzzerutil::UpdateModuleIdBound(ir_context, float_add_id);
       float_add_ids.push_back(float_add_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFAdd, linear_algebra_instruction->type_id(),
+          ir_context, spv::Op::OpFAdd, linear_algebra_instruction->type_id(),
           float_add_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[i]}},
@@ -1019,7 +1020,7 @@
 
     // The last OpFAdd instruction is got by changing some of the OpDot
     // instruction attributes.
-    linear_algebra_instruction->SetOpcode(SpvOpFAdd);
+    linear_algebra_instruction->SetOpcode(spv::Op::OpFAdd);
     linear_algebra_instruction->SetInOperand(
         0, {float_multiplication_ids[float_multiplication_ids.size() - 1]});
     linear_algebra_instruction->SetInOperand(
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
index e75337f..36610f2 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
@@ -48,14 +48,14 @@
   // The OpLoad instruction must be defined.
   auto load_instruction =
       FindInstruction(message_.load_instruction_descriptor(), ir_context);
-  if (!load_instruction || load_instruction->opcode() != SpvOpLoad) {
+  if (!load_instruction || load_instruction->opcode() != spv::Op::OpLoad) {
     return false;
   }
 
   // The OpStore instruction must be defined.
   auto store_instruction =
       FindInstruction(message_.store_instruction_descriptor(), ir_context);
-  if (!store_instruction || store_instruction->opcode() != SpvOpStore) {
+  if (!store_instruction || store_instruction->opcode() != spv::Op::OpStore) {
     return false;
   }
 
@@ -69,7 +69,7 @@
   // Get storage class of the variable pointed by the source operand in OpLoad.
   opt::Instruction* source_id = ir_context->get_def_use_mgr()->GetDef(
       load_instruction->GetSingleWordOperand(2));
-  SpvStorageClass storage_class = fuzzerutil::GetStorageClassFromPointerType(
+  spv::StorageClass storage_class = fuzzerutil::GetStorageClassFromPointerType(
       ir_context, source_id->type_id());
 
   // Iterate over all instructions between |load_instruction| and
@@ -99,11 +99,11 @@
   // OpLoad and OpStore instructions must be defined.
   auto load_instruction =
       FindInstruction(message_.load_instruction_descriptor(), ir_context);
-  assert(load_instruction && load_instruction->opcode() == SpvOpLoad &&
+  assert(load_instruction && load_instruction->opcode() == spv::Op::OpLoad &&
          "The required OpLoad instruction must be defined.");
   auto store_instruction =
       FindInstruction(message_.store_instruction_descriptor(), ir_context);
-  assert(store_instruction && store_instruction->opcode() == SpvOpStore &&
+  assert(store_instruction && store_instruction->opcode() == spv::Op::OpStore &&
          "The required OpStore instruction must be defined.");
 
   // Intermediate values of the OpLoad and the OpStore must match.
@@ -121,7 +121,7 @@
 
   // Insert the OpCopyMemory instruction before the OpStore instruction.
   store_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCopyMemory, 0, 0,
+      ir_context, spv::Op::OpCopyMemory, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {target_variable_id}},
            {SPV_OPERAND_TYPE_ID, {source_variable_id}}})));
@@ -133,14 +133,14 @@
 }
 
 bool TransformationReplaceLoadStoreWithCopyMemory::IsMemoryWritingOpCode(
-    SpvOp op_code) {
+    spv::Op op_code) {
   if (spvOpcodeIsAtomicOp(op_code)) {
-    return op_code != SpvOpAtomicLoad;
+    return op_code != spv::Op::OpAtomicLoad;
   }
   switch (op_code) {
-    case SpvOpStore:
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       return true;
     default:
       return false;
@@ -148,10 +148,10 @@
 }
 
 bool TransformationReplaceLoadStoreWithCopyMemory::IsMemoryBarrierOpCode(
-    SpvOp op_code) {
+    spv::Op op_code) {
   switch (op_code) {
-    case SpvOpMemoryBarrier:
-    case SpvOpMemoryNamedBarrier:
+    case spv::Op::OpMemoryBarrier:
+    case spv::Op::OpMemoryNamedBarrier:
       return true;
     default:
       return false;
@@ -159,13 +159,13 @@
 }
 
 bool TransformationReplaceLoadStoreWithCopyMemory::
-    IsStorageClassSafeAcrossMemoryBarriers(SpvStorageClass storage_class) {
+    IsStorageClassSafeAcrossMemoryBarriers(spv::StorageClass storage_class) {
   switch (storage_class) {
-    case SpvStorageClassUniformConstant:
-    case SpvStorageClassInput:
-    case SpvStorageClassUniform:
-    case SpvStorageClassPrivate:
-    case SpvStorageClassFunction:
+    case spv::StorageClass::UniformConstant:
+    case spv::StorageClass::Input:
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::Private:
+    case spv::StorageClass::Function:
       return true;
     default:
       return false;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_load_store_with_copy_memory.h b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_load_store_with_copy_memory.h
index bb4d27e..43c754e 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_load_store_with_copy_memory.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_load_store_with_copy_memory.h
@@ -52,17 +52,17 @@
 
   // Checks if the instruction that has an |op_code| might write to
   // the source operand of the OpLoad instruction.
-  static bool IsMemoryWritingOpCode(SpvOp op_code);
+  static bool IsMemoryWritingOpCode(spv::Op op_code);
 
   // Checks if the instruction that has an |op_code| is a memory barrier that
   // could interfere with the source operand of the OpLoad instruction
-  static bool IsMemoryBarrierOpCode(SpvOp op_code);
+  static bool IsMemoryBarrierOpCode(spv::Op op_code);
 
   // Checks if the |storage_class| of the source operand of the OpLoad
   // instruction implies that this variable cannot change (due to other threads)
   // across memory barriers.
   static bool IsStorageClassSafeAcrossMemoryBarriers(
-      SpvStorageClass storage_class);
+      spv::StorageClass storage_class);
 
   std::unordered_set<uint32_t> GetFreshIds() const override;
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp
index 84ca1ab..eeda68d 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp
@@ -38,7 +38,7 @@
     const TransformationContext& transformation_context) const {
   // |opphi_id| must be the id of an OpPhi instruction.
   auto opphi_def = ir_context->get_def_use_mgr()->GetDef(message_.opphi_id());
-  if (!opphi_def || opphi_def->opcode() != SpvOpPhi) {
+  if (!opphi_def || opphi_def->opcode() != spv::Op::OpPhi) {
     return false;
   }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp
index c0e6e44..b2010a9 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp
@@ -50,7 +50,7 @@
       ir_context->get_def_use_mgr()->GetDef(message_.select_id());
 
   // The instruction must exist and it must be an OpSelect instruction.
-  if (!instruction || instruction->opcode() != SpvOpSelect) {
+  if (!instruction || instruction->opcode() != spv::Op::OpSelect) {
     return false;
   }
 
@@ -90,7 +90,7 @@
   // The predecessor must not be the header of a construct and it must end with
   // OpBranch.
   if (predecessor->GetMergeInst() != nullptr ||
-      predecessor->terminator()->opcode() != SpvOpBranch) {
+      predecessor->terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
@@ -115,13 +115,14 @@
       fuzzerutil::UpdateModuleIdBound(ir_context, id);
 
       // Create the new block.
-      auto new_block = MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, id, opt::Instruction::OperandList{}));
+      auto new_block = MakeUnique<opt::BasicBlock>(
+          MakeUnique<opt::Instruction>(ir_context, spv::Op::OpLabel, 0, id,
+                                       opt::Instruction::OperandList{}));
 
       // Add an unconditional branch from the new block to the instruction
       // block.
       new_block->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpBranch, 0, 0,
+          ir_context, spv::Op::OpBranch, 0, 0,
           opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {block->id()}}}));
 
       // Insert the new block right after the predecessor of the instruction
@@ -136,10 +137,11 @@
   // Add an OpSelectionMerge instruction to the predecessor block, where the
   // merge block is the instruction block.
   predecessor->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
-      opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {block->id()}},
-                                    {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-                                     {SpvSelectionControlMaskNone}}}));
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
+      opt::Instruction::OperandList{
+          {SPV_OPERAND_TYPE_ID, {block->id()}},
+          {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+           {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
 
   // |if_block| will be the true block, if it has been created, the instruction
   // block otherwise.
@@ -158,7 +160,7 @@
   // Add a conditional branching instruction to the predecessor, branching to
   // |if_block| if the condition is true and to |if_false| otherwise.
   predecessor->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranchConditional, 0, 0,
+      ir_context, spv::Op::OpBranchConditional, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {instruction->GetSingleWordInOperand(0)}},
           {SPV_OPERAND_TYPE_ID, {if_block}},
@@ -177,7 +179,7 @@
   // Replace the OpSelect instruction in the merge block with an OpPhi.
   // This:          OpSelect %type %cond %if %else
   // will become:   OpPhi %type %if %if_pred %else %else_pred
-  instruction->SetOpcode(SpvOpPhi);
+  instruction->SetOpcode(spv::Op::OpPhi);
   std::vector<opt::Operand> operands;
 
   operands.emplace_back(instruction->GetInOperand(1));
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_parameter_with_global.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_parameter_with_global.cpp
index caf6716..e80dfe9 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_parameter_with_global.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_parameter_with_global.cpp
@@ -41,7 +41,7 @@
   // Check that |parameter_id| is valid.
   const auto* param_inst =
       ir_context->get_def_use_mgr()->GetDef(message_.parameter_id());
-  if (!param_inst || param_inst->opcode() != SpvOpFunctionParameter) {
+  if (!param_inst || param_inst->opcode() != spv::Op::OpFunctionParameter) {
     return false;
   }
 
@@ -69,7 +69,7 @@
 
   // Check that pointer type for the global variable exists in the module.
   if (!fuzzerutil::MaybeGetPointerType(ir_context, param_inst->type_id(),
-                                       SpvStorageClassPrivate)) {
+                                       spv::StorageClass::Private)) {
     return false;
   }
 
@@ -91,8 +91,8 @@
   fuzzerutil::AddGlobalVariable(
       ir_context, message_.global_variable_fresh_id(),
       fuzzerutil::MaybeGetPointerType(ir_context, param_inst->type_id(),
-                                      SpvStorageClassPrivate),
-      SpvStorageClassPrivate,
+                                      spv::StorageClass::Private),
+      spv::StorageClass::Private,
       fuzzerutil::MaybeGetZeroConstant(ir_context, *transformation_context,
                                        param_inst->type_id(), false));
 
@@ -103,16 +103,17 @@
   // Insert an OpLoad instruction right after OpVariable instructions.
   auto it = function->begin()->begin();
   while (it != function->begin()->end() &&
-         !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, it)) {
+         !fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad, it)) {
     ++it;
   }
 
-  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, it) &&
+  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad, it) &&
          "Can't insert OpLoad or OpCopyMemory into the first basic block of "
          "the function");
 
   it.InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLoad, param_inst->type_id(), param_inst->result_id(),
+      ir_context, spv::Op::OpLoad, param_inst->type_id(),
+      param_inst->result_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.global_variable_fresh_id()}}}));
 
@@ -132,13 +133,14 @@
 
   // Update all relevant OpFunctionCall instructions.
   for (auto* inst : fuzzerutil::GetCallers(ir_context, function->result_id())) {
-    assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore, inst) &&
-           "Can't insert OpStore right before the function call");
+    assert(
+        fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpStore, inst) &&
+        "Can't insert OpStore right before the function call");
 
     // Insert an OpStore before the OpFunctionCall. +1 since the first
     // operand of OpFunctionCall is an id of the function.
     inst->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpStore, 0, 0,
+        ir_context, spv::Op::OpStore, 0, 0,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {message_.global_variable_fresh_id()}},
             {SPV_OPERAND_TYPE_ID,
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_params_with_struct.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_params_with_struct.cpp
index 13eeccb..c8af14a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_replace_params_with_struct.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_replace_params_with_struct.cpp
@@ -142,7 +142,7 @@
 
   // Add new parameter to the function.
   function->AddParameter(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionParameter, struct_type_id,
+      ir_context, spv::Op::OpFunctionParameter, struct_type_id,
       message_.fresh_parameter_id(), opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_parameter_id());
@@ -182,8 +182,8 @@
     auto fresh_composite_id =
         caller_id_to_fresh_composite_id.at(inst->result_id());
     inst->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct, struct_type_id, fresh_composite_id,
-        std::move(composite_components)));
+        ir_context, spv::Op::OpCompositeConstruct, struct_type_id,
+        fresh_composite_id, std::move(composite_components)));
 
     // Add a new operand to the OpFunctionCall instruction.
     inst->AddOperand({SPV_OPERAND_TYPE_ID, {fresh_composite_id}});
@@ -200,19 +200,19 @@
     // Skip all OpVariable instructions.
     auto iter = function->begin()->begin();
     while (iter != function->begin()->end() &&
-           !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                         iter)) {
+           !fuzzerutil::CanInsertOpcodeBeforeInstruction(
+               spv::Op::OpCompositeExtract, iter)) {
       ++iter;
     }
 
-    assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                        iter) &&
+    assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(
+               spv::Op::OpCompositeExtract, iter) &&
            "Can't extract parameter's value from the structure");
 
     // Insert OpCompositeExtract instructions to unpack parameters' values from
     // the struct type.
     iter.InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract, param_inst->type_id(),
+        ir_context, spv::Op::OpCompositeExtract, param_inst->type_id(),
         param_inst->result_id(),
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {message_.fresh_parameter_id()}},
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_set_function_control.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_set_function_control.cpp
index 02a8c9f..ef48171 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_set_function_control.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_set_function_control.cpp
@@ -40,9 +40,9 @@
 
   // Check (via an assertion) that function control mask doesn't have any bad
   // bits set.
-  uint32_t acceptable_function_control_bits =
-      SpvFunctionControlInlineMask | SpvFunctionControlDontInlineMask |
-      SpvFunctionControlPureMask | SpvFunctionControlConstMask;
+  uint32_t acceptable_function_control_bits = uint32_t(
+      spv::FunctionControlMask::Inline | spv::FunctionControlMask::DontInline |
+      spv::FunctionControlMask::Pure | spv::FunctionControlMask::Const);
   // The following is to keep release-mode compilers happy as this variable is
   // only used in an assertion.
   (void)(acceptable_function_control_bits);
@@ -51,17 +51,19 @@
 
   // Check (via an assertion) that function control mask does not have both
   // Inline and DontInline bits set.
-  assert(!((message_.function_control() & SpvFunctionControlInlineMask) &&
-           (message_.function_control() & SpvFunctionControlDontInlineMask)) &&
+  assert(!((message_.function_control() &
+            (uint32_t)spv::FunctionControlMask::Inline) &&
+           (message_.function_control() &
+            (uint32_t)spv::FunctionControlMask::DontInline)) &&
          "It is not OK to set both the 'Inline' and 'DontInline' bits of a "
          "function control mask");
 
   // Check that Const and Pure are only present if they were present on the
   // original function
   for (auto mask_bit :
-       {SpvFunctionControlPureMask, SpvFunctionControlConstMask}) {
-    if ((message_.function_control() & mask_bit) &&
-        !(existing_function_control_mask & mask_bit)) {
+       {spv::FunctionControlMask::Pure, spv::FunctionControlMask::Const}) {
+    if ((message_.function_control() & uint32_t(mask_bit)) &&
+        !(existing_function_control_mask & uint32_t(mask_bit))) {
       return false;
     }
   }
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_set_loop_control.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_set_loop_control.cpp
index 1449960..dc9ee7c 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_set_loop_control.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_set_loop_control.cpp
@@ -38,18 +38,20 @@
     return false;
   }
   auto merge_inst = block->GetMergeInst();
-  if (!merge_inst || merge_inst->opcode() != SpvOpLoopMerge) {
+  if (!merge_inst || merge_inst->opcode() != spv::Op::OpLoopMerge) {
     return false;
   }
 
   // We assert that the transformation does not try to set any meaningless bits
   // of the loop control mask.
-  uint32_t all_loop_control_mask_bits_set =
-      SpvLoopControlUnrollMask | SpvLoopControlDontUnrollMask |
-      SpvLoopControlDependencyInfiniteMask |
-      SpvLoopControlDependencyLengthMask | SpvLoopControlMinIterationsMask |
-      SpvLoopControlMaxIterationsMask | SpvLoopControlIterationMultipleMask |
-      SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask;
+  uint32_t all_loop_control_mask_bits_set = uint32_t(
+      spv::LoopControlMask::Unroll | spv::LoopControlMask::DontUnroll |
+      spv::LoopControlMask::DependencyInfinite |
+      spv::LoopControlMask::DependencyLength |
+      spv::LoopControlMask::MinIterations |
+      spv::LoopControlMask::MaxIterations |
+      spv::LoopControlMask::IterationMultiple |
+      spv::LoopControlMask::PeelCount | spv::LoopControlMask::PartialCount);
 
   // The variable is only used in an assertion; the following keeps release-mode
   // compilers happy.
@@ -65,10 +67,11 @@
 
   // Check that there is no attempt to set one of the loop controls that
   // requires guarantees to hold.
-  for (SpvLoopControlMask mask :
-       {SpvLoopControlDependencyInfiniteMask,
-        SpvLoopControlDependencyLengthMask, SpvLoopControlMinIterationsMask,
-        SpvLoopControlMaxIterationsMask, SpvLoopControlIterationMultipleMask}) {
+  for (spv::LoopControlMask mask : {spv::LoopControlMask::DependencyInfinite,
+                                    spv::LoopControlMask::DependencyLength,
+                                    spv::LoopControlMask::MinIterations,
+                                    spv::LoopControlMask::MaxIterations,
+                                    spv::LoopControlMask::IterationMultiple}) {
     // We have a problem if this loop control bit was not set in the original
     // loop control mask but is set by the transformation.
     if (LoopControlBitIsAddedByTransformation(mask,
@@ -78,33 +81,36 @@
   }
 
   // Check that PeelCount and PartialCount are supported if used.
-  if ((message_.loop_control() & SpvLoopControlPeelCountMask) &&
+  if ((message_.loop_control() & uint32_t(spv::LoopControlMask::PeelCount)) &&
       !PeelCountIsSupported(ir_context)) {
     return false;
   }
 
-  if ((message_.loop_control() & SpvLoopControlPartialCountMask) &&
+  if ((message_.loop_control() &
+       uint32_t(spv::LoopControlMask::PartialCount)) &&
       !PartialCountIsSupported(ir_context)) {
     return false;
   }
 
   if (message_.peel_count() > 0 &&
-      !(message_.loop_control() & SpvLoopControlPeelCountMask)) {
+      !(message_.loop_control() & uint32_t(spv::LoopControlMask::PeelCount))) {
     // Peel count provided, but peel count mask bit not set.
     return false;
   }
 
   if (message_.partial_count() > 0 &&
-      !(message_.loop_control() & SpvLoopControlPartialCountMask)) {
+      !(message_.loop_control() &
+        uint32_t(spv::LoopControlMask::PartialCount))) {
     // Partial count provided, but partial count mask bit not set.
     return false;
   }
 
   // We must not set both 'don't unroll' and one of 'peel count' or 'partial
   // count'.
-  return !((message_.loop_control() & SpvLoopControlDontUnrollMask) &&
-           (message_.loop_control() &
-            (SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask)));
+  return !(
+      (message_.loop_control() & uint32_t(spv::LoopControlMask::DontUnroll)) &&
+      (message_.loop_control() & uint32_t(spv::LoopControlMask::PeelCount |
+                                          spv::LoopControlMask::PartialCount)));
 }
 
 void TransformationSetLoopControl::Apply(
@@ -133,13 +139,14 @@
 
   uint32_t literal_index = 0;  // Indexes into the literals from the original
   // instruction.
-  for (SpvLoopControlMask mask :
-       {SpvLoopControlDependencyLengthMask, SpvLoopControlMinIterationsMask,
-        SpvLoopControlMaxIterationsMask, SpvLoopControlIterationMultipleMask}) {
+  for (spv::LoopControlMask mask : {spv::LoopControlMask::DependencyLength,
+                                    spv::LoopControlMask::MinIterations,
+                                    spv::LoopControlMask::MaxIterations,
+                                    spv::LoopControlMask::IterationMultiple}) {
     // Check whether the bit was set in the original loop control mask.
-    if (existing_loop_control_mask & mask) {
+    if (existing_loop_control_mask & uint32_t(mask)) {
       // Check whether the bit is set in the new loop control mask.
-      if (message_.loop_control() & mask) {
+      if (message_.loop_control() & uint32_t(mask)) {
         // Add the associated literal to our sequence of replacement operands.
         new_operands.push_back(
             {SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -154,13 +161,13 @@
 
   // If PeelCount is set in the new mask, |message_.peel_count| provides the
   // associated peel count.
-  if (message_.loop_control() & SpvLoopControlPeelCountMask) {
+  if (message_.loop_control() & uint32_t(spv::LoopControlMask::PeelCount)) {
     new_operands.push_back(
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.peel_count()}});
   }
 
   // Similar, but for PartialCount.
-  if (message_.loop_control() & SpvLoopControlPartialCountMask) {
+  if (message_.loop_control() & uint32_t(spv::LoopControlMask::PartialCount)) {
     new_operands.push_back(
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.partial_count()}});
   }
@@ -177,10 +184,11 @@
 }
 
 bool TransformationSetLoopControl::LoopControlBitIsAddedByTransformation(
-    SpvLoopControlMask loop_control_single_bit_mask,
+    spv::LoopControlMask loop_control_single_bit_mask,
     uint32_t existing_loop_control_mask) const {
-  return !(loop_control_single_bit_mask & existing_loop_control_mask) &&
-         (loop_control_single_bit_mask & message_.loop_control());
+  return !(uint32_t(loop_control_single_bit_mask) &
+           existing_loop_control_mask) &&
+         (uint32_t(loop_control_single_bit_mask) & message_.loop_control());
 }
 
 bool TransformationSetLoopControl::PartialCountIsSupported(
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_set_loop_control.h b/third_party/SPIRV-Tools/source/fuzz/transformation_set_loop_control.h
index bc17c8a..d57447b 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_set_loop_control.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_set_loop_control.h
@@ -71,7 +71,7 @@
   // Returns true if and only if |loop_single_bit_mask| is *not* set in
   // |existing_loop_control| but *is* set in |message_.loop_control|.
   bool LoopControlBitIsAddedByTransformation(
-      SpvLoopControlMask loop_control_single_bit_mask,
+      spv::LoopControlMask loop_control_single_bit_mask,
       uint32_t existing_loop_control_mask) const;
 
   protobufs::TransformationSetLoopControl message_;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_set_memory_operands_mask.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_set_memory_operands_mask.cpp
index 5a986ad..16d591a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_set_memory_operands_mask.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_set_memory_operands_mask.cpp
@@ -48,10 +48,13 @@
     // which they were applied during fuzzing, hence why these are assertions
     // rather than applicability checks.
     assert(message_.memory_operands_mask_index() == 1);
-    assert(message_.memory_access_instruction().target_instruction_opcode() ==
-               SpvOpCopyMemory ||
-           message_.memory_access_instruction().target_instruction_opcode() ==
-               SpvOpCopyMemorySized);
+    assert(
+        spv::Op(
+            message_.memory_access_instruction().target_instruction_opcode()) ==
+            spv::Op::OpCopyMemory ||
+        spv::Op(
+            message_.memory_access_instruction().target_instruction_opcode()) ==
+            spv::Op::OpCopyMemorySized);
     assert(MultipleMemoryOperandMasksAreSupported(ir_context) &&
            "Multiple memory operand masks are not supported for this SPIR-V "
            "version.");
@@ -73,12 +76,12 @@
   uint32_t original_mask =
       original_mask_in_operand_index < instruction->NumInOperands()
           ? instruction->GetSingleWordInOperand(original_mask_in_operand_index)
-          : static_cast<uint32_t>(SpvMemoryAccessMaskNone);
+          : static_cast<uint32_t>(spv::MemoryAccessMask::MaskNone);
   uint32_t new_mask = message_.memory_operands_mask();
 
   // Volatile must not be removed
-  if ((original_mask & SpvMemoryAccessVolatileMask) &&
-      !(new_mask & SpvMemoryAccessVolatileMask)) {
+  if ((original_mask & uint32_t(spv::MemoryAccessMask::Volatile)) &&
+      !(new_mask & uint32_t(spv::MemoryAccessMask::Volatile))) {
     return false;
   }
 
@@ -87,10 +90,10 @@
   // their Volatile and Nontemporal flags to the same value (this works
   // because valid manipulation of Volatile is checked above, and the manner
   // in which Nontemporal is manipulated does not matter).
-  return (original_mask | SpvMemoryAccessVolatileMask |
-          SpvMemoryAccessNontemporalMask) ==
-         (new_mask | SpvMemoryAccessVolatileMask |
-          SpvMemoryAccessNontemporalMask);
+  return (original_mask | uint32_t(spv::MemoryAccessMask::Volatile) |
+          uint32_t(spv::MemoryAccessMask::Nontemporal)) ==
+         (new_mask | uint32_t(spv::MemoryAccessMask::Volatile) |
+          uint32_t(spv::MemoryAccessMask::Nontemporal));
 }
 
 void TransformationSetMemoryOperandsMask::Apply(
@@ -106,8 +109,8 @@
     if (message_.memory_operands_mask_index() == 1 &&
         GetInOperandIndexForMask(*instruction, 0) >=
             instruction->NumInOperands()) {
-      instruction->AddOperand(
-          {SPV_OPERAND_TYPE_MEMORY_ACCESS, {SpvMemoryAccessMaskNone}});
+      instruction->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS,
+                               {uint32_t(spv::MemoryAccessMask::MaskNone)}});
     }
 
     instruction->AddOperand(
@@ -129,10 +132,10 @@
 bool TransformationSetMemoryOperandsMask::IsMemoryAccess(
     const opt::Instruction& instruction) {
   switch (instruction.opcode()) {
-    case SpvOpLoad:
-    case SpvOpStore:
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       return true;
     default:
       return false;
@@ -145,16 +148,16 @@
   // for the instruction.
   uint32_t first_mask_in_operand_index = 0;
   switch (instruction.opcode()) {
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       first_mask_in_operand_index = kOpLoadMemoryOperandsMaskIndex;
       break;
-    case SpvOpStore:
+    case spv::Op::OpStore:
       first_mask_in_operand_index = kOpStoreMemoryOperandsMaskIndex;
       break;
-    case SpvOpCopyMemory:
+    case spv::Op::OpCopyMemory:
       first_mask_in_operand_index = kOpCopyMemoryFirstMemoryOperandsMaskIndex;
       break;
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemorySized:
       first_mask_in_operand_index =
           kOpCopyMemorySizedFirstMemoryOperandsMaskIndex;
       break;
@@ -192,12 +195,12 @@
   // Consider each bit that might have an associated extra input operand, and
   // count how many there are expected to be.
   uint32_t first_mask_extra_operand_count = 0;
-  for (auto mask_bit :
-       {SpvMemoryAccessAlignedMask, SpvMemoryAccessMakePointerAvailableMask,
-        SpvMemoryAccessMakePointerAvailableKHRMask,
-        SpvMemoryAccessMakePointerVisibleMask,
-        SpvMemoryAccessMakePointerVisibleKHRMask}) {
-    if (first_mask & mask_bit) {
+  for (auto mask_bit : {spv::MemoryAccessMask::Aligned,
+                        spv::MemoryAccessMask::MakePointerAvailable,
+                        spv::MemoryAccessMask::MakePointerAvailableKHR,
+                        spv::MemoryAccessMask::MakePointerVisible,
+                        spv::MemoryAccessMask::MakePointerVisibleKHR}) {
+    if (first_mask & uint32_t(mask_bit)) {
       first_mask_extra_operand_count++;
     }
   }
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_set_selection_control.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_set_selection_control.cpp
index 6dddbdf..c6f68d9 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_set_selection_control.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_set_selection_control.cpp
@@ -29,14 +29,17 @@
 
 bool TransformationSetSelectionControl::IsApplicable(
     opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
-  assert((message_.selection_control() == SpvSelectionControlMaskNone ||
-          message_.selection_control() == SpvSelectionControlFlattenMask ||
-          message_.selection_control() == SpvSelectionControlDontFlattenMask) &&
+  assert((spv::SelectionControlMask(message_.selection_control()) ==
+              spv::SelectionControlMask::MaskNone ||
+          spv::SelectionControlMask(message_.selection_control()) ==
+              spv::SelectionControlMask::Flatten ||
+          spv::SelectionControlMask(message_.selection_control()) ==
+              spv::SelectionControlMask::DontFlatten) &&
          "Selection control should never be set to something other than "
          "'None', 'Flatten' or 'DontFlatten'");
   if (auto block = ir_context->get_instr_block(message_.block_id())) {
     if (auto merge_inst = block->GetMergeInst()) {
-      return merge_inst->opcode() == SpvOpSelectionMerge;
+      return merge_inst->opcode() == spv::Op::OpSelectionMerge;
     }
   }
   // Either the block did not exit, or did not end with OpSelectionMerge.
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_split_block.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_split_block.cpp
index e15dffa..959bedc 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_split_block.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_split_block.cpp
@@ -64,19 +64,19 @@
          " block split point exists.");
 
   if (split_before->PreviousNode() &&
-      split_before->PreviousNode()->opcode() == SpvOpSelectionMerge) {
+      split_before->PreviousNode()->opcode() == spv::Op::OpSelectionMerge) {
     // We cannot split directly after a selection merge: this would separate
     // the merge from its associated branch or switch operation.
     return false;
   }
-  if (split_before->opcode() == SpvOpVariable) {
+  if (split_before->opcode() == spv::Op::OpVariable) {
     // We cannot split directly after a variable; variables in a function
     // must be contiguous in the entry block.
     return false;
   }
   // We cannot split before an OpPhi unless the OpPhi has exactly one
   // associated incoming edge.
-  if (split_before->opcode() == SpvOpPhi &&
+  if (split_before->opcode() == spv::Op::OpPhi &&
       split_before->NumInOperands() != 2) {
     return false;
   }
@@ -110,7 +110,7 @@
   // The split does not automatically add a branch between the two parts of
   // the original block, so we add one.
   auto branch_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       std::initializer_list<opt::Operand>{opt::Operand(
           spv_operand_type_t::SPV_OPERAND_TYPE_ID, {message_.fresh_id()})});
   auto branch_instruction_ptr = branch_instruction.get();
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_store.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_store.cpp
index c00cd34..6ba1c55 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_store.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_store.cpp
@@ -48,7 +48,7 @@
   // The pointer type must indeed be a pointer.
   auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
   assert(pointer_type && "Type id must be defined.");
-  if (pointer_type->opcode() != SpvOpTypePointer) {
+  if (pointer_type->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
@@ -59,8 +59,8 @@
 
   // We do not want to allow storing to null or undefined pointers.
   switch (pointer->opcode()) {
-    case SpvOpConstantNull:
-    case SpvOpUndef:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpUndef:
       return false;
     default:
       break;
@@ -75,11 +75,11 @@
   }
   // ... and it must be legitimate to insert a store before it.
   if (!message_.is_atomic() && !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                                   SpvOpStore, insert_before)) {
+                                   spv::Op::OpStore, insert_before)) {
     return false;
   }
   if (message_.is_atomic() && !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                                  SpvOpAtomicStore, insert_before)) {
+                                  spv::Op::OpAtomicStore, insert_before)) {
     return false;
   }
 
@@ -125,10 +125,10 @@
     }
     // The memory scope and memory semantics instructions must have the
     // 'OpConstant' opcode.
-    if (memory_scope_instruction->opcode() != SpvOpConstant) {
+    if (memory_scope_instruction->opcode() != spv::Op::OpConstant) {
       return false;
     }
-    if (memory_semantics_instruction->opcode() != SpvOpConstant) {
+    if (memory_semantics_instruction->opcode() != spv::Op::OpConstant) {
       return false;
     }
     // The memory scope and memory semantics need to be available before
@@ -145,12 +145,12 @@
     // operand type with signedness does not matters.
     if (ir_context->get_def_use_mgr()
             ->GetDef(memory_scope_instruction->type_id())
-            ->opcode() != SpvOpTypeInt) {
+            ->opcode() != spv::Op::OpTypeInt) {
       return false;
     }
     if (ir_context->get_def_use_mgr()
             ->GetDef(memory_semantics_instruction->type_id())
-            ->opcode() != SpvOpTypeInt) {
+            ->opcode() != spv::Op::OpTypeInt) {
       return false;
     }
 
@@ -172,20 +172,20 @@
       return false;
     }
 
-    // The memory scope constant value must be that of SpvScopeInvocation.
+    // The memory scope constant value must be that of spv::Scope::Invocation.
     auto memory_scope_const_value =
         memory_scope_instruction->GetSingleWordInOperand(0);
-    if (memory_scope_const_value != SpvScopeInvocation) {
+    if (spv::Scope(memory_scope_const_value) != spv::Scope::Invocation) {
       return false;
     }
 
     // The memory semantics constant value must match the storage class of the
     // pointer being loaded from.
-    auto memory_semantics_const_value = static_cast<SpvMemorySemanticsMask>(
+    auto memory_semantics_const_value = static_cast<spv::MemorySemanticsMask>(
         memory_semantics_instruction->GetSingleWordInOperand(0));
     if (memory_semantics_const_value !=
         fuzzerutil::GetMemorySemanticsForStorageClass(
-            static_cast<SpvStorageClass>(
+            static_cast<spv::StorageClass>(
                 pointer_type->GetSingleWordInOperand(0)))) {
       return false;
     }
@@ -203,7 +203,7 @@
     auto insert_before =
         FindInstruction(message_.instruction_to_insert_before(), ir_context);
     auto new_instruction = MakeUnique<opt::Instruction>(
-        ir_context, SpvOpAtomicStore, 0, 0,
+        ir_context, spv::Op::OpAtomicStore, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
              {SPV_OPERAND_TYPE_SCOPE_ID, {message_.memory_scope_id()}},
@@ -223,7 +223,7 @@
     auto insert_before =
         FindInstruction(message_.instruction_to_insert_before(), ir_context);
     auto new_instruction = MakeUnique<opt::Instruction>(
-        ir_context, SpvOpStore, 0, 0,
+        ir_context, spv::Op::OpStore, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
              {SPV_OPERAND_TYPE_ID, {message_.value_id()}}}));
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_store.h b/third_party/SPIRV-Tools/source/fuzz/transformation_store.h
index 638713b..5b55ce6 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_store.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_store.h
@@ -38,7 +38,7 @@
   // - |message_.is_atomic| must be true if want to work with OpAtomicStore.
   // - If |is_atomic| is true then |message_memory_scope_id| must be the id of
   //   an OpConstant 32 bit integer instruction with the value
-  //   SpvScopeInvocation.
+  //   spv::Scope::Invocation.
   // - If |is_atomic| is true then |message_.memory_semantics_id| must be the id
   //   of an OpConstant 32 bit integer instruction with the values
   //   SpvMemorySemanticsWorkgroupMemoryMask or
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_swap_commutable_operands.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_swap_commutable_operands.cpp
index a02e95a..1512144 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_swap_commutable_operands.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_swap_commutable_operands.cpp
@@ -35,9 +35,9 @@
       FindInstruction(message_.instruction_descriptor(), ir_context);
   if (instruction == nullptr) return false;
 
-  SpvOp opcode = static_cast<SpvOp>(
+  spv::Op opcode = static_cast<spv::Op>(
       message_.instruction_descriptor().target_instruction_opcode());
-  assert(instruction->opcode() == opcode &&
+  assert(spv::Op(instruction->opcode()) == opcode &&
          "The located instruction must have the same opcode as in the "
          "descriptor.");
   return spvOpcodeIsCommutativeBinaryOperator(opcode);
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_swap_conditional_branch_operands.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_swap_conditional_branch_operands.cpp
index 340836d..520a6a8 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_swap_conditional_branch_operands.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_swap_conditional_branch_operands.cpp
@@ -38,7 +38,7 @@
   const auto* inst =
       FindInstruction(message_.instruction_descriptor(), ir_context);
   return fuzzerutil::IsFreshId(ir_context, message_.fresh_id()) && inst &&
-         inst->opcode() == SpvOpBranchConditional;
+         inst->opcode() == spv::Op::OpBranchConditional;
 }
 
 void TransformationSwapConditionalBranchOperands::Apply(
@@ -53,13 +53,15 @@
   // Compute the last instruction in the |block| that allows us to insert
   // OpLogicalNot above it.
   auto iter = fuzzerutil::GetIteratorForInstruction(block, branch_inst);
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLogicalNot, iter)) {
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLogicalNot,
+                                                    iter)) {
     // There might be a merge instruction before OpBranchConditional.
     --iter;
   }
 
-  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLogicalNot, iter) &&
-         "We should now be able to insert SpvOpLogicalNot before |iter|");
+  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLogicalNot,
+                                                      iter) &&
+         "We should now be able to insert spv::Op::OpLogicalNot before |iter|");
 
   // Get the instruction whose result is used as a condition for
   // OpBranchConditional.
@@ -70,7 +72,7 @@
   // We are swapping the labels in OpBranchConditional. This means that we must
   // invert the guard as well. We are using OpLogicalNot for that purpose here.
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLogicalNot, condition_inst->type_id(),
+      ir_context, spv::Op::OpLogicalNot, condition_inst->type_id(),
       message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {condition_inst->result_id()}}});
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_swap_function_variables.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_swap_function_variables.cpp
index aec32fe..14ba7bb 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_swap_function_variables.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_swap_function_variables.cpp
@@ -43,8 +43,8 @@
     return false;
   }
   // Both instructions must be variables.
-  if (instruction1->opcode() != SpvOpVariable ||
-      instruction2->opcode() != SpvOpVariable) {
+  if (instruction1->opcode() != spv::Op::OpVariable ||
+      instruction2->opcode() != spv::Op::OpVariable) {
     return false;
   }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_toggle_access_chain_instruction.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_toggle_access_chain_instruction.cpp
index 34523fe..ae6ab9a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_toggle_access_chain_instruction.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_toggle_access_chain_instruction.cpp
@@ -39,14 +39,15 @@
     return false;
   }
 
-  SpvOp opcode = static_cast<SpvOp>(
+  spv::Op opcode = static_cast<spv::Op>(
       message_.instruction_descriptor().target_instruction_opcode());
 
   assert(instruction->opcode() == opcode &&
          "The located instruction must have the same opcode as in the "
          "descriptor.");
 
-  if (opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain) {
+  if (opcode == spv::Op::OpAccessChain ||
+      opcode == spv::Op::OpInBoundsAccessChain) {
     return true;
   }
 
@@ -57,15 +58,15 @@
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   auto instruction =
       FindInstruction(message_.instruction_descriptor(), ir_context);
-  SpvOp opcode = instruction->opcode();
+  spv::Op opcode = instruction->opcode();
 
-  if (opcode == SpvOpAccessChain) {
-    instruction->SetOpcode(SpvOpInBoundsAccessChain);
+  if (opcode == spv::Op::OpAccessChain) {
+    instruction->SetOpcode(spv::Op::OpInBoundsAccessChain);
   } else {
-    assert(opcode == SpvOpInBoundsAccessChain &&
+    assert(opcode == spv::Op::OpInBoundsAccessChain &&
            "The located instruction must be an OpInBoundsAccessChain "
            "instruction.");
-    instruction->SetOpcode(SpvOpAccessChain);
+    instruction->SetOpcode(spv::Op::OpAccessChain);
   }
 }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_vector_shuffle.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_vector_shuffle.cpp
index 742a2c8..8ba557c 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_vector_shuffle.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_vector_shuffle.cpp
@@ -108,7 +108,7 @@
   // It must be legitimate to insert an OpVectorShuffle before the identified
   // instruction.
   return fuzzerutil::CanInsertOpcodeBeforeInstruction(
-      SpvOpVectorShuffle, instruction_to_insert_before);
+      spv::Op::OpVectorShuffle, instruction_to_insert_before);
 }
 
 void TransformationVectorShuffle::Apply(
@@ -134,8 +134,8 @@
       FindInstruction(message_.instruction_to_insert_before(), ir_context);
   opt::Instruction* new_instruction =
       insert_before->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpVectorShuffle, result_type_id, message_.fresh_id(),
-          shuffle_operands));
+          ir_context, spv::Op::OpVectorShuffle, result_type_id,
+          message_.fresh_id(), shuffle_operands));
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // Inform the def-use manager about the new instruction and record its basic
   // block.
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_early_terminator_in_function.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_early_terminator_in_function.cpp
index 468d809..f59d78a 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_early_terminator_in_function.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_early_terminator_in_function.cpp
@@ -52,9 +52,9 @@
     return false;
   }
   switch (early_terminator->opcode()) {
-    case SpvOpKill:
-    case SpvOpUnreachable:
-    case SpvOpTerminateInvocation:
+    case spv::Op::OpKill:
+    case spv::Op::OpUnreachable:
+    case spv::Op::OpTerminateInvocation:
       break;
     default:
       return false;
@@ -119,7 +119,7 @@
       MaybeGetWrapperFunction(ir_context, early_terminator->opcode());
 
   iterator->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionCall, wrapper_function->type_id(),
+      ir_context, spv::Op::OpFunctionCall, wrapper_function->type_id(),
       message_.fresh_id(),
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {wrapper_function->result_id()}}})));
@@ -130,9 +130,9 @@
            ->AsVoid()) {
     new_in_operands.push_back(
         {SPV_OPERAND_TYPE_ID, {message_.returned_value_id()}});
-    early_terminator->SetOpcode(SpvOpReturnValue);
+    early_terminator->SetOpcode(spv::Op::OpReturnValue);
   } else {
-    early_terminator->SetOpcode(SpvOpReturn);
+    early_terminator->SetOpcode(spv::Op::OpReturn);
   }
   early_terminator->SetInOperands(std::move(new_in_operands));
 
@@ -153,10 +153,10 @@
 
 opt::Function*
 TransformationWrapEarlyTerminatorInFunction::MaybeGetWrapperFunction(
-    opt::IRContext* ir_context, SpvOp early_terminator_opcode) {
-  assert((early_terminator_opcode == SpvOpKill ||
-          early_terminator_opcode == SpvOpUnreachable ||
-          early_terminator_opcode == SpvOpTerminateInvocation) &&
+    opt::IRContext* ir_context, spv::Op early_terminator_opcode) {
+  assert((early_terminator_opcode == spv::Op::OpKill ||
+          early_terminator_opcode == spv::Op::OpUnreachable ||
+          early_terminator_opcode == spv::Op::OpTerminateInvocation) &&
          "Invalid opcode.");
   auto void_type_id = fuzzerutil::MaybeGetVoidType(ir_context);
   if (!void_type_id) {
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_early_terminator_in_function.h b/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_early_terminator_in_function.h
index d6e5551..d824783 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_early_terminator_in_function.h
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_early_terminator_in_function.h
@@ -60,8 +60,8 @@
 
   protobufs::Transformation ToMessage() const override;
 
-  static opt::Function* MaybeGetWrapperFunction(opt::IRContext* ir_context,
-                                                SpvOp early_terminator_opcode);
+  static opt::Function* MaybeGetWrapperFunction(
+      opt::IRContext* ir_context, spv::Op early_terminator_opcode);
 
  private:
   protobufs::TransformationWrapEarlyTerminatorInFunction message_;
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_region_in_selection.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_region_in_selection.cpp
index 01c98cc..a63d1ac 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_region_in_selection.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_region_in_selection.cpp
@@ -53,14 +53,14 @@
     TransformationContext* transformation_context) const {
   auto* new_header_block =
       ir_context->cfg()->block(message_.region_entry_block_id());
-  assert(new_header_block->terminator()->opcode() == SpvOpBranch &&
+  assert(new_header_block->terminator()->opcode() == spv::Op::OpBranch &&
          "This condition should have been checked in the IsApplicable");
 
   const auto successor_id =
       new_header_block->terminator()->GetSingleWordInOperand(0);
 
   // Change |entry_block|'s terminator to |OpBranchConditional|.
-  new_header_block->terminator()->SetOpcode(SpvOpBranchConditional);
+  new_header_block->terminator()->SetOpcode(spv::Op::OpBranchConditional);
   new_header_block->terminator()->SetInOperands(
       {{SPV_OPERAND_TYPE_ID,
         {fuzzerutil::MaybeGetBoolConstant(ir_context, *transformation_context,
@@ -70,11 +70,11 @@
 
   // Insert OpSelectionMerge before the terminator.
   new_header_block->terminator()->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.region_exit_block_id()}},
           {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-           {SpvSelectionControlMaskNone}}}));
+           {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
 
   // We've change the module so we must invalidate analyses.
   ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
@@ -130,7 +130,7 @@
   }
 
   // |header_block_candidate| must have an OpBranch terminator.
-  if (header_block_candidate->terminator()->opcode() != SpvOpBranch) {
+  if (header_block_candidate->terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
diff --git a/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_vector_synonym.cpp b/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_vector_synonym.cpp
index 490bcd7..3b1543d 100644
--- a/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_vector_synonym.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/transformation_wrap_vector_synonym.cpp
@@ -83,7 +83,7 @@
   }
 
   auto vec1_type = ir_context->get_def_use_mgr()->GetDef(vec1_type_id);
-  if (vec1_type->opcode() != SpvOpTypeVector) {
+  if (vec1_type->opcode() != spv::Op::OpTypeVector) {
     return false;
   }
 
@@ -178,18 +178,18 @@
   auto type_instruction =
       ir_context->get_def_use_mgr()->GetDef(instruction.type_id());
 
-  if ((type_instruction->opcode() != SpvOpTypeInt &&
-       type_instruction->opcode() != SpvOpTypeFloat)) {
+  if ((type_instruction->opcode() != spv::Op::OpTypeInt &&
+       type_instruction->opcode() != spv::Op::OpTypeFloat)) {
     return false;
   }
 
   switch (instruction.opcode()) {
-    case SpvOpIAdd:
-    case SpvOpISub:
-    case SpvOpIMul:
-    case SpvOpFAdd:
-    case SpvOpFSub:
-    case SpvOpFMul:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpFSub:
+    case spv::Op::OpFMul:
       return true;
     default:
       return false;
diff --git a/third_party/SPIRV-Tools/source/fuzz/uniform_buffer_element_descriptor.cpp b/third_party/SPIRV-Tools/source/fuzz/uniform_buffer_element_descriptor.cpp
index 90fd85e..55e84de 100644
--- a/third_party/SPIRV-Tools/source/fuzz/uniform_buffer_element_descriptor.cpp
+++ b/third_party/SPIRV-Tools/source/fuzz/uniform_buffer_element_descriptor.cpp
@@ -49,10 +49,11 @@
 
   for (auto& inst : context->types_values()) {
     // Consider all global variables with uniform storage class.
-    if (inst.opcode() != SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       continue;
     }
-    if (inst.GetSingleWordInOperand(0) != SpvStorageClassUniform) {
+    if (spv::StorageClass(inst.GetSingleWordInOperand(0)) !=
+        spv::StorageClass::Uniform) {
       continue;
     }
 
@@ -60,7 +61,7 @@
     // matching that in |uniform_buffer_element|.
     bool descriptor_set_matches = false;
     context->get_decoration_mgr()->ForEachDecoration(
-        inst.result_id(), SpvDecorationDescriptorSet,
+        inst.result_id(), uint32_t(spv::Decoration::DescriptorSet),
         [&descriptor_set_matches, &uniform_buffer_element_descriptor](
             const opt::Instruction& decoration_inst) {
           const uint32_t kDescriptorSetOperandIndex = 2;
@@ -79,7 +80,7 @@
     // in |uniform_buffer_element|.
     bool binding_matches = false;
     context->get_decoration_mgr()->ForEachDecoration(
-        inst.result_id(), SpvDecorationBinding,
+        inst.result_id(), uint32_t(spv::Decoration::Binding),
         [&binding_matches, &uniform_buffer_element_descriptor](
             const opt::Instruction& decoration_inst) {
           const uint32_t kBindingOperandIndex = 2;
diff --git a/third_party/SPIRV-Tools/source/instruction.h b/third_party/SPIRV-Tools/source/instruction.h
index 9e7dccd..2acbb57 100644
--- a/third_party/SPIRV-Tools/source/instruction.h
+++ b/third_party/SPIRV-Tools/source/instruction.h
@@ -26,7 +26,7 @@
   // Normally, both opcode and extInstType contain valid data.
   // However, when the assembler parses !<number> as the first word in
   // an instruction and opcode and extInstType are invalid.
-  SpvOp opcode;
+  spv::Op opcode;
   spv_ext_inst_type_t extInstType;
 
   // The Id of the result type, if this instruction has one.  Zero otherwise.
diff --git a/third_party/SPIRV-Tools/source/latest_version_spirv_header.h b/third_party/SPIRV-Tools/source/latest_version_spirv_header.h
index e4f28e4..f6ab5c8 100644
--- a/third_party/SPIRV-Tools/source/latest_version_spirv_header.h
+++ b/third_party/SPIRV-Tools/source/latest_version_spirv_header.h
@@ -15,6 +15,6 @@
 #ifndef SOURCE_LATEST_VERSION_SPIRV_HEADER_H_
 #define SOURCE_LATEST_VERSION_SPIRV_HEADER_H_
 
-#include "spirv/unified1/spirv.h"
+#include "spirv/unified1/spirv.hpp11"
 
 #endif  // SOURCE_LATEST_VERSION_SPIRV_HEADER_H_
diff --git a/third_party/SPIRV-Tools/source/link/linker.cpp b/third_party/SPIRV-Tools/source/link/linker.cpp
index 3b388cc..e50391a 100644
--- a/third_party/SPIRV-Tools/source/link/linker.cpp
+++ b/third_party/SPIRV-Tools/source/link/linker.cpp
@@ -57,12 +57,12 @@
 
 // Stores various information about an imported or exported symbol.
 struct LinkageSymbolInfo {
-  SpvId id;          // ID of the symbol
-  SpvId type_id;     // ID of the type of the symbol
+  spv::Id id;        // ID of the symbol
+  spv::Id type_id;   // ID of the type of the symbol
   std::string name;  // unique name defining the symbol and used for matching
                      // imports and exports together
-  std::vector<SpvId> parameter_ids;  // ID of the parameters of the symbol, if
-                                     // it is a function
+  std::vector<spv::Id> parameter_ids;  // ID of the parameters of the symbol, if
+                                       // it is a function
 };
 struct LinkageEntry {
   LinkageSymbolInfo imported_symbol;
@@ -226,7 +226,7 @@
              << " (input module " << (i + 1) << ").";
   }
 
-  header->magic_number = SpvMagicNumber;
+  header->magic_number = spv::MagicNumber;
   header->version = linked_version;
   header->generator = SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_LINKER, 0);
   header->bound = max_id_bound;
@@ -367,7 +367,7 @@
     std::vector<uint32_t> processed_words =
         spvtools::utils::MakeVector(processed_string);
     linked_module->AddDebug3Inst(std::unique_ptr<Instruction>(
-        new Instruction(linked_context, SpvOpModuleProcessed, 0u, 0u,
+        new Instruction(linked_context, spv::Op::OpModuleProcessed, 0u, 0u,
                         {{SPV_OPERAND_TYPE_LITERAL_STRING, processed_words}})));
   }
 
@@ -377,7 +377,7 @@
           std::unique_ptr<Instruction>(inst.Clone(linked_context)));
 
   // TODO(pierremoreau): Since the modules have not been validate, should we
-  //                     expect SpvStorageClassFunction variables outside
+  //                     expect spv::StorageClass::Function variables outside
   //                     functions?
   for (const auto& module : input_modules) {
     for (const auto& inst : module->types_values()) {
@@ -414,16 +414,18 @@
 
   // Figure out the imports and exports
   for (const auto& decoration : linked_context.annotations()) {
-    if (decoration.opcode() != SpvOpDecorate ||
-        decoration.GetSingleWordInOperand(1u) != SpvDecorationLinkageAttributes)
+    if (decoration.opcode() != spv::Op::OpDecorate ||
+        spv::Decoration(decoration.GetSingleWordInOperand(1u)) !=
+            spv::Decoration::LinkageAttributes)
       continue;
 
-    const SpvId id = decoration.GetSingleWordInOperand(0u);
+    const spv::Id id = decoration.GetSingleWordInOperand(0u);
     // Ignore if the targeted symbol is a built-in
     bool is_built_in = false;
     for (const auto& id_decoration :
          decoration_manager.GetDecorationsFor(id, false)) {
-      if (id_decoration->GetSingleWordInOperand(1u) == SpvDecorationBuiltIn) {
+      if (spv::Decoration(id_decoration->GetSingleWordInOperand(1u)) ==
+          spv::Decoration::BuiltIn) {
         is_built_in = true;
         break;
       }
@@ -447,9 +449,9 @@
       return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
              << "ID " << id << " is never defined:\n";
 
-    if (def_inst->opcode() == SpvOpVariable) {
+    if (def_inst->opcode() == spv::Op::OpVariable) {
       symbol_info.type_id = def_inst->type_id();
-    } else if (def_inst->opcode() == SpvOpFunction) {
+    } else if (def_inst->opcode() == spv::Op::OpFunction) {
       symbol_info.type_id = def_inst->GetSingleWordInOperand(1u);
 
       // range-based for loop calls begin()/end(), but never cbegin()/cend(),
@@ -467,9 +469,9 @@
              << " LinkageAttributes; " << id << " is neither of them.\n";
     }
 
-    if (type == SpvLinkageTypeImport)
+    if (spv::LinkageType(type) == spv::LinkageType::Import)
       imports.push_back(symbol_info);
-    else if (type == SpvLinkageTypeExport)
+    else if (spv::LinkageType(type) == spv::LinkageType::Export)
       exports[symbol_info.name].push_back(symbol_info);
   }
 
@@ -585,7 +587,7 @@
   // TODO(pierremoreau): This will not work if the decoration is applied
   //                     through a group, but the linker does not support that
   //                     either.
-  std::unordered_set<SpvId> imports;
+  std::unordered_set<spv::Id> imports;
   if (options.GetAllowPartialLinkage()) {
     imports.reserve(linkings_to_do.size());
     for (const auto& linking_entry : linkings_to_do)
@@ -601,9 +603,11 @@
     // * if we do not allow partial linkage, remove all import annotations;
     // * otherwise, remove the annotation only if there was a corresponding
     //   export.
-    if (inst->opcode() == SpvOpDecorate &&
-        inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
-        inst->GetSingleWordOperand(3u) == SpvLinkageTypeImport &&
+    if (inst->opcode() == spv::Op::OpDecorate &&
+        spv::Decoration(inst->GetSingleWordOperand(1u)) ==
+            spv::Decoration::LinkageAttributes &&
+        spv::LinkageType(inst->GetSingleWordOperand(3u)) ==
+            spv::LinkageType::Import &&
         (!options.GetAllowPartialLinkage() ||
          imports.find(inst->GetSingleWordOperand(0u)) != imports.end())) {
       linked_context->KillInst(&*inst);
@@ -616,9 +620,11 @@
     for (auto inst = next; inst != linked_context->annotation_end();
          inst = next) {
       ++next;
-      if (inst->opcode() == SpvOpDecorate &&
-          inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
-          inst->GetSingleWordOperand(3u) == SpvLinkageTypeExport) {
+      if (inst->opcode() == spv::Op::OpDecorate &&
+          spv::Decoration(inst->GetSingleWordOperand(1u)) ==
+              spv::Decoration::LinkageAttributes &&
+          spv::LinkageType(inst->GetSingleWordOperand(3u)) ==
+              spv::LinkageType::Export) {
         linked_context->KillInst(&*inst);
       }
     }
@@ -628,10 +634,11 @@
   // not allowed
   if (!options.GetCreateLibrary() && !options.GetAllowPartialLinkage()) {
     for (auto& inst : linked_context->capabilities())
-      if (inst.GetSingleWordInOperand(0u) == SpvCapabilityLinkage) {
+      if (spv::Capability(inst.GetSingleWordInOperand(0u)) ==
+          spv::Capability::Linkage) {
         linked_context->KillInst(&inst);
         // The RemoveDuplicatesPass did remove duplicated capabilities, so we
-        // now there aren’t more SpvCapabilityLinkage further down.
+        // now there aren’t more spv::Capability::Linkage further down.
         break;
       }
   }
@@ -671,7 +678,7 @@
 
   size_t num_global_values = 0u;
   for (const auto& inst : linked_context.module()->types_values()) {
-    num_global_values += inst.opcode() == SpvOpVariable;
+    num_global_values += inst.opcode() == spv::Op::OpVariable;
   }
   if (num_global_values >= SPV_LIMIT_GLOBAL_VARIABLES_MAX)
     DiagnosticStream(position, consumer, "", SPV_WARNING)
diff --git a/third_party/SPIRV-Tools/source/lint/divergence_analysis.cpp b/third_party/SPIRV-Tools/source/lint/divergence_analysis.cpp
index b5a72b4..fe32e1a 100644
--- a/third_party/SPIRV-Tools/source/lint/divergence_analysis.cpp
+++ b/third_party/SPIRV-Tools/source/lint/divergence_analysis.cpp
@@ -19,7 +19,6 @@
 #include "source/opt/dataflow.h"
 #include "source/opt/function.h"
 #include "source/opt/instruction.h"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 namespace lint {
@@ -32,7 +31,7 @@
   uint32_t block_id;
   if (inst->IsBlockTerminator()) {
     block_id = context().get_instr_block(inst)->id();
-  } else if (inst->opcode() == SpvOpLabel) {
+  } else if (inst->opcode() == spv::Op::OpLabel) {
     block_id = inst->result_id();
     opt::BasicBlock* bb = context().cfg()->block(block_id);
     // Only enqueue phi instructions, as other uses don't affect divergence.
@@ -54,7 +53,7 @@
 
 opt::DataFlowAnalysis::VisitResult DivergenceAnalysis::Visit(
     opt::Instruction* inst) {
-  if (inst->opcode() == SpvOpLabel) {
+  if (inst->opcode() == spv::Op::OpLabel) {
     return VisitBlock(inst->result_id());
   } else {
     return VisitInstruction(inst);
@@ -128,12 +127,12 @@
   // Device/QueueFamily could satisfy fully uniform.
   uint32_t id = inst->result_id();
   // Handle divergence roots.
-  if (inst->opcode() == SpvOpFunctionParameter) {
+  if (inst->opcode() == spv::Op::OpFunctionParameter) {
     divergence_source_[id] = 0;
     return divergence_[id] = DivergenceLevel::kDivergent;
   } else if (inst->IsLoad()) {
     spvtools::opt::Instruction* var = inst->GetBaseAddress();
-    if (var->opcode() != SpvOpVariable) {
+    if (var->opcode() != spv::Op::OpVariable) {
       // Assume divergent.
       divergence_source_[id] = 0;
       return DivergenceLevel::kDivergent;
@@ -166,29 +165,30 @@
   uint32_t def_id = var->result_id();
   DivergenceLevel ret;
   switch (type->storage_class()) {
-    case SpvStorageClassFunction:
-    case SpvStorageClassGeneric:
-    case SpvStorageClassAtomicCounter:
-    case SpvStorageClassStorageBuffer:
-    case SpvStorageClassPhysicalStorageBuffer:
-    case SpvStorageClassOutput:
-    case SpvStorageClassWorkgroup:
-    case SpvStorageClassImage:  // Image atomics probably aren't uniform.
-    case SpvStorageClassPrivate:
+    case spv::StorageClass::Function:
+    case spv::StorageClass::Generic:
+    case spv::StorageClass::AtomicCounter:
+    case spv::StorageClass::StorageBuffer:
+    case spv::StorageClass::PhysicalStorageBuffer:
+    case spv::StorageClass::Output:
+    case spv::StorageClass::Workgroup:
+    case spv::StorageClass::Image:  // Image atomics probably aren't uniform.
+    case spv::StorageClass::Private:
       ret = DivergenceLevel::kDivergent;
       break;
-    case SpvStorageClassInput:
+    case spv::StorageClass::Input:
       ret = DivergenceLevel::kDivergent;
       // If this variable has a Flat decoration, it is partially uniform.
       // TODO(kuhar): Track access chain indices and also consider Flat members
       // of a structure.
       context().get_decoration_mgr()->WhileEachDecoration(
-          def_id, SpvDecorationFlat, [&ret](const opt::Instruction&) {
+          def_id, static_cast<uint32_t>(spv::Decoration::Flat),
+          [&ret](const opt::Instruction&) {
             ret = DivergenceLevel::kPartiallyUniform;
             return false;
           });
       break;
-    case SpvStorageClassUniformConstant:
+    case spv::StorageClass::UniformConstant:
       // May be a storage image which is also written to; mark those as
       // divergent.
       if (!var->IsVulkanStorageImage() || var->IsReadOnlyPointer()) {
@@ -197,9 +197,10 @@
         ret = DivergenceLevel::kDivergent;
       }
       break;
-    case SpvStorageClassUniform:
-    case SpvStorageClassPushConstant:
-    case SpvStorageClassCrossWorkgroup:  // Not for shaders; default uniform.
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::PushConstant:
+    case spv::StorageClass::CrossWorkgroup:  // Not for shaders; default
+                                             // uniform.
     default:
       ret = DivergenceLevel::kUniform;
       break;
@@ -216,7 +217,7 @@
       function->entry().get(), [this](const opt::BasicBlock* bb) {
         uint32_t id = bb->id();
         if (bb->terminator() == nullptr ||
-            bb->terminator()->opcode() != SpvOpBranch) {
+            bb->terminator()->opcode() != spv::Op::OpBranch) {
           follow_unconditional_branches_[id] = id;
         } else {
           uint32_t target_id = bb->terminator()->GetSingleWordInOperand(0);
diff --git a/third_party/SPIRV-Tools/source/lint/lint_divergent_derivatives.cpp b/third_party/SPIRV-Tools/source/lint/lint_divergent_derivatives.cpp
index 512847b..82d5ac6 100644
--- a/third_party/SPIRV-Tools/source/lint/lint_divergent_derivatives.cpp
+++ b/third_party/SPIRV-Tools/source/lint/lint_divergent_derivatives.cpp
@@ -27,7 +27,6 @@
 #include "source/opt/instruction.h"
 #include "source/opt/ir_context.h"
 #include "spirv-tools/libspirv.h"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 namespace lint {
@@ -43,7 +42,7 @@
     ss << id;
   } else {
     opt::Instruction* inst_name = names.begin()->second;
-    if (inst_name->opcode() == SpvOpName) {
+    if (inst_name->opcode() == spv::Op::OpName) {
       ss << names.begin()->second->GetInOperand(0).AsString();
       ss << "[" << id << "]";
     } else {
@@ -54,26 +53,26 @@
 }
 
 bool InstructionHasDerivative(const opt::Instruction& inst) {
-  static const SpvOp derivative_opcodes[] = {
+  static const spv::Op derivative_opcodes[] = {
       // Implicit derivatives.
-      SpvOpImageSampleImplicitLod,
-      SpvOpImageSampleDrefImplicitLod,
-      SpvOpImageSampleProjImplicitLod,
-      SpvOpImageSampleProjDrefImplicitLod,
-      SpvOpImageSparseSampleImplicitLod,
-      SpvOpImageSparseSampleDrefImplicitLod,
-      SpvOpImageSparseSampleProjImplicitLod,
-      SpvOpImageSparseSampleProjDrefImplicitLod,
+      spv::Op::OpImageSampleImplicitLod,
+      spv::Op::OpImageSampleDrefImplicitLod,
+      spv::Op::OpImageSampleProjImplicitLod,
+      spv::Op::OpImageSampleProjDrefImplicitLod,
+      spv::Op::OpImageSparseSampleImplicitLod,
+      spv::Op::OpImageSparseSampleDrefImplicitLod,
+      spv::Op::OpImageSparseSampleProjImplicitLod,
+      spv::Op::OpImageSparseSampleProjDrefImplicitLod,
       // Explicit derivatives.
-      SpvOpDPdx,
-      SpvOpDPdy,
-      SpvOpFwidth,
-      SpvOpDPdxFine,
-      SpvOpDPdyFine,
-      SpvOpFwidthFine,
-      SpvOpDPdxCoarse,
-      SpvOpDPdyCoarse,
-      SpvOpFwidthCoarse,
+      spv::Op::OpDPdx,
+      spv::Op::OpDPdy,
+      spv::Op::OpFwidth,
+      spv::Op::OpDPdxFine,
+      spv::Op::OpDPdyFine,
+      spv::Op::OpFwidthFine,
+      spv::Op::OpDPdxCoarse,
+      spv::Op::OpDPdyCoarse,
+      spv::Op::OpFwidthCoarse,
   };
   return std::find(std::begin(derivative_opcodes), std::end(derivative_opcodes),
                    inst.opcode()) != std::end(derivative_opcodes);
@@ -97,13 +96,14 @@
   opt::analysis::DefUseManager* def_use = context->get_def_use_mgr();
   opt::CFG* cfg = context->cfg();
   while (id != 0) {
-    bool is_block = def_use->GetDef(id)->opcode() == SpvOpLabel;
+    bool is_block = def_use->GetDef(id)->opcode() == spv::Op::OpLabel;
     if (is_block) {
       Warn(context, nullptr)
           << "block " << GetFriendlyName(context, id) << " is divergent";
       uint32_t source = div.GetDivergenceSource(id);
       // Skip intermediate blocks.
-      while (source != 0 && def_use->GetDef(source)->opcode() == SpvOpLabel) {
+      while (source != 0 &&
+             def_use->GetDef(source)->opcode() == spv::Op::OpLabel) {
         id = source;
         source = div.GetDivergenceSource(id);
       }
@@ -122,7 +122,7 @@
       opt::Instruction* source_def =
           source == 0 ? nullptr : def_use->GetDef(source);
       // First print data -> data dependencies.
-      while (source != 0 && source_def->opcode() != SpvOpLabel) {
+      while (source != 0 && source_def->opcode() != spv::Op::OpLabel) {
         Warn(context, def_use->GetDef(id))
             << "because " << GetFriendlyName(context, id) << " uses value "
             << GetFriendlyName(context, source)
diff --git a/third_party/SPIRV-Tools/source/lint/linter.cpp b/third_party/SPIRV-Tools/source/lint/linter.cpp
index e4ed04e..7480676 100644
--- a/third_party/SPIRV-Tools/source/lint/linter.cpp
+++ b/third_party/SPIRV-Tools/source/lint/linter.cpp
@@ -19,7 +19,6 @@
 #include "source/opt/ir_context.h"
 #include "spirv-tools/libspirv.h"
 #include "spirv-tools/libspirv.hpp"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 
diff --git a/third_party/SPIRV-Tools/source/name_mapper.cpp b/third_party/SPIRV-Tools/source/name_mapper.cpp
index 3b31d33..b2d0f44 100644
--- a/third_party/SPIRV-Tools/source/name_mapper.cpp
+++ b/third_party/SPIRV-Tools/source/name_mapper.cpp
@@ -100,18 +100,18 @@
 void FriendlyNameMapper::SaveBuiltInName(uint32_t target_id,
                                          uint32_t built_in) {
 #define GLCASE(name)                  \
-  case SpvBuiltIn##name:              \
+  case spv::BuiltIn::name:            \
     SaveName(target_id, "gl_" #name); \
     return;
 #define GLCASE2(name, suggested)           \
-  case SpvBuiltIn##name:                   \
+  case spv::BuiltIn::name:                 \
     SaveName(target_id, "gl_" #suggested); \
     return;
 #define CASE(name)              \
-  case SpvBuiltIn##name:        \
+  case spv::BuiltIn::name:      \
     SaveName(target_id, #name); \
     return;
-  switch (built_in) {
+  switch (spv::BuiltIn(built_in)) {
     GLCASE(Position)
     GLCASE(PointSize)
     GLCASE(ClipDistance)
@@ -170,28 +170,28 @@
 spv_result_t FriendlyNameMapper::ParseInstruction(
     const spv_parsed_instruction_t& inst) {
   const auto result_id = inst.result_id;
-  switch (inst.opcode) {
-    case SpvOpName:
+  switch (spv::Op(inst.opcode)) {
+    case spv::Op::OpName:
       SaveName(inst.words[1], spvDecodeLiteralStringOperand(inst, 1));
       break;
-    case SpvOpDecorate:
+    case spv::Op::OpDecorate:
       // Decorations come after OpName.  So OpName will take precedence over
       // decorations.
       //
       // In theory, we should also handle OpGroupDecorate.  But that's unlikely
       // to occur.
-      if (inst.words[2] == SpvDecorationBuiltIn) {
+      if (spv::Decoration(inst.words[2]) == spv::Decoration::BuiltIn) {
         assert(inst.num_words > 3);
         SaveBuiltInName(inst.words[1], inst.words[3]);
       }
       break;
-    case SpvOpTypeVoid:
+    case spv::Op::OpTypeVoid:
       SaveName(result_id, "void");
       break;
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       SaveName(result_id, "bool");
       break;
-    case SpvOpTypeInt: {
+    case spv::Op::OpTypeInt: {
       std::string signedness;
       std::string root;
       const auto bit_width = inst.words[2];
@@ -216,7 +216,7 @@
       if (0 == inst.words[3]) signedness = "u";
       SaveName(result_id, signedness + root);
     } break;
-    case SpvOpTypeFloat: {
+    case spv::Op::OpTypeFloat: {
       const auto bit_width = inst.words[2];
       switch (bit_width) {
         case 16:
@@ -233,68 +233,68 @@
           break;
       }
     } break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       SaveName(result_id, std::string("v") + to_string(inst.words[3]) +
                               NameForId(inst.words[2]));
       break;
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       SaveName(result_id, std::string("mat") + to_string(inst.words[3]) +
                               NameForId(inst.words[2]));
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       SaveName(result_id, std::string("_arr_") + NameForId(inst.words[2]) +
                               "_" + NameForId(inst.words[3]));
       break;
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       SaveName(result_id,
                std::string("_runtimearr_") + NameForId(inst.words[2]));
       break;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       SaveName(result_id, std::string("_ptr_") +
                               NameForEnumOperand(SPV_OPERAND_TYPE_STORAGE_CLASS,
                                                  inst.words[2]) +
                               "_" + NameForId(inst.words[3]));
       break;
-    case SpvOpTypePipe:
+    case spv::Op::OpTypePipe:
       SaveName(result_id,
                std::string("Pipe") +
                    NameForEnumOperand(SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
                                       inst.words[2]));
       break;
-    case SpvOpTypeEvent:
+    case spv::Op::OpTypeEvent:
       SaveName(result_id, "Event");
       break;
-    case SpvOpTypeDeviceEvent:
+    case spv::Op::OpTypeDeviceEvent:
       SaveName(result_id, "DeviceEvent");
       break;
-    case SpvOpTypeReserveId:
+    case spv::Op::OpTypeReserveId:
       SaveName(result_id, "ReserveId");
       break;
-    case SpvOpTypeQueue:
+    case spv::Op::OpTypeQueue:
       SaveName(result_id, "Queue");
       break;
-    case SpvOpTypeOpaque:
+    case spv::Op::OpTypeOpaque:
       SaveName(result_id, std::string("Opaque_") +
                               Sanitize(spvDecodeLiteralStringOperand(inst, 1)));
       break;
-    case SpvOpTypePipeStorage:
+    case spv::Op::OpTypePipeStorage:
       SaveName(result_id, "PipeStorage");
       break;
-    case SpvOpTypeNamedBarrier:
+    case spv::Op::OpTypeNamedBarrier:
       SaveName(result_id, "NamedBarrier");
       break;
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       // Structs are mapped rather simplisitically. Just indicate that they
       // are a struct and then give the raw Id number.
       SaveName(result_id, std::string("_struct_") + to_string(result_id));
       break;
-    case SpvOpConstantTrue:
+    case spv::Op::OpConstantTrue:
       SaveName(result_id, "true");
       break;
-    case SpvOpConstantFalse:
+    case spv::Op::OpConstantFalse:
       SaveName(result_id, "false");
       break;
-    case SpvOpConstant: {
+    case spv::Op::OpConstant: {
       std::ostringstream value;
       EmitNumericLiteral(&value, inst, inst.operands[2]);
       auto value_str = value.str();
diff --git a/third_party/SPIRV-Tools/source/opcode.cpp b/third_party/SPIRV-Tools/source/opcode.cpp
index 2584d51..c5006af 100644
--- a/third_party/SPIRV-Tools/source/opcode.cpp
+++ b/third_party/SPIRV-Tools/source/opcode.cpp
@@ -64,7 +64,7 @@
   return "Unknown";
 }
 
-uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
+uint32_t spvOpcodeMake(uint16_t wordCount, spv::Op opcode) {
   return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
 }
 
@@ -125,7 +125,7 @@
 
 spv_result_t spvOpcodeTableValueLookup(spv_target_env env,
                                        const spv_opcode_table table,
-                                       const SpvOp opcode,
+                                       const spv::Op opcode,
                                        spv_opcode_desc* pEntry) {
   if (!table) return SPV_ERROR_INVALID_TABLE;
   if (!pEntry) return SPV_ERROR_INVALID_POINTER;
@@ -166,7 +166,7 @@
   return SPV_ERROR_INVALID_LOOKUP;
 }
 
-void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
+void spvInstructionCopy(const uint32_t* words, const spv::Op opcode,
                         const uint16_t wordCount, const spv_endianness_t endian,
                         spv_instruction_t* pInst) {
   pInst->opcode = opcode;
@@ -177,7 +177,7 @@
       uint16_t thisWordCount;
       uint16_t thisOpcode;
       spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
-      assert(opcode == static_cast<SpvOp>(thisOpcode) &&
+      assert(opcode == static_cast<spv::Op>(thisOpcode) &&
              wordCount == thisWordCount && "Endianness failed!");
     }
   }
@@ -186,7 +186,7 @@
 const char* spvOpcodeString(const uint32_t opcode) {
   const auto beg = kOpcodeTableEntries;
   const auto end = kOpcodeTableEntries + ARRAY_SIZE(kOpcodeTableEntries);
-  spv_opcode_desc_t needle = {"",    static_cast<SpvOp>(opcode),
+  spv_opcode_desc_t needle = {"",    static_cast<spv::Op>(opcode),
                               0,     nullptr,
                               0,     {},
                               false, false,
@@ -196,7 +196,7 @@
     return lhs.opcode < rhs.opcode;
   };
   auto it = std::lower_bound(beg, end, needle, comp);
-  if (it != end && it->opcode == opcode) {
+  if (it != end && it->opcode == spv::Op(opcode)) {
     return it->name;
   }
 
@@ -204,140 +204,144 @@
   return "unknown";
 }
 
-int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
+const char* spvOpcodeString(const spv::Op opcode) {
+  return spvOpcodeString(static_cast<uint32_t>(opcode));
+}
+
+int32_t spvOpcodeIsScalarType(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeBool:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeIsSpecConstant(const SpvOp opcode) {
+int32_t spvOpcodeIsSpecConstant(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
-    case SpvOpSpecConstant:
-    case SpvOpSpecConstantComposite:
-    case SpvOpSpecConstantOp:
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpSpecConstantComposite:
+    case spv::Op::OpSpecConstantOp:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeIsConstant(const SpvOp opcode) {
+int32_t spvOpcodeIsConstant(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpConstantTrue:
-    case SpvOpConstantFalse:
-    case SpvOpConstant:
-    case SpvOpConstantComposite:
-    case SpvOpConstantSampler:
-    case SpvOpConstantNull:
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
-    case SpvOpSpecConstant:
-    case SpvOpSpecConstantComposite:
-    case SpvOpSpecConstantOp:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstantFalse:
+    case spv::Op::OpConstant:
+    case spv::Op::OpConstantComposite:
+    case spv::Op::OpConstantSampler:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpSpecConstantComposite:
+    case spv::Op::OpSpecConstantOp:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsConstantOrUndef(const SpvOp opcode) {
-  return opcode == SpvOpUndef || spvOpcodeIsConstant(opcode);
+bool spvOpcodeIsConstantOrUndef(const spv::Op opcode) {
+  return opcode == spv::Op::OpUndef || spvOpcodeIsConstant(opcode);
 }
 
-bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode) {
+bool spvOpcodeIsScalarSpecConstant(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
-    case SpvOpSpecConstant:
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpSpecConstant:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeIsComposite(const SpvOp opcode) {
+int32_t spvOpcodeIsComposite(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeArray:
-    case SpvOpTypeStruct:
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeStruct:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode) {
+bool spvOpcodeReturnsLogicalVariablePointer(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpVariable:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpFunctionParameter:
-    case SpvOpImageTexelPointer:
-    case SpvOpCopyObject:
-    case SpvOpSelect:
-    case SpvOpPhi:
-    case SpvOpFunctionCall:
-    case SpvOpPtrAccessChain:
-    case SpvOpLoad:
-    case SpvOpConstantNull:
+    case spv::Op::OpVariable:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpFunctionParameter:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpSelect:
+    case spv::Op::OpPhi:
+    case spv::Op::OpFunctionCall:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpLoad:
+    case spv::Op::OpConstantNull:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
+int32_t spvOpcodeReturnsLogicalPointer(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpVariable:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpFunctionParameter:
-    case SpvOpImageTexelPointer:
-    case SpvOpCopyObject:
+    case spv::Op::OpVariable:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpFunctionParameter:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpCopyObject:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeGeneratesType(SpvOp op) {
+int32_t spvOpcodeGeneratesType(spv::Op op) {
   switch (op) {
-    case SpvOpTypeVoid:
-    case SpvOpTypeBool:
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
-    case SpvOpTypeStruct:
-    case SpvOpTypeOpaque:
-    case SpvOpTypePointer:
-    case SpvOpTypeFunction:
-    case SpvOpTypeEvent:
-    case SpvOpTypeDeviceEvent:
-    case SpvOpTypeReserveId:
-    case SpvOpTypeQueue:
-    case SpvOpTypePipe:
-    case SpvOpTypePipeStorage:
-    case SpvOpTypeNamedBarrier:
-    case SpvOpTypeAccelerationStructureNV:
-    case SpvOpTypeCooperativeMatrixNV:
-    // case SpvOpTypeAccelerationStructureKHR: covered by
-    // SpvOpTypeAccelerationStructureNV
-    case SpvOpTypeRayQueryKHR:
+    case spv::Op::OpTypeVoid:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
+    case spv::Op::OpTypeStruct:
+    case spv::Op::OpTypeOpaque:
+    case spv::Op::OpTypePointer:
+    case spv::Op::OpTypeFunction:
+    case spv::Op::OpTypeEvent:
+    case spv::Op::OpTypeDeviceEvent:
+    case spv::Op::OpTypeReserveId:
+    case spv::Op::OpTypeQueue:
+    case spv::Op::OpTypePipe:
+    case spv::Op::OpTypePipeStorage:
+    case spv::Op::OpTypeNamedBarrier:
+    case spv::Op::OpTypeAccelerationStructureNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
+    // case spv::Op::OpTypeAccelerationStructureKHR: covered by
+    // spv::Op::OpTypeAccelerationStructureNV
+    case spv::Op::OpTypeRayQueryKHR:
       return true;
     default:
       // In particular, OpTypeForwardPointer does not generate a type,
@@ -348,15 +352,15 @@
   return 0;
 }
 
-bool spvOpcodeIsDecoration(const SpvOp opcode) {
+bool spvOpcodeIsDecoration(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId:
-    case SpvOpMemberDecorate:
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorateStringGOOGLE:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorateStringGOOGLE:
       return true;
     default:
       break;
@@ -364,406 +368,403 @@
   return false;
 }
 
-bool spvOpcodeIsLoad(const SpvOp opcode) {
+bool spvOpcodeIsLoad(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpLoad:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageRead:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpLoad:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseRead:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsBranch(SpvOp opcode) {
+bool spvOpcodeIsBranch(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpBranch:
-    case SpvOpBranchConditional:
-    case SpvOpSwitch:
+    case spv::Op::OpBranch:
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode) {
+bool spvOpcodeIsAtomicWithLoad(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicFAddEXT:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicFMinEXT:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicFMaxEXT:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicFAddEXT:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicFMinEXT:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicFMaxEXT:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsAtomicOp(const SpvOp opcode) {
-  return (spvOpcodeIsAtomicWithLoad(opcode) || opcode == SpvOpAtomicStore ||
-          opcode == SpvOpAtomicFlagClear);
+bool spvOpcodeIsAtomicOp(const spv::Op opcode) {
+  return (spvOpcodeIsAtomicWithLoad(opcode) ||
+          opcode == spv::Op::OpAtomicStore ||
+          opcode == spv::Op::OpAtomicFlagClear);
 }
 
-bool spvOpcodeIsReturn(SpvOp opcode) {
+bool spvOpcodeIsReturn(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpReturn:
-    case SpvOpReturnValue:
+    case spv::Op::OpReturn:
+    case spv::Op::OpReturnValue:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsAbort(SpvOp opcode) {
+bool spvOpcodeIsAbort(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpKill:
-    case SpvOpUnreachable:
-    case SpvOpTerminateInvocation:
-    case SpvOpTerminateRayKHR:
-    case SpvOpIgnoreIntersectionKHR:
+    case spv::Op::OpKill:
+    case spv::Op::OpUnreachable:
+    case spv::Op::OpTerminateInvocation:
+    case spv::Op::OpTerminateRayKHR:
+    case spv::Op::OpIgnoreIntersectionKHR:
+    case spv::Op::OpEmitMeshTasksEXT:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsReturnOrAbort(SpvOp opcode) {
+bool spvOpcodeIsReturnOrAbort(spv::Op opcode) {
   return spvOpcodeIsReturn(opcode) || spvOpcodeIsAbort(opcode);
 }
 
-bool spvOpcodeIsBlockTerminator(SpvOp opcode) {
+bool spvOpcodeIsBlockTerminator(spv::Op opcode) {
   return spvOpcodeIsBranch(opcode) || spvOpcodeIsReturnOrAbort(opcode);
 }
 
-bool spvOpcodeTerminatesExecution(SpvOp opcode) {
-  return opcode == SpvOpKill || opcode == SpvOpTerminateInvocation ||
-         opcode == SpvOpTerminateRayKHR || opcode == SpvOpIgnoreIntersectionKHR;
-}
-
-bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) {
+bool spvOpcodeIsBaseOpaqueType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpTypeImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeOpaque:
-    case SpvOpTypeEvent:
-    case SpvOpTypeDeviceEvent:
-    case SpvOpTypeReserveId:
-    case SpvOpTypeQueue:
-    case SpvOpTypePipe:
-    case SpvOpTypeForwardPointer:
-    case SpvOpTypePipeStorage:
-    case SpvOpTypeNamedBarrier:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeOpaque:
+    case spv::Op::OpTypeEvent:
+    case spv::Op::OpTypeDeviceEvent:
+    case spv::Op::OpTypeReserveId:
+    case spv::Op::OpTypeQueue:
+    case spv::Op::OpTypePipe:
+    case spv::Op::OpTypeForwardPointer:
+    case spv::Op::OpTypePipeStorage:
+    case spv::Op::OpTypeNamedBarrier:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsNonUniformGroupOperation(SpvOp opcode) {
+bool spvOpcodeIsNonUniformGroupOperation(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpGroupNonUniformElect:
-    case SpvOpGroupNonUniformAll:
-    case SpvOpGroupNonUniformAny:
-    case SpvOpGroupNonUniformAllEqual:
-    case SpvOpGroupNonUniformBroadcast:
-    case SpvOpGroupNonUniformBroadcastFirst:
-    case SpvOpGroupNonUniformBallot:
-    case SpvOpGroupNonUniformInverseBallot:
-    case SpvOpGroupNonUniformBallotBitExtract:
-    case SpvOpGroupNonUniformBallotBitCount:
-    case SpvOpGroupNonUniformBallotFindLSB:
-    case SpvOpGroupNonUniformBallotFindMSB:
-    case SpvOpGroupNonUniformShuffle:
-    case SpvOpGroupNonUniformShuffleXor:
-    case SpvOpGroupNonUniformShuffleUp:
-    case SpvOpGroupNonUniformShuffleDown:
-    case SpvOpGroupNonUniformIAdd:
-    case SpvOpGroupNonUniformFAdd:
-    case SpvOpGroupNonUniformIMul:
-    case SpvOpGroupNonUniformFMul:
-    case SpvOpGroupNonUniformSMin:
-    case SpvOpGroupNonUniformUMin:
-    case SpvOpGroupNonUniformFMin:
-    case SpvOpGroupNonUniformSMax:
-    case SpvOpGroupNonUniformUMax:
-    case SpvOpGroupNonUniformFMax:
-    case SpvOpGroupNonUniformBitwiseAnd:
-    case SpvOpGroupNonUniformBitwiseOr:
-    case SpvOpGroupNonUniformBitwiseXor:
-    case SpvOpGroupNonUniformLogicalAnd:
-    case SpvOpGroupNonUniformLogicalOr:
-    case SpvOpGroupNonUniformLogicalXor:
-    case SpvOpGroupNonUniformQuadBroadcast:
-    case SpvOpGroupNonUniformQuadSwap:
-    case SpvOpGroupNonUniformRotateKHR:
+    case spv::Op::OpGroupNonUniformElect:
+    case spv::Op::OpGroupNonUniformAll:
+    case spv::Op::OpGroupNonUniformAny:
+    case spv::Op::OpGroupNonUniformAllEqual:
+    case spv::Op::OpGroupNonUniformBroadcast:
+    case spv::Op::OpGroupNonUniformBroadcastFirst:
+    case spv::Op::OpGroupNonUniformBallot:
+    case spv::Op::OpGroupNonUniformInverseBallot:
+    case spv::Op::OpGroupNonUniformBallotBitExtract:
+    case spv::Op::OpGroupNonUniformBallotBitCount:
+    case spv::Op::OpGroupNonUniformBallotFindLSB:
+    case spv::Op::OpGroupNonUniformBallotFindMSB:
+    case spv::Op::OpGroupNonUniformShuffle:
+    case spv::Op::OpGroupNonUniformShuffleXor:
+    case spv::Op::OpGroupNonUniformShuffleUp:
+    case spv::Op::OpGroupNonUniformShuffleDown:
+    case spv::Op::OpGroupNonUniformIAdd:
+    case spv::Op::OpGroupNonUniformFAdd:
+    case spv::Op::OpGroupNonUniformIMul:
+    case spv::Op::OpGroupNonUniformFMul:
+    case spv::Op::OpGroupNonUniformSMin:
+    case spv::Op::OpGroupNonUniformUMin:
+    case spv::Op::OpGroupNonUniformFMin:
+    case spv::Op::OpGroupNonUniformSMax:
+    case spv::Op::OpGroupNonUniformUMax:
+    case spv::Op::OpGroupNonUniformFMax:
+    case spv::Op::OpGroupNonUniformBitwiseAnd:
+    case spv::Op::OpGroupNonUniformBitwiseOr:
+    case spv::Op::OpGroupNonUniformBitwiseXor:
+    case spv::Op::OpGroupNonUniformLogicalAnd:
+    case spv::Op::OpGroupNonUniformLogicalOr:
+    case spv::Op::OpGroupNonUniformLogicalXor:
+    case spv::Op::OpGroupNonUniformQuadBroadcast:
+    case spv::Op::OpGroupNonUniformQuadSwap:
+    case spv::Op::OpGroupNonUniformRotateKHR:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsScalarizable(SpvOp opcode) {
+bool spvOpcodeIsScalarizable(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpPhi:
-    case SpvOpCopyObject:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
+    case spv::Op::OpPhi:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsDebug(SpvOp opcode) {
+bool spvOpcodeIsDebug(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpName:
-    case SpvOpMemberName:
-    case SpvOpSource:
-    case SpvOpSourceContinued:
-    case SpvOpSourceExtension:
-    case SpvOpString:
-    case SpvOpLine:
-    case SpvOpNoLine:
-    case SpvOpModuleProcessed:
+    case spv::Op::OpName:
+    case spv::Op::OpMemberName:
+    case spv::Op::OpSource:
+    case spv::Op::OpSourceContinued:
+    case spv::Op::OpSourceExtension:
+    case spv::Op::OpString:
+    case spv::Op::OpLine:
+    case spv::Op::OpNoLine:
+    case spv::Op::OpModuleProcessed:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode) {
+bool spvOpcodeIsCommutativeBinaryOperator(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsLinearAlgebra(SpvOp opcode) {
+bool spvOpcodeIsLinearAlgebra(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpTranspose:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsImageSample(const SpvOp opcode) {
+bool spvOpcodeIsImageSample(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
       return true;
     default:
       return false;
   }
 }
 
-std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
+std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpMemoryBarrier:
+    case spv::Op::OpMemoryBarrier:
       return {1};
-    case SpvOpAtomicStore:
-    case SpvOpControlBarrier:
-    case SpvOpAtomicFlagClear:
-    case SpvOpMemoryNamedBarrier:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpControlBarrier:
+    case spv::Op::OpAtomicFlagClear:
+    case spv::Op::OpMemoryNamedBarrier:
       return {2};
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicFAddEXT:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicFAddEXT:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return {4};
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
       return {4, 5};
     default:
       return {};
   }
 }
 
-bool spvOpcodeIsAccessChain(SpvOp opcode) {
+bool spvOpcodeIsAccessChain(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsBit(SpvOp opcode) {
+bool spvOpcodeIsBit(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
       return true;
     default:
       return false;
diff --git a/third_party/SPIRV-Tools/source/opcode.h b/third_party/SPIRV-Tools/source/opcode.h
index c8525a2..217aeb2 100644
--- a/third_party/SPIRV-Tools/source/opcode.h
+++ b/third_party/SPIRV-Tools/source/opcode.h
@@ -29,7 +29,7 @@
 const char* spvGeneratorStr(uint32_t generator);
 
 // Combines word_count and opcode enumerant in single word.
-uint32_t spvOpcodeMake(uint16_t word_count, SpvOp opcode);
+uint32_t spvOpcodeMake(uint16_t word_count, spv::Op opcode);
 
 // Splits word into into two constituent parts: word_count and opcode.
 void spvOpcodeSplit(const uint32_t word, uint16_t* word_count,
@@ -45,117 +45,118 @@
 // SPV_SUCCESS and writes a handle of the table entry into *entry.
 spv_result_t spvOpcodeTableValueLookup(spv_target_env,
                                        const spv_opcode_table table,
-                                       const SpvOp opcode,
+                                       const spv::Op opcode,
                                        spv_opcode_desc* entry);
 
 // Copies an instruction's word and fixes the endianness to host native. The
 // source instruction's stream/opcode/endianness is in the words/opcode/endian
 // parameter. The word_count parameter specifies the number of words to copy.
 // Writes copied instruction into *inst.
-void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
+void spvInstructionCopy(const uint32_t* words, const spv::Op opcode,
                         const uint16_t word_count,
                         const spv_endianness_t endian, spv_instruction_t* inst);
 
 // Determine if the given opcode is a scalar type. Returns zero if false,
 // non-zero otherwise.
-int32_t spvOpcodeIsScalarType(const SpvOp opcode);
+int32_t spvOpcodeIsScalarType(const spv::Op opcode);
 
 // Determines if the given opcode is a specialization constant. Returns zero if
 // false, non-zero otherwise.
-int32_t spvOpcodeIsSpecConstant(const SpvOp opcode);
+int32_t spvOpcodeIsSpecConstant(const spv::Op opcode);
 
 // Determines if the given opcode is a constant. Returns zero if false, non-zero
 // otherwise.
-int32_t spvOpcodeIsConstant(const SpvOp opcode);
+int32_t spvOpcodeIsConstant(const spv::Op opcode);
 
 // Returns true if the given opcode is a constant or undef.
-bool spvOpcodeIsConstantOrUndef(const SpvOp opcode);
+bool spvOpcodeIsConstantOrUndef(const spv::Op opcode);
 
 // Returns true if the given opcode is a scalar specialization constant.
-bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode);
+bool spvOpcodeIsScalarSpecConstant(const spv::Op opcode);
 
 // Determines if the given opcode is a composite type. Returns zero if false,
 // non-zero otherwise.
-int32_t spvOpcodeIsComposite(const SpvOp opcode);
+int32_t spvOpcodeIsComposite(const spv::Op opcode);
 
 // Determines if the given opcode results in a pointer when using the logical
 // addressing model. Returns zero if false, non-zero otherwise.
-int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode);
+int32_t spvOpcodeReturnsLogicalPointer(const spv::Op opcode);
 
 // Returns whether the given opcode could result in a pointer or a variable
 // pointer when using the logical addressing model.
-bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode);
+bool spvOpcodeReturnsLogicalVariablePointer(const spv::Op opcode);
 
 // Determines if the given opcode generates a type. Returns zero if false,
 // non-zero otherwise.
-int32_t spvOpcodeGeneratesType(SpvOp opcode);
+int32_t spvOpcodeGeneratesType(spv::Op opcode);
 
 // Returns true if the opcode adds a decoration to an id.
-bool spvOpcodeIsDecoration(const SpvOp opcode);
+bool spvOpcodeIsDecoration(const spv::Op opcode);
 
 // Returns true if the opcode is a load from memory into a result id.  This
 // function only considers core instructions.
-bool spvOpcodeIsLoad(const SpvOp opcode);
+bool spvOpcodeIsLoad(const spv::Op opcode);
 
 // Returns true if the opcode is an atomic operation that uses the original
 // value.
-bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode);
+bool spvOpcodeIsAtomicWithLoad(const spv::Op opcode);
 
 // Returns true if the opcode is an atomic operation.
-bool spvOpcodeIsAtomicOp(const SpvOp opcode);
+bool spvOpcodeIsAtomicOp(const spv::Op opcode);
 
 // Returns true if the given opcode is a branch instruction.
-bool spvOpcodeIsBranch(SpvOp opcode);
+bool spvOpcodeIsBranch(spv::Op opcode);
 
 // Returns true if the given opcode is a return instruction.
-bool spvOpcodeIsReturn(SpvOp opcode);
+bool spvOpcodeIsReturn(spv::Op opcode);
 
-// Returns true if the given opcode aborts execution.
-bool spvOpcodeIsAbort(SpvOp opcode);
+// Returns true if the given opcode aborts execution.  To abort means that after
+// executing that instruction, no other instructions will be executed regardless
+// of the context in which the instruction appears.  Note that `OpUnreachable`
+// is considered an abort even if its behaviour is undefined.
+bool spvOpcodeIsAbort(spv::Op opcode);
 
 // Returns true if the given opcode is a return instruction or it aborts
 // execution.
-bool spvOpcodeIsReturnOrAbort(SpvOp opcode);
-
-// Returns true if the given opcode is a kill instruction or it terminates
-// execution. Note that branches, returns, and unreachables do not terminate
-// execution.
-bool spvOpcodeTerminatesExecution(SpvOp opcode);
+bool spvOpcodeIsReturnOrAbort(spv::Op opcode);
 
 // Returns true if the given opcode is a basic block terminator.
-bool spvOpcodeIsBlockTerminator(SpvOp opcode);
+bool spvOpcodeIsBlockTerminator(spv::Op opcode);
 
 // Returns true if the given opcode always defines an opaque type.
-bool spvOpcodeIsBaseOpaqueType(SpvOp opcode);
+bool spvOpcodeIsBaseOpaqueType(spv::Op opcode);
 
 // Returns true if the given opcode is a non-uniform group operation.
-bool spvOpcodeIsNonUniformGroupOperation(SpvOp opcode);
+bool spvOpcodeIsNonUniformGroupOperation(spv::Op opcode);
 
 // Returns true if the opcode with vector inputs could be divided into a series
 // of independent scalar operations that would give the same result.
-bool spvOpcodeIsScalarizable(SpvOp opcode);
+bool spvOpcodeIsScalarizable(spv::Op opcode);
 
 // Returns true if the given opcode is a debug instruction.
-bool spvOpcodeIsDebug(SpvOp opcode);
+bool spvOpcodeIsDebug(spv::Op opcode);
 
 // Returns true for opcodes that are binary operators,
 // where the order of the operands is irrelevant.
-bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode);
+bool spvOpcodeIsCommutativeBinaryOperator(spv::Op opcode);
 
 // Returns true for opcodes that represent linear algebra instructions.
-bool spvOpcodeIsLinearAlgebra(SpvOp opcode);
+bool spvOpcodeIsLinearAlgebra(spv::Op opcode);
 
 // Returns true for opcodes that represent image sample instructions.
-bool spvOpcodeIsImageSample(SpvOp opcode);
+bool spvOpcodeIsImageSample(spv::Op opcode);
 
 // Returns a vector containing the indices of the memory semantics <id>
 // operands for |opcode|.
-std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode);
+std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode);
 
 // Returns true for opcodes that represent access chain instructions.
-bool spvOpcodeIsAccessChain(SpvOp opcode);
+bool spvOpcodeIsAccessChain(spv::Op opcode);
 
 // Returns true for opcodes that represent bit instructions.
-bool spvOpcodeIsBit(SpvOp opcode);
+bool spvOpcodeIsBit(spv::Op opcode);
+
+// Gets the name of an instruction, without the "Op" prefix.
+const char* spvOpcodeString(const spv::Op opcode);
 
 #endif  // SOURCE_OPCODE_H_
diff --git a/third_party/SPIRV-Tools/source/operand.cpp b/third_party/SPIRV-Tools/source/operand.cpp
index 0c255a3..31a6c59 100644
--- a/third_party/SPIRV-Tools/source/operand.cpp
+++ b/third_party/SPIRV-Tools/source/operand.cpp
@@ -512,7 +512,7 @@
 }
 
 std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
-    SpvOp opcode) {
+    spv::Op opcode) {
   std::function<bool(unsigned index)> out;
   if (spvOpcodeGeneratesType(opcode)) {
     // All types can use forward pointers.
@@ -520,57 +520,57 @@
     return out;
   }
   switch (opcode) {
-    case SpvOpExecutionMode:
-    case SpvOpExecutionModeId:
-    case SpvOpEntryPoint:
-    case SpvOpName:
-    case SpvOpMemberName:
-    case SpvOpSelectionMerge:
-    case SpvOpDecorate:
-    case SpvOpMemberDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorateStringGOOGLE:
-    case SpvOpBranch:
-    case SpvOpLoopMerge:
+    case spv::Op::OpExecutionMode:
+    case spv::Op::OpExecutionModeId:
+    case spv::Op::OpEntryPoint:
+    case spv::Op::OpName:
+    case spv::Op::OpMemberName:
+    case spv::Op::OpSelectionMerge:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorateStringGOOGLE:
+    case spv::Op::OpBranch:
+    case spv::Op::OpLoopMerge:
       out = [](unsigned) { return true; };
       break;
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate:
-    case SpvOpBranchConditional:
-    case SpvOpSwitch:
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate:
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch:
       out = [](unsigned index) { return index != 0; };
       break;
 
-    case SpvOpFunctionCall:
+    case spv::Op::OpFunctionCall:
       // The Function parameter.
       out = [](unsigned index) { return index == 2; };
       break;
 
-    case SpvOpPhi:
+    case spv::Op::OpPhi:
       out = [](unsigned index) { return index > 1; };
       break;
 
-    case SpvOpEnqueueKernel:
+    case spv::Op::OpEnqueueKernel:
       // The Invoke parameter.
       out = [](unsigned index) { return index == 8; };
       break;
 
-    case SpvOpGetKernelNDrangeSubGroupCount:
-    case SpvOpGetKernelNDrangeMaxSubGroupSize:
+    case spv::Op::OpGetKernelNDrangeSubGroupCount:
+    case spv::Op::OpGetKernelNDrangeMaxSubGroupSize:
       // The Invoke parameter.
       out = [](unsigned index) { return index == 3; };
       break;
 
-    case SpvOpGetKernelWorkGroupSize:
-    case SpvOpGetKernelPreferredWorkGroupSizeMultiple:
+    case spv::Op::OpGetKernelWorkGroupSize:
+    case spv::Op::OpGetKernelPreferredWorkGroupSizeMultiple:
       // The Invoke parameter.
       out = [](unsigned index) { return index == 2; };
       break;
-    case SpvOpTypeForwardPointer:
+    case spv::Op::OpTypeForwardPointer:
       out = [](unsigned index) { return index == 0; };
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       out = [](unsigned index) { return index == 1; };
       break;
     default:
diff --git a/third_party/SPIRV-Tools/source/operand.h b/third_party/SPIRV-Tools/source/operand.h
index 7c73c6f..a3010d9 100644
--- a/third_party/SPIRV-Tools/source/operand.h
+++ b/third_party/SPIRV-Tools/source/operand.h
@@ -139,7 +139,7 @@
 // of the operand can be forward declared. This function will
 // used in the SSA validation stage of the pipeline
 std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
-    SpvOp opcode);
+    spv::Op opcode);
 
 // Takes the instruction key of a debug info extension instruction
 // and returns a function object that will return true if the index
diff --git a/third_party/SPIRV-Tools/source/opt/CMakeLists.txt b/third_party/SPIRV-Tools/source/opt/CMakeLists.txt
index 75fe4c0..085c430 100644
--- a/third_party/SPIRV-Tools/source/opt/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/opt/CMakeLists.txt
@@ -15,6 +15,7 @@
   fix_func_call_arguments.h
   aggressive_dead_code_elim_pass.h
   amd_ext_to_khr.h
+  analyze_live_input_pass.h
   basic_block.h
   block_merge_pass.h
   block_merge_util.h
@@ -48,6 +49,7 @@
   eliminate_dead_functions_util.h
   eliminate_dead_input_components_pass.h
   eliminate_dead_members_pass.h
+  eliminate_dead_output_stores_pass.h
   empty_pass.h
   feature_manager.h
   fix_storage_class.h
@@ -74,6 +76,7 @@
   ir_context.h
   ir_loader.h
   licm_pass.h
+  liveness.h
   local_access_chain_convert_pass.h
   local_redundancy_elimination.h
   local_single_block_elim_pass.h
@@ -131,6 +134,7 @@
   fix_func_call_arguments.cpp
   aggressive_dead_code_elim_pass.cpp
   amd_ext_to_khr.cpp
+  analyze_live_input_pass.cpp
   basic_block.cpp
   block_merge_pass.cpp
   block_merge_util.cpp
@@ -164,6 +168,7 @@
   eliminate_dead_functions_util.cpp
   eliminate_dead_input_components_pass.cpp
   eliminate_dead_members_pass.cpp
+  eliminate_dead_output_stores_pass.cpp
   feature_manager.cpp
   fix_storage_class.cpp
   flatten_decoration_pass.cpp
@@ -188,6 +193,7 @@
   ir_context.cpp
   ir_loader.cpp
   licm_pass.cpp
+  liveness.cpp
   local_access_chain_convert_pass.cpp
   local_redundancy_elimination.cpp
   local_single_block_elim_pass.cpp
diff --git a/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.cpp b/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.cpp
index ffb499f..f68032d 100644
--- a/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.cpp
@@ -31,51 +31,50 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
 
-const uint32_t kTypePointerStorageClassInIdx = 0;
-const uint32_t kEntryPointFunctionIdInIdx = 1;
-const uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
-const uint32_t kLoopMergeContinueBlockIdInIdx = 1;
-const uint32_t kCopyMemoryTargetAddrInIdx = 0;
-const uint32_t kCopyMemorySourceAddrInIdx = 1;
-const uint32_t kLoadSourceAddrInIdx = 0;
-const uint32_t kDebugDeclareOperandVariableIndex = 5;
-const uint32_t kGlobalVariableVariableIndex = 12;
+constexpr uint32_t kTypePointerStorageClassInIdx = 0;
+constexpr uint32_t kEntryPointFunctionIdInIdx = 1;
+constexpr uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
+constexpr uint32_t kLoopMergeContinueBlockIdInIdx = 1;
+constexpr uint32_t kCopyMemoryTargetAddrInIdx = 0;
+constexpr uint32_t kCopyMemorySourceAddrInIdx = 1;
+constexpr uint32_t kLoadSourceAddrInIdx = 0;
+constexpr uint32_t kDebugDeclareOperandVariableIndex = 5;
+constexpr uint32_t kGlobalVariableVariableIndex = 12;
 
 // Sorting functor to present annotation instructions in an easy-to-process
 // order. The functor orders by opcode first and falls back on unique id
 // ordering if both instructions have the same opcode.
 //
 // Desired priority:
-// SpvOpGroupDecorate
-// SpvOpGroupMemberDecorate
-// SpvOpDecorate
-// SpvOpMemberDecorate
-// SpvOpDecorateId
-// SpvOpDecorateStringGOOGLE
-// SpvOpDecorationGroup
+// spv::Op::OpGroupDecorate
+// spv::Op::OpGroupMemberDecorate
+// spv::Op::OpDecorate
+// spv::Op::OpMemberDecorate
+// spv::Op::OpDecorateId
+// spv::Op::OpDecorateStringGOOGLE
+// spv::Op::OpDecorationGroup
 struct DecorationLess {
   bool operator()(const Instruction* lhs, const Instruction* rhs) const {
     assert(lhs && rhs);
-    SpvOp lhsOp = lhs->opcode();
-    SpvOp rhsOp = rhs->opcode();
+    spv::Op lhsOp = lhs->opcode();
+    spv::Op rhsOp = rhs->opcode();
     if (lhsOp != rhsOp) {
 #define PRIORITY_CASE(opcode)                          \
   if (lhsOp == opcode && rhsOp != opcode) return true; \
   if (rhsOp == opcode && lhsOp != opcode) return false;
       // OpGroupDecorate and OpGroupMember decorate are highest priority to
       // eliminate dead targets early and simplify subsequent checks.
-      PRIORITY_CASE(SpvOpGroupDecorate)
-      PRIORITY_CASE(SpvOpGroupMemberDecorate)
-      PRIORITY_CASE(SpvOpDecorate)
-      PRIORITY_CASE(SpvOpMemberDecorate)
-      PRIORITY_CASE(SpvOpDecorateId)
-      PRIORITY_CASE(SpvOpDecorateStringGOOGLE)
+      PRIORITY_CASE(spv::Op::OpGroupDecorate)
+      PRIORITY_CASE(spv::Op::OpGroupMemberDecorate)
+      PRIORITY_CASE(spv::Op::OpDecorate)
+      PRIORITY_CASE(spv::Op::OpMemberDecorate)
+      PRIORITY_CASE(spv::Op::OpDecorateId)
+      PRIORITY_CASE(spv::Op::OpDecorateStringGOOGLE)
       // OpDecorationGroup is lowest priority to ensure use/def chains remain
       // usable for instructions that target this group.
-      PRIORITY_CASE(SpvOpDecorationGroup)
+      PRIORITY_CASE(spv::Op::OpDecorationGroup)
 #undef PRIORITY_CASE
     }
 
@@ -86,25 +85,26 @@
 
 }  // namespace
 
-bool AggressiveDCEPass::IsVarOfStorage(uint32_t varId, uint32_t storageClass) {
+bool AggressiveDCEPass::IsVarOfStorage(uint32_t varId,
+                                       spv::StorageClass storageClass) {
   if (varId == 0) return false;
   const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
-  const SpvOp op = varInst->opcode();
-  if (op != SpvOpVariable) return false;
+  const spv::Op op = varInst->opcode();
+  if (op != spv::Op::OpVariable) return false;
   const uint32_t varTypeId = varInst->type_id();
   const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
-  if (varTypeInst->opcode() != SpvOpTypePointer) return false;
-  return varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
-         storageClass;
+  if (varTypeInst->opcode() != spv::Op::OpTypePointer) return false;
+  return spv::StorageClass(varTypeInst->GetSingleWordInOperand(
+             kTypePointerStorageClassInIdx)) == storageClass;
 }
 
 bool AggressiveDCEPass::IsLocalVar(uint32_t varId, Function* func) {
-  if (IsVarOfStorage(varId, SpvStorageClassFunction)) {
+  if (IsVarOfStorage(varId, spv::StorageClass::Function)) {
     return true;
   }
 
-  if (!IsVarOfStorage(varId, SpvStorageClassPrivate) &&
-      !IsVarOfStorage(varId, SpvStorageClassWorkgroup)) {
+  if (!IsVarOfStorage(varId, spv::StorageClass::Private) &&
+      !IsVarOfStorage(varId, spv::StorageClass::Workgroup)) {
     return false;
   }
 
@@ -122,21 +122,21 @@
     if (blk && blk->GetParent() != func) return;
 
     switch (user->opcode()) {
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
-      case SpvOpCopyObject:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
+      case spv::Op::OpCopyObject:
         this->AddStores(func, user->result_id());
         break;
-      case SpvOpLoad:
+      case spv::Op::OpLoad:
         break;
-      case SpvOpCopyMemory:
-      case SpvOpCopyMemorySized:
+      case spv::Op::OpCopyMemory:
+      case spv::Op::OpCopyMemorySized:
         if (user->GetSingleWordInOperand(kCopyMemoryTargetAddrInIdx) == ptrId) {
           AddToWorklist(user);
         }
         break;
       // If default, assume it stores e.g. frexp, modf, function call
-      case SpvOpStore:
+      case spv::Op::OpStore:
       default:
         AddToWorklist(user);
         break;
@@ -154,7 +154,7 @@
   // Only allow NonSemantic.Shader.DebugInfo.100, we cannot safely optimise
   // around unknown extended instruction sets even if they are non-semantic
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
@@ -172,11 +172,11 @@
     // This must be a decoration group. We go through annotations in a specific
     // order. So if this is not used by any group or group member decorates, it
     // is dead.
-    assert(tInst->opcode() == SpvOpDecorationGroup);
+    assert(tInst->opcode() == spv::Op::OpDecorationGroup);
     bool dead = true;
     get_def_use_mgr()->ForEachUser(tInst, [&dead](Instruction* user) {
-      if (user->opcode() == SpvOpGroupDecorate ||
-          user->opcode() == SpvOpGroupMemberDecorate)
+      if (user->opcode() == spv::Op::OpGroupDecorate ||
+          user->opcode() == spv::Op::OpGroupMemberDecorate)
         dead = false;
     });
     return dead;
@@ -197,7 +197,7 @@
 
 void AggressiveDCEPass::AddBranch(uint32_t labelId, BasicBlock* bp) {
   std::unique_ptr<Instruction> newBranch(
-      new Instruction(context(), SpvOpBranch, 0, 0,
+      new Instruction(context(), spv::Op::OpBranch, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}}));
   context()->AnalyzeDefUse(&*newBranch);
   context()->set_instr_block(&*newBranch, bp);
@@ -206,8 +206,8 @@
 
 void AggressiveDCEPass::AddBreaksAndContinuesToWorklist(
     Instruction* mergeInst) {
-  assert(mergeInst->opcode() == SpvOpSelectionMerge ||
-         mergeInst->opcode() == SpvOpLoopMerge);
+  assert(mergeInst->opcode() == spv::Op::OpSelectionMerge ||
+         mergeInst->opcode() == spv::Op::OpLoopMerge);
 
   BasicBlock* header = context()->get_instr_block(mergeInst);
   const uint32_t mergeId = mergeInst->GetSingleWordInOperand(0);
@@ -223,7 +223,7 @@
     }
   });
 
-  if (mergeInst->opcode() != SpvOpLoopMerge) {
+  if (mergeInst->opcode() != spv::Op::OpLoopMerge) {
     return;
   }
 
@@ -231,26 +231,27 @@
   const uint32_t contId =
       mergeInst->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx);
   get_def_use_mgr()->ForEachUser(contId, [&contId, this](Instruction* user) {
-    SpvOp op = user->opcode();
-    if (op == SpvOpBranchConditional || op == SpvOpSwitch) {
+    spv::Op op = user->opcode();
+    if (op == spv::Op::OpBranchConditional || op == spv::Op::OpSwitch) {
       // A conditional branch or switch can only be a continue if it does not
       // have a merge instruction or its merge block is not the continue block.
       Instruction* hdrMerge = GetMergeInstruction(user);
-      if (hdrMerge != nullptr && hdrMerge->opcode() == SpvOpSelectionMerge) {
+      if (hdrMerge != nullptr &&
+          hdrMerge->opcode() == spv::Op::OpSelectionMerge) {
         uint32_t hdrMergeId =
             hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
         if (hdrMergeId == contId) return;
         // Need to mark merge instruction too
         AddToWorklist(hdrMerge);
       }
-    } else if (op == SpvOpBranch) {
+    } else if (op == spv::Op::OpBranch) {
       // An unconditional branch can only be a continue if it is not
       // branching to its own merge block.
       BasicBlock* blk = context()->get_instr_block(user);
       Instruction* hdrBranch = GetHeaderBranch(blk);
       if (hdrBranch == nullptr) return;
       Instruction* hdrMerge = GetMergeInstruction(hdrBranch);
-      if (hdrMerge->opcode() == SpvOpLoopMerge) return;
+      if (hdrMerge->opcode() == spv::Op::OpLoopMerge) return;
       uint32_t hdrMergeId =
           hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
       if (contId == hdrMergeId) return;
@@ -277,11 +278,11 @@
     uint32_t merge_block_id = 0;
     (*bi)->ForEachInst([this, &modified, &merge_block_id](Instruction* inst) {
       if (IsLive(inst)) return;
-      if (inst->opcode() == SpvOpLabel) return;
+      if (inst->opcode() == spv::Op::OpLabel) return;
       // If dead instruction is selection merge, remember merge block
       // for new branch at end of block
-      if (inst->opcode() == SpvOpSelectionMerge ||
-          inst->opcode() == SpvOpLoopMerge)
+      if (inst->opcode() == spv::Op::OpSelectionMerge ||
+          inst->opcode() == spv::Op::OpLoopMerge)
         merge_block_id = inst->GetSingleWordInOperand(0);
       to_kill_.push_back(inst);
       modified = true;
@@ -295,19 +296,19 @@
       }
 
       auto merge_terminator = (*bi)->terminator();
-      if (merge_terminator->opcode() == SpvOpUnreachable) {
+      if (merge_terminator->opcode() == spv::Op::OpUnreachable) {
         // The merge was unreachable. This is undefined behaviour so just
         // return (or return an undef). Then mark the new return as live.
         auto func_ret_type_inst = get_def_use_mgr()->GetDef(func->type_id());
-        if (func_ret_type_inst->opcode() == SpvOpTypeVoid) {
-          merge_terminator->SetOpcode(SpvOpReturn);
+        if (func_ret_type_inst->opcode() == spv::Op::OpTypeVoid) {
+          merge_terminator->SetOpcode(spv::Op::OpReturn);
         } else {
           // Find an undef for the return value and make sure it gets kept by
           // the pass.
           auto undef_id = Type2Undef(func->type_id());
           auto undef = get_def_use_mgr()->GetDef(undef_id);
           live_insts_.Set(undef->unique_id());
-          merge_terminator->SetOpcode(SpvOpReturnValue);
+          merge_terminator->SetOpcode(spv::Op::OpReturnValue);
           merge_terminator->SetInOperands({{SPV_OPERAND_TYPE_ID, {undef_id}}});
           get_def_use_mgr()->AnalyzeInstUse(merge_terminator);
         }
@@ -338,23 +339,25 @@
   }
 }
 
+void AggressiveDCEPass::AddDebugScopeToWorkList(const Instruction* inst) {
+  auto scope = inst->GetDebugScope();
+  auto lex_scope_id = scope.GetLexicalScope();
+  if (lex_scope_id != kNoDebugScope)
+    AddToWorklist(get_def_use_mgr()->GetDef(lex_scope_id));
+  auto inlined_at_id = scope.GetInlinedAt();
+  if (inlined_at_id != kNoInlinedAt)
+    AddToWorklist(get_def_use_mgr()->GetDef(inlined_at_id));
+}
+
 void AggressiveDCEPass::AddDebugInstructionsToWorkList(
     const Instruction* inst) {
   for (auto& line_inst : inst->dbg_line_insts()) {
     if (line_inst.IsDebugLineInst()) {
       AddOperandsToWorkList(&line_inst);
     }
+    AddDebugScopeToWorkList(&line_inst);
   }
-
-  if (inst->GetDebugScope().GetLexicalScope() != kNoDebugScope) {
-    auto* scope =
-        get_def_use_mgr()->GetDef(inst->GetDebugScope().GetLexicalScope());
-    AddToWorklist(scope);
-  }
-  if (inst->GetDebugInlinedAt() != kNoInlinedAt) {
-    auto* inlined_at = get_def_use_mgr()->GetDef(inst->GetDebugInlinedAt());
-    AddToWorklist(inlined_at);
-  }
+  AddDebugScopeToWorkList(inst);
 }
 
 void AggressiveDCEPass::AddDecorationsToWorkList(const Instruction* inst) {
@@ -367,11 +370,11 @@
     // We only care about OpDecorateId instructions because the are the only
     // decorations that will reference an id that will have to be kept live
     // because of that use.
-    if (dec->opcode() != SpvOpDecorateId) {
+    if (dec->opcode() != spv::Op::OpDecorateId) {
       continue;
     }
-    if (dec->GetSingleWordInOperand(1) ==
-        SpvDecorationHlslCounterBufferGOOGLE) {
+    if (spv::Decoration(dec->GetSingleWordInOperand(1)) ==
+        spv::Decoration::HlslCounterBufferGOOGLE) {
       // These decorations should not force the use id to be live.  It will be
       // removed if either the target or the in operand are dead.
       continue;
@@ -389,7 +392,7 @@
 }
 
 std::vector<uint32_t> AggressiveDCEPass::GetLoadedVariables(Instruction* inst) {
-  if (inst->opcode() == SpvOpFunctionCall) {
+  if (inst->opcode() == spv::Op::OpFunctionCall) {
     return GetLoadedVariablesFromFunctionCall(inst);
   }
   uint32_t var_id = GetLoadedVariableFromNonFunctionCalls(inst);
@@ -407,11 +410,11 @@
   }
 
   switch (inst->opcode()) {
-    case SpvOpLoad:
-    case SpvOpImageTexelPointer:
+    case spv::Op::OpLoad:
+    case spv::Op::OpImageTexelPointer:
       return GetVariableId(inst->GetSingleWordInOperand(kLoadSourceAddrInIdx));
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       return GetVariableId(
           inst->GetSingleWordInOperand(kCopyMemorySourceAddrInIdx));
     default:
@@ -434,7 +437,7 @@
 
 std::vector<uint32_t> AggressiveDCEPass::GetLoadedVariablesFromFunctionCall(
     const Instruction* inst) {
-  assert(inst->opcode() == SpvOpFunctionCall);
+  assert(inst->opcode() == spv::Op::OpFunctionCall);
   std::vector<uint32_t> live_variables;
   inst->ForEachInId([this, &live_variables](const uint32_t* operand_id) {
     if (!IsPtr(*operand_id)) return;
@@ -479,7 +482,7 @@
   // the loop, so the loop construct must be live.  We exclude the label because
   // it does not matter how many times it is executed.  This could be extended
   // to more instructions, but we will need it for now.
-  if (inst->opcode() != SpvOpLabel)
+  if (inst->opcode() != spv::Op::OpLabel)
     MarkLoopConstructAsLiveIfLoopHeader(basic_block);
 
   Instruction* next_branch_inst = GetBranchForNextHeader(basic_block);
@@ -489,8 +492,8 @@
     AddToWorklist(mergeInst);
   }
 
-  if (inst->opcode() == SpvOpLoopMerge ||
-      inst->opcode() == SpvOpSelectionMerge) {
+  if (inst->opcode() == spv::Op::OpLoopMerge ||
+      inst->opcode() == spv::Op::OpSelectionMerge) {
     AddBreaksAndContinuesToWorklist(inst);
   }
 }
@@ -527,27 +530,27 @@
   // cleaned up.
   for (auto& bi : structured_order) {
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
-      SpvOp op = ii->opcode();
+      spv::Op op = ii->opcode();
       if (ii->IsBranch()) {
         continue;
       }
       switch (op) {
-        case SpvOpStore: {
+        case spv::Op::OpStore: {
           uint32_t var_id = 0;
           (void)GetPtr(&*ii, &var_id);
           if (!IsLocalVar(var_id, func)) AddToWorklist(&*ii);
         } break;
-        case SpvOpCopyMemory:
-        case SpvOpCopyMemorySized: {
+        case spv::Op::OpCopyMemory:
+        case spv::Op::OpCopyMemorySized: {
           uint32_t var_id = 0;
           uint32_t target_addr_id =
               ii->GetSingleWordInOperand(kCopyMemoryTargetAddrInIdx);
           (void)GetPtr(target_addr_id, &var_id);
           if (!IsLocalVar(var_id, func)) AddToWorklist(&*ii);
         } break;
-        case SpvOpLoopMerge:
-        case SpvOpSelectionMerge:
-        case SpvOpUnreachable:
+        case spv::Op::OpLoopMerge:
+        case spv::Op::OpSelectionMerge:
+        case spv::Op::OpUnreachable:
           break;
         default: {
           // Function calls, atomics, function params, function returns, etc.
@@ -577,7 +580,7 @@
         auto storage_class = var->GetSingleWordInOperand(0u);
         // Vulkan support outputs without an associated input, but not inputs
         // without an associated output.
-        if (storage_class == SpvStorageClassOutput) {
+        if (spv::StorageClass(storage_class) == spv::StorageClass::Output) {
           AddToWorklist(var);
         }
       }
@@ -586,24 +589,29 @@
     }
   }
   for (auto& anno : get_module()->annotations()) {
-    if (anno.opcode() == SpvOpDecorate) {
+    if (anno.opcode() == spv::Op::OpDecorate) {
       // Keep workgroup size.
-      if (anno.GetSingleWordInOperand(1u) == SpvDecorationBuiltIn &&
-          anno.GetSingleWordInOperand(2u) == SpvBuiltInWorkgroupSize) {
+      if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+              spv::Decoration::BuiltIn &&
+          spv::BuiltIn(anno.GetSingleWordInOperand(2u)) ==
+              spv::BuiltIn::WorkgroupSize) {
         AddToWorklist(&anno);
       }
 
       if (context()->preserve_bindings()) {
         // Keep all bindings.
-        if ((anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet) ||
-            (anno.GetSingleWordInOperand(1u) == SpvDecorationBinding)) {
+        if ((spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+             spv::Decoration::DescriptorSet) ||
+            (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+             spv::Decoration::Binding)) {
           AddToWorklist(&anno);
         }
       }
 
       if (context()->preserve_spec_constants()) {
         // Keep all specialization constant instructions
-        if (anno.GetSingleWordInOperand(1u) == SpvDecorationSpecId) {
+        if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+            spv::Decoration::SpecId) {
           AddToWorklist(&anno);
         }
       }
@@ -622,7 +630,7 @@
     debug_global_seen = true;
     dbg.ForEachInId([this](const uint32_t* iid) {
       Instruction* in_inst = get_def_use_mgr()->GetDef(*iid);
-      if (in_inst->opcode() == SpvOpVariable) return;
+      if (in_inst->opcode() == spv::Op::OpVariable) return;
       AddToWorklist(in_inst);
     });
   }
@@ -630,24 +638,34 @@
     auto dbg_none = context()->get_debug_info_mgr()->GetDebugInfoNone();
     AddToWorklist(dbg_none);
   }
+
+  // Add top level DebugInfo to worklist
+  for (auto& dbg : get_module()->ext_inst_debuginfo()) {
+    auto op = dbg.GetShader100DebugOpcode();
+    if (op == NonSemanticShaderDebugInfo100DebugCompilationUnit ||
+        op == NonSemanticShaderDebugInfo100DebugEntryPoint ||
+        op == NonSemanticShaderDebugInfo100DebugSourceContinued) {
+      AddToWorklist(&dbg);
+    }
+  }
 }
 
 Pass::Status AggressiveDCEPass::ProcessImpl() {
   // Current functionality assumes shader capability
   // TODO(greg-lunarg): Handle additional capabilities
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return Status::SuccessWithoutChange;
 
   // Current functionality assumes relaxed logical addressing (see
   // instruction.h)
   // TODO(greg-lunarg): Handle non-logical addressing
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
     return Status::SuccessWithoutChange;
 
   // The variable pointer extension is no longer needed to use the capability,
   // so we have to look for the capability.
   if (context()->get_feature_mgr()->HasCapability(
-          SpvCapabilityVariablePointersStorageBuffer))
+          spv::Capability::VariablePointersStorageBuffer))
     return Status::SuccessWithoutChange;
 
   // If any extensions in the module are not explicitly supported,
@@ -731,7 +749,7 @@
   bool modified = false;
   Instruction* instruction = &*get_module()->debug2_begin();
   while (instruction) {
-    if (instruction->opcode() != SpvOpName) {
+    if (instruction->opcode() != spv::Op::OpName) {
       instruction = instruction->NextNode();
       continue;
     }
@@ -752,22 +770,22 @@
   std::sort(annotations.begin(), annotations.end(), DecorationLess());
   for (auto annotation : annotations) {
     switch (annotation->opcode()) {
-      case SpvOpDecorate:
-      case SpvOpMemberDecorate:
-      case SpvOpDecorateStringGOOGLE:
-      case SpvOpMemberDecorateStringGOOGLE:
+      case spv::Op::OpDecorate:
+      case spv::Op::OpMemberDecorate:
+      case spv::Op::OpDecorateStringGOOGLE:
+      case spv::Op::OpMemberDecorateStringGOOGLE:
         if (IsTargetDead(annotation)) {
           context()->KillInst(annotation);
           modified = true;
         }
         break;
-      case SpvOpDecorateId:
+      case spv::Op::OpDecorateId:
         if (IsTargetDead(annotation)) {
           context()->KillInst(annotation);
           modified = true;
         } else {
-          if (annotation->GetSingleWordInOperand(1) ==
-              SpvDecorationHlslCounterBufferGOOGLE) {
+          if (spv::Decoration(annotation->GetSingleWordInOperand(1)) ==
+              spv::Decoration::HlslCounterBufferGOOGLE) {
             // HlslCounterBuffer will reference an id other than the target.
             // If that id is dead, then the decoration can be removed as well.
             uint32_t counter_buffer_id = annotation->GetSingleWordInOperand(2);
@@ -780,7 +798,7 @@
           }
         }
         break;
-      case SpvOpGroupDecorate: {
+      case spv::Op::OpGroupDecorate: {
         // Go through the targets of this group decorate. Remove each dead
         // target. If all targets are dead, remove this decoration.
         bool dead = true;
@@ -806,7 +824,7 @@
         }
         break;
       }
-      case SpvOpGroupMemberDecorate: {
+      case spv::Op::OpGroupMemberDecorate: {
         // Go through the targets of this group member decorate. Remove each
         // dead target (and member index). If all targets are dead, remove this
         // decoration.
@@ -834,7 +852,7 @@
         }
         break;
       }
-      case SpvOpDecorationGroup:
+      case spv::Op::OpDecorationGroup:
         // By the time we hit decoration groups we've checked everything that
         // can target them. So if they have no uses they must be dead.
         if (get_def_use_mgr()->NumUsers(annotation) == 0) {
@@ -875,7 +893,7 @@
       // this live as it does not have a result id. This is a little too
       // conservative since it is not known if the structure type that needed
       // it is still live. TODO(greg-lunarg): Only save if needed.
-      if (val.opcode() == SpvOpTypeForwardPointer) {
+      if (val.opcode() == spv::Op::OpTypeForwardPointer) {
         uint32_t ptr_ty_id = val.GetSingleWordInOperand(0);
         Instruction* ptr_ty_inst = get_def_use_mgr()->GetDef(ptr_ty_id);
         if (IsLive(ptr_ty_inst)) continue;
@@ -1071,8 +1089,9 @@
 }
 
 bool AggressiveDCEPass::HasCall(Function* func) {
-  return !func->WhileEachInst(
-      [](Instruction* inst) { return inst->opcode() != SpvOpFunctionCall; });
+  return !func->WhileEachInst([](Instruction* inst) {
+    return inst->opcode() != spv::Op::OpFunctionCall;
+  });
 }
 
 void AggressiveDCEPass::MarkFirstBlockAsLive(Function* func) {
diff --git a/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.h b/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.h
index 1b3fd1e..99c4739 100644
--- a/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/aggressive_dead_code_elim_pass.h
@@ -65,7 +65,7 @@
 
   // Return true if |varId| is a variable of |storageClass|. |varId| must either
   // be 0 or the result of an instruction.
-  bool IsVarOfStorage(uint32_t varId, uint32_t storageClass);
+  bool IsVarOfStorage(uint32_t varId, spv::StorageClass storageClass);
 
   // Return true if the instance of the variable |varId| can only be access in
   // |func|.  For example, a function scope variable, or a private variable
@@ -178,6 +178,9 @@
   // Adds all decorations of |inst| to the work list.
   void AddDecorationsToWorkList(const Instruction* inst);
 
+  // Adds DebugScope instruction associated with |inst| to the work list.
+  void AddDebugScopeToWorkList(const Instruction* inst);
+
   // Adds all debug instruction associated with |inst| to the work list.
   void AddDebugInstructionsToWorkList(const Instruction* inst);
 
diff --git a/third_party/SPIRV-Tools/source/opt/amd_ext_to_khr.cpp b/third_party/SPIRV-Tools/source/opt/amd_ext_to_khr.cpp
index dd9bafd..a314567 100644
--- a/third_party/SPIRV-Tools/source/opt/amd_ext_to_khr.cpp
+++ b/third_party/SPIRV-Tools/source/opt/amd_ext_to_khr.cpp
@@ -24,7 +24,6 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
 
 enum AmdShaderBallotExtOpcodes {
@@ -136,19 +135,19 @@
 // Returns a folding rule that will replace the opcode with |opcode| and add
 // the capabilities required.  The folding rule assumes it is folding an
 // OpGroup*NonUniformAMD instruction from the SPV_AMD_shader_ballot extension.
-template <SpvOp new_opcode>
+template <spv::Op new_opcode>
 bool ReplaceGroupNonuniformOperationOpCode(
     IRContext* ctx, Instruction* inst,
     const std::vector<const analysis::Constant*>&) {
   switch (new_opcode) {
-    case SpvOpGroupNonUniformIAdd:
-    case SpvOpGroupNonUniformFAdd:
-    case SpvOpGroupNonUniformUMin:
-    case SpvOpGroupNonUniformSMin:
-    case SpvOpGroupNonUniformFMin:
-    case SpvOpGroupNonUniformUMax:
-    case SpvOpGroupNonUniformSMax:
-    case SpvOpGroupNonUniformFMax:
+    case spv::Op::OpGroupNonUniformIAdd:
+    case spv::Op::OpGroupNonUniformFAdd:
+    case spv::Op::OpGroupNonUniformUMin:
+    case spv::Op::OpGroupNonUniformSMin:
+    case spv::Op::OpGroupNonUniformFMin:
+    case spv::Op::OpGroupNonUniformUMax:
+    case spv::Op::OpGroupNonUniformSMax:
+    case spv::Op::OpGroupNonUniformFMax:
       break;
     default:
       assert(
@@ -157,21 +156,21 @@
   }
 
   switch (inst->opcode()) {
-    case SpvOpGroupIAddNonUniformAMD:
-    case SpvOpGroupFAddNonUniformAMD:
-    case SpvOpGroupUMinNonUniformAMD:
-    case SpvOpGroupSMinNonUniformAMD:
-    case SpvOpGroupFMinNonUniformAMD:
-    case SpvOpGroupUMaxNonUniformAMD:
-    case SpvOpGroupSMaxNonUniformAMD:
-    case SpvOpGroupFMaxNonUniformAMD:
+    case spv::Op::OpGroupIAddNonUniformAMD:
+    case spv::Op::OpGroupFAddNonUniformAMD:
+    case spv::Op::OpGroupUMinNonUniformAMD:
+    case spv::Op::OpGroupSMinNonUniformAMD:
+    case spv::Op::OpGroupFMinNonUniformAMD:
+    case spv::Op::OpGroupUMaxNonUniformAMD:
+    case spv::Op::OpGroupSMaxNonUniformAMD:
+    case spv::Op::OpGroupFMaxNonUniformAMD:
       break;
     default:
       assert(false &&
              "Should be replacing a group non uniform arithmetic operation.");
   }
 
-  ctx->AddCapability(SpvCapabilityGroupNonUniformArithmetic);
+  ctx->AddCapability(spv::Capability::GroupNonUniformArithmetic);
   inst->SetOpcode(new_opcode);
   return true;
 }
@@ -215,8 +214,8 @@
   analysis::ConstantManager* const_mgr = ctx->get_constant_mgr();
 
   ctx->AddExtension("SPV_KHR_shader_ballot");
-  ctx->AddCapability(SpvCapabilityGroupNonUniformBallot);
-  ctx->AddCapability(SpvCapabilityGroupNonUniformShuffle);
+  ctx->AddCapability(spv::Capability::GroupNonUniformBallot);
+  ctx->AddCapability(spv::Capability::GroupNonUniformShuffle);
 
   InstructionBuilder ir_builder(
       ctx, inst,
@@ -226,8 +225,8 @@
   uint32_t offset_id = inst->GetSingleWordInOperand(3);
 
   // Get the subgroup invocation id.
-  uint32_t var_id =
-      ctx->GetBuiltinInputVarId(SpvBuiltInSubgroupLocalInvocationId);
+  uint32_t var_id = ctx->GetBuiltinInputVarId(
+      uint32_t(spv::BuiltIn::SubgroupLocalInvocationId));
   assert(var_id != 0 && "Could not get SubgroupLocalInvocationId variable.");
   Instruction* var_inst = ctx->get_def_use_mgr()->GetDef(var_id);
   Instruction* var_ptr_type =
@@ -239,35 +238,38 @@
   uint32_t quad_mask = ir_builder.GetUintConstantId(3);
 
   // This gives the offset in the group of 4 of this invocation.
-  Instruction* quad_idx = ir_builder.AddBinaryOp(uint_type_id, SpvOpBitwiseAnd,
-                                                 id->result_id(), quad_mask);
+  Instruction* quad_idx = ir_builder.AddBinaryOp(
+      uint_type_id, spv::Op::OpBitwiseAnd, id->result_id(), quad_mask);
 
   // Get the invocation id of the first invocation in the group of 4.
-  Instruction* quad_ldr = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpBitwiseXor, id->result_id(), quad_idx->result_id());
+  Instruction* quad_ldr =
+      ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpBitwiseXor,
+                             id->result_id(), quad_idx->result_id());
 
   // Get the offset of the target invocation from the offset vector.
   Instruction* my_offset =
-      ir_builder.AddBinaryOp(uint_type_id, SpvOpVectorExtractDynamic, offset_id,
-                             quad_idx->result_id());
+      ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpVectorExtractDynamic,
+                             offset_id, quad_idx->result_id());
 
   // Determine the index of the invocation to read from.
-  Instruction* target_inv = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpIAdd, quad_ldr->result_id(), my_offset->result_id());
+  Instruction* target_inv =
+      ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpIAdd,
+                             quad_ldr->result_id(), my_offset->result_id());
 
   // Do the group operations
   uint32_t uint_max_id = ir_builder.GetUintConstantId(0xFFFFFFFF);
-  uint32_t subgroup_scope = ir_builder.GetUintConstantId(SpvScopeSubgroup);
+  uint32_t subgroup_scope =
+      ir_builder.GetUintConstantId(uint32_t(spv::Scope::Subgroup));
   const auto* ballot_value_const = const_mgr->GetConstant(
       type_mgr->GetUIntVectorType(4),
       {uint_max_id, uint_max_id, uint_max_id, uint_max_id});
   Instruction* ballot_value =
       const_mgr->GetDefiningInstruction(ballot_value_const);
   Instruction* is_active = ir_builder.AddNaryOp(
-      type_mgr->GetBoolTypeId(), SpvOpGroupNonUniformBallotBitExtract,
+      type_mgr->GetBoolTypeId(), spv::Op::OpGroupNonUniformBallotBitExtract,
       {subgroup_scope, ballot_value->result_id(), target_inv->result_id()});
   Instruction* shuffle =
-      ir_builder.AddNaryOp(inst->type_id(), SpvOpGroupNonUniformShuffle,
+      ir_builder.AddNaryOp(inst->type_id(), spv::Op::OpGroupNonUniformShuffle,
                            {subgroup_scope, data_id, target_inv->result_id()});
 
   // Create the null constant to use in the select.
@@ -276,7 +278,7 @@
   Instruction* null_inst = const_mgr->GetDefiningInstruction(null);
 
   // Build the select.
-  inst->SetOpcode(SpvOpSelect);
+  inst->SetOpcode(spv::Op::OpSelect);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {is_active->result_id()}});
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {shuffle->result_id()}});
@@ -327,8 +329,8 @@
   analysis::DefUseManager* def_use_mgr = ctx->get_def_use_mgr();
   analysis::ConstantManager* const_mgr = ctx->get_constant_mgr();
 
-  ctx->AddCapability(SpvCapabilityGroupNonUniformBallot);
-  ctx->AddCapability(SpvCapabilityGroupNonUniformShuffle);
+  ctx->AddCapability(spv::Capability::GroupNonUniformBallot);
+  ctx->AddCapability(spv::Capability::GroupNonUniformShuffle);
 
   InstructionBuilder ir_builder(
       ctx, inst,
@@ -338,7 +340,7 @@
   uint32_t data_id = inst->GetSingleWordInOperand(2);
 
   Instruction* mask_inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(3));
-  assert(mask_inst->opcode() == SpvOpConstantComposite &&
+  assert(mask_inst->opcode() == spv::Op::OpConstantComposite &&
          "The mask is suppose to be a vector constant.");
   assert(mask_inst->NumInOperands() == 3 &&
          "The mask is suppose to have 3 components.");
@@ -348,8 +350,8 @@
   uint32_t uint_z = mask_inst->GetSingleWordInOperand(2);
 
   // Get the subgroup invocation id.
-  uint32_t var_id =
-      ctx->GetBuiltinInputVarId(SpvBuiltInSubgroupLocalInvocationId);
+  uint32_t var_id = ctx->GetBuiltinInputVarId(
+      uint32_t(spv::BuiltIn::SubgroupLocalInvocationId));
   ctx->AddExtension("SPV_KHR_shader_ballot");
   assert(var_id != 0 && "Could not get SubgroupLocalInvocationId variable.");
   Instruction* var_inst = ctx->get_def_use_mgr()->GetDef(var_id);
@@ -361,28 +363,30 @@
 
   // Do the bitwise operations.
   uint32_t mask_extended = ir_builder.GetUintConstantId(0xFFFFFFE0);
-  Instruction* and_mask = ir_builder.AddBinaryOp(uint_type_id, SpvOpBitwiseOr,
-                                                 uint_x, mask_extended);
-  Instruction* and_result = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpBitwiseAnd, id->result_id(), and_mask->result_id());
+  Instruction* and_mask = ir_builder.AddBinaryOp(
+      uint_type_id, spv::Op::OpBitwiseOr, uint_x, mask_extended);
+  Instruction* and_result =
+      ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpBitwiseAnd,
+                             id->result_id(), and_mask->result_id());
   Instruction* or_result = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpBitwiseOr, and_result->result_id(), uint_y);
+      uint_type_id, spv::Op::OpBitwiseOr, and_result->result_id(), uint_y);
   Instruction* target_inv = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpBitwiseXor, or_result->result_id(), uint_z);
+      uint_type_id, spv::Op::OpBitwiseXor, or_result->result_id(), uint_z);
 
   // Do the group operations
   uint32_t uint_max_id = ir_builder.GetUintConstantId(0xFFFFFFFF);
-  uint32_t subgroup_scope = ir_builder.GetUintConstantId(SpvScopeSubgroup);
+  uint32_t subgroup_scope =
+      ir_builder.GetUintConstantId(uint32_t(spv::Scope::Subgroup));
   const auto* ballot_value_const = const_mgr->GetConstant(
       type_mgr->GetUIntVectorType(4),
       {uint_max_id, uint_max_id, uint_max_id, uint_max_id});
   Instruction* ballot_value =
       const_mgr->GetDefiningInstruction(ballot_value_const);
   Instruction* is_active = ir_builder.AddNaryOp(
-      type_mgr->GetBoolTypeId(), SpvOpGroupNonUniformBallotBitExtract,
+      type_mgr->GetBoolTypeId(), spv::Op::OpGroupNonUniformBallotBitExtract,
       {subgroup_scope, ballot_value->result_id(), target_inv->result_id()});
   Instruction* shuffle =
-      ir_builder.AddNaryOp(inst->type_id(), SpvOpGroupNonUniformShuffle,
+      ir_builder.AddNaryOp(inst->type_id(), spv::Op::OpGroupNonUniformShuffle,
                            {subgroup_scope, data_id, target_inv->result_id()});
 
   // Create the null constant to use in the select.
@@ -391,7 +395,7 @@
   Instruction* null_inst = const_mgr->GetDefiningInstruction(null);
 
   // Build the select.
-  inst->SetOpcode(SpvOpSelect);
+  inst->SetOpcode(spv::Op::OpSelect);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {is_active->result_id()}});
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {shuffle->result_id()}});
@@ -420,9 +424,9 @@
 // Also adding the capabilities and builtins that are needed.
 bool ReplaceWriteInvocation(IRContext* ctx, Instruction* inst,
                             const std::vector<const analysis::Constant*>&) {
-  uint32_t var_id =
-      ctx->GetBuiltinInputVarId(SpvBuiltInSubgroupLocalInvocationId);
-  ctx->AddCapability(SpvCapabilitySubgroupBallotKHR);
+  uint32_t var_id = ctx->GetBuiltinInputVarId(
+      uint32_t(spv::BuiltIn::SubgroupLocalInvocationId));
+  ctx->AddCapability(spv::Capability::SubgroupBallotKHR);
   ctx->AddExtension("SPV_KHR_shader_ballot");
   assert(var_id != 0 && "Could not get SubgroupLocalInvocationId variable.");
   Instruction* var_inst = ctx->get_def_use_mgr()->GetDef(var_id);
@@ -437,11 +441,11 @@
   analysis::Bool bool_type;
   uint32_t bool_type_id = ctx->get_type_mgr()->GetTypeInstruction(&bool_type);
   Instruction* cmp =
-      ir_builder.AddBinaryOp(bool_type_id, SpvOpIEqual, t->result_id(),
+      ir_builder.AddBinaryOp(bool_type_id, spv::Op::OpIEqual, t->result_id(),
                              inst->GetSingleWordInOperand(4));
 
   // Build a select.
-  inst->SetOpcode(SpvOpSelect);
+  inst->SetOpcode(spv::Op::OpSelect);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {cmp->result_id()}});
   new_operands.push_back(inst->GetInOperand(3));
@@ -479,14 +483,15 @@
   analysis::TypeManager* type_mgr = context->get_type_mgr();
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
 
-  uint32_t var_id = context->GetBuiltinInputVarId(SpvBuiltInSubgroupLtMask);
+  uint32_t var_id =
+      context->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::SubgroupLtMask));
   assert(var_id != 0 && "Could not get SubgroupLtMask variable.");
-  context->AddCapability(SpvCapabilityGroupNonUniformBallot);
+  context->AddCapability(spv::Capability::GroupNonUniformBallot);
   Instruction* var_inst = def_use_mgr->GetDef(var_id);
   Instruction* var_ptr_type = def_use_mgr->GetDef(var_inst->type_id());
   Instruction* var_type =
       def_use_mgr->GetDef(var_ptr_type->GetSingleWordInOperand(1));
-  assert(var_type->opcode() == SpvOpTypeVector &&
+  assert(var_type->opcode() == spv::Op::OpTypeVector &&
          "Variable is suppose to be a vector of 4 ints");
 
   // Get the type for the shuffle.
@@ -509,11 +514,12 @@
   Instruction* shuffle = ir_builder.AddVectorShuffle(
       shuffle_type_id, load->result_id(), load->result_id(), {0, 1});
   Instruction* bitcast = ir_builder.AddUnaryOp(
-      mask_inst->type_id(), SpvOpBitcast, shuffle->result_id());
-  Instruction* t = ir_builder.AddBinaryOp(mask_inst->type_id(), SpvOpBitwiseAnd,
-                                          bitcast->result_id(), mask_id);
+      mask_inst->type_id(), spv::Op::OpBitcast, shuffle->result_id());
+  Instruction* t =
+      ir_builder.AddBinaryOp(mask_inst->type_id(), spv::Op::OpBitwiseAnd,
+                             bitcast->result_id(), mask_id);
 
-  inst->SetOpcode(SpvOpBitCount);
+  inst->SetOpcode(spv::Op::OpBitCount);
   inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {t->result_id()}}});
   context->UpdateDefUse(inst);
   return true;
@@ -599,11 +605,11 @@
 
   // Negate the input values.
   Instruction* nx =
-      ir_builder.AddUnaryOp(float_type_id, SpvOpFNegate, x->result_id());
+      ir_builder.AddUnaryOp(float_type_id, spv::Op::OpFNegate, x->result_id());
   Instruction* ny =
-      ir_builder.AddUnaryOp(float_type_id, SpvOpFNegate, y->result_id());
+      ir_builder.AddUnaryOp(float_type_id, spv::Op::OpFNegate, y->result_id());
   Instruction* nz =
-      ir_builder.AddUnaryOp(float_type_id, SpvOpFNegate, z->result_id());
+      ir_builder.AddUnaryOp(float_type_id, spv::Op::OpFNegate, z->result_id());
 
   // Get the abolsute values of the inputs.
   Instruction* ax = ir_builder.AddNaryExtendedInstruction(
@@ -614,12 +620,12 @@
       float_type_id, glsl405_ext_inst_id, GLSLstd450FAbs, {z->result_id()});
 
   // Find which values are negative.  Used in later computations.
-  Instruction* is_z_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 z->result_id(), f0_const_id);
-  Instruction* is_y_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 y->result_id(), f0_const_id);
-  Instruction* is_x_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 x->result_id(), f0_const_id);
+  Instruction* is_z_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, z->result_id(), f0_const_id);
+  Instruction* is_y_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, y->result_id(), f0_const_id);
+  Instruction* is_x_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, x->result_id(), f0_const_id);
 
   // Compute cubema
   Instruction* amax_x_y = ir_builder.AddNaryExtendedInstruction(
@@ -628,19 +634,21 @@
   Instruction* amax = ir_builder.AddNaryExtendedInstruction(
       float_type_id, glsl405_ext_inst_id, GLSLstd450FMax,
       {az->result_id(), amax_x_y->result_id()});
-  Instruction* cubema = ir_builder.AddBinaryOp(float_type_id, SpvOpFMul,
+  Instruction* cubema = ir_builder.AddBinaryOp(float_type_id, spv::Op::OpFMul,
                                                f2_const_id, amax->result_id());
 
   // Do the comparisons needed for computing cubesc and cubetc.
   Instruction* is_z_max =
-      ir_builder.AddBinaryOp(bool_id, SpvOpFOrdGreaterThanEqual,
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
                              az->result_id(), amax_x_y->result_id());
-  Instruction* not_is_z_max =
-      ir_builder.AddUnaryOp(bool_id, SpvOpLogicalNot, is_z_max->result_id());
-  Instruction* y_gr_x = ir_builder.AddBinaryOp(
-      bool_id, SpvOpFOrdGreaterThanEqual, ay->result_id(), ax->result_id());
-  Instruction* is_y_max = ir_builder.AddBinaryOp(
-      bool_id, SpvOpLogicalAnd, not_is_z_max->result_id(), y_gr_x->result_id());
+  Instruction* not_is_z_max = ir_builder.AddUnaryOp(
+      bool_id, spv::Op::OpLogicalNot, is_z_max->result_id());
+  Instruction* y_gr_x =
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
+                             ay->result_id(), ax->result_id());
+  Instruction* is_y_max =
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpLogicalAnd,
+                             not_is_z_max->result_id(), y_gr_x->result_id());
 
   // Select the correct value for cubesc.
   Instruction* cubesc_case_1 = ir_builder.AddSelect(
@@ -667,10 +675,10 @@
   Instruction* denom = ir_builder.AddCompositeConstruct(
       v2_float_type_id, {cubema->result_id(), cubema->result_id()});
   Instruction* div = ir_builder.AddBinaryOp(
-      v2_float_type_id, SpvOpFDiv, cube->result_id(), denom->result_id());
+      v2_float_type_id, spv::Op::OpFDiv, cube->result_id(), denom->result_id());
 
   // Get the final result by adding 0.5 to |div|.
-  inst->SetOpcode(SpvOpFAdd);
+  inst->SetOpcode(spv::Op::OpFAdd);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {div->result_id()}});
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {vec_const_id}});
@@ -752,22 +760,23 @@
       float_type_id, glsl405_ext_inst_id, GLSLstd450FAbs, {z->result_id()});
 
   // Find which values are negative.  Used in later computations.
-  Instruction* is_z_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 z->result_id(), f0_const_id);
-  Instruction* is_y_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 y->result_id(), f0_const_id);
-  Instruction* is_x_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 x->result_id(), f0_const_id);
+  Instruction* is_z_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, z->result_id(), f0_const_id);
+  Instruction* is_y_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, y->result_id(), f0_const_id);
+  Instruction* is_x_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, x->result_id(), f0_const_id);
 
   // Find the max value.
   Instruction* amax_x_y = ir_builder.AddNaryExtendedInstruction(
       float_type_id, glsl405_ext_inst_id, GLSLstd450FMax,
       {ax->result_id(), ay->result_id()});
   Instruction* is_z_max =
-      ir_builder.AddBinaryOp(bool_id, SpvOpFOrdGreaterThanEqual,
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
                              az->result_id(), amax_x_y->result_id());
-  Instruction* y_gr_x = ir_builder.AddBinaryOp(
-      bool_id, SpvOpFOrdGreaterThanEqual, ay->result_id(), ax->result_id());
+  Instruction* y_gr_x =
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
+                             ay->result_id(), ax->result_id());
 
   // Get the value for each case.
   Instruction* case_z = ir_builder.AddSelect(
@@ -783,7 +792,7 @@
                            case_y->result_id(), case_x->result_id());
 
   // Get the final result by adding 0.5 to |div|.
-  inst->SetOpcode(SpvOpSelect);
+  inst->SetOpcode(spv::Op::OpSelect);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {is_z_max->result_id()}});
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {case_z->result_id()}});
@@ -813,11 +822,12 @@
       ctx, inst,
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
   ctx->AddExtension("SPV_KHR_shader_clock");
-  ctx->AddCapability(SpvCapabilityShaderClockKHR);
+  ctx->AddCapability(spv::Capability::ShaderClockKHR);
 
-  inst->SetOpcode(SpvOpReadClockKHR);
+  inst->SetOpcode(spv::Op::OpReadClockKHR);
   Instruction::OperandList args;
-  uint32_t subgroup_scope_id = ir_builder.GetUintConstantId(SpvScopeSubgroup);
+  uint32_t subgroup_scope_id =
+      ir_builder.GetUintConstantId(uint32_t(spv::Scope::Subgroup));
   args.push_back({SPV_OPERAND_TYPE_ID, {subgroup_scope_id}});
   inst->SetInOperands(std::move(args));
   ctx->UpdateDefUse(inst);
@@ -831,22 +841,22 @@
 
  protected:
   virtual void AddFoldingRules() override {
-    rules_[SpvOpGroupIAddNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformIAdd>);
-    rules_[SpvOpGroupFAddNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformFAdd>);
-    rules_[SpvOpGroupUMinNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformUMin>);
-    rules_[SpvOpGroupSMinNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformSMin>);
-    rules_[SpvOpGroupFMinNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformFMin>);
-    rules_[SpvOpGroupUMaxNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformUMax>);
-    rules_[SpvOpGroupSMaxNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformSMax>);
-    rules_[SpvOpGroupFMaxNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformFMax>);
+    rules_[spv::Op::OpGroupIAddNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformIAdd>);
+    rules_[spv::Op::OpGroupFAddNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformFAdd>);
+    rules_[spv::Op::OpGroupUMinNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformUMin>);
+    rules_[spv::Op::OpGroupSMinNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformSMin>);
+    rules_[spv::Op::OpGroupFMinNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformFMin>);
+    rules_[spv::Op::OpGroupUMaxNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformUMax>);
+    rules_[spv::Op::OpGroupSMaxNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformSMax>);
+    rules_[spv::Op::OpGroupFMaxNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformFMax>);
 
     uint32_t extension_id =
         context()->module()->GetExtInstImportId("SPV_AMD_shader_ballot");
@@ -934,7 +944,7 @@
 
   std::vector<Instruction*> to_be_killed;
   for (Instruction& inst : context()->module()->extensions()) {
-    if (inst.opcode() == SpvOpExtension) {
+    if (inst.opcode() == spv::Op::OpExtension) {
       if (ext_to_remove.count(inst.GetInOperand(0).AsString()) != 0) {
         to_be_killed.push_back(&inst);
       }
@@ -942,7 +952,7 @@
   }
 
   for (Instruction& inst : context()->ext_inst_imports()) {
-    if (inst.opcode() == SpvOpExtInstImport) {
+    if (inst.opcode() == spv::Op::OpExtInstImport) {
       if (ext_to_remove.count(inst.GetInOperand(0).AsString()) != 0) {
         to_be_killed.push_back(&inst);
       }
diff --git a/third_party/SPIRV-Tools/source/opt/analyze_live_input_pass.cpp b/third_party/SPIRV-Tools/source/opt/analyze_live_input_pass.cpp
new file mode 100644
index 0000000..529e684
--- /dev/null
+++ b/third_party/SPIRV-Tools/source/opt/analyze_live_input_pass.cpp
@@ -0,0 +1,45 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+// Copyright (c) 2022 LunarG Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "source/opt/analyze_live_input_pass.h"
+
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace opt {
+
+Pass::Status AnalyzeLiveInputPass::Process() {
+  // Current functionality assumes shader capability
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
+    return Status::SuccessWithoutChange;
+  Pass::Status status = DoLiveInputAnalysis();
+  return status;
+}
+
+Pass::Status AnalyzeLiveInputPass::DoLiveInputAnalysis() {
+  // Current functionality only supports frag, tesc, tese or geom shaders.
+  // Report failure for any other stage.
+  auto stage = context()->GetStage();
+  if (stage != spv::ExecutionModel::Fragment &&
+      stage != spv::ExecutionModel::TessellationControl &&
+      stage != spv::ExecutionModel::TessellationEvaluation &&
+      stage != spv::ExecutionModel::Geometry)
+    return Status::Failure;
+  context()->get_liveness_mgr()->GetLiveness(live_locs_, live_builtins_);
+  return Status::SuccessWithoutChange;
+}
+
+}  // namespace opt
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/analyze_live_input_pass.h b/third_party/SPIRV-Tools/source/opt/analyze_live_input_pass.h
new file mode 100644
index 0000000..ab292ef
--- /dev/null
+++ b/third_party/SPIRV-Tools/source/opt/analyze_live_input_pass.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+// Copyright (c) 2022 LunarG Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SOURCE_OPT_ANALYZE_LIVE_INPUT_H_
+#define SOURCE_OPT_ANALYZE_LIVE_INPUT_H_
+
+#include <unordered_set>
+
+#include "source/opt/pass.h"
+
+namespace spvtools {
+namespace opt {
+
+// See optimizer.hpp for documentation.
+class AnalyzeLiveInputPass : public Pass {
+ public:
+  explicit AnalyzeLiveInputPass(std::unordered_set<uint32_t>* live_locs,
+                                std::unordered_set<uint32_t>* live_builtins)
+      : live_locs_(live_locs), live_builtins_(live_builtins) {}
+
+  const char* name() const override { return "analyze-live-input"; }
+  Status Process() override;
+
+  // Return the mask of preserved Analyses.
+  IRContext::Analysis GetPreservedAnalyses() override {
+    return IRContext::kAnalysisDefUse |
+           IRContext::kAnalysisInstrToBlockMapping |
+           IRContext::kAnalysisCombinators | IRContext::kAnalysisCFG |
+           IRContext::kAnalysisDominatorAnalysis |
+           IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
+           IRContext::kAnalysisConstants | IRContext::kAnalysisTypes;
+  }
+
+ private:
+  // Do live input analysis
+  Status DoLiveInputAnalysis();
+
+  std::unordered_set<uint32_t>* live_locs_;
+  std::unordered_set<uint32_t>* live_builtins_;
+};
+
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // SOURCE_OPT_ANALYZE_LIVE_INPUT_H_
diff --git a/third_party/SPIRV-Tools/source/opt/basic_block.cpp b/third_party/SPIRV-Tools/source/opt/basic_block.cpp
index e82a744..d12178e 100644
--- a/third_party/SPIRV-Tools/source/opt/basic_block.cpp
+++ b/third_party/SPIRV-Tools/source/opt/basic_block.cpp
@@ -25,11 +25,9 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-const uint32_t kLoopMergeContinueBlockIdInIdx = 1;
-const uint32_t kLoopMergeMergeBlockIdInIdx = 0;
-const uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
-
+constexpr uint32_t kLoopMergeContinueBlockIdInIdx = 1;
+constexpr uint32_t kLoopMergeMergeBlockIdInIdx = 0;
+constexpr uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
 }  // namespace
 
 BasicBlock* BasicBlock::Clone(IRContext* context) const {
@@ -58,7 +56,7 @@
   if (iter != cbegin()) {
     --iter;
     const auto opcode = iter->opcode();
-    if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
+    if (opcode == spv::Op::OpLoopMerge || opcode == spv::Op::OpSelectionMerge) {
       result = &*iter;
     }
   }
@@ -73,7 +71,7 @@
   if (iter != begin()) {
     --iter;
     const auto opcode = iter->opcode();
-    if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
+    if (opcode == spv::Op::OpLoopMerge || opcode == spv::Op::OpSelectionMerge) {
       result = &*iter;
     }
   }
@@ -82,7 +80,7 @@
 
 const Instruction* BasicBlock::GetLoopMergeInst() const {
   if (auto* merge = GetMergeInst()) {
-    if (merge->opcode() == SpvOpLoopMerge) {
+    if (merge->opcode() == spv::Op::OpLoopMerge) {
       return merge;
     }
   }
@@ -91,7 +89,7 @@
 
 Instruction* BasicBlock::GetLoopMergeInst() {
   if (auto* merge = GetMergeInst()) {
-    if (merge->opcode() == SpvOpLoopMerge) {
+    if (merge->opcode() == spv::Op::OpLoopMerge) {
       return merge;
     }
   }
@@ -100,7 +98,7 @@
 
 void BasicBlock::KillAllInsts(bool killLabel) {
   ForEachInst([killLabel](Instruction* ip) {
-    if (killLabel || ip->opcode() != SpvOpLabel) {
+    if (killLabel || ip->opcode() != spv::Op::OpLabel) {
       ip->context()->KillInst(ip);
     }
   });
@@ -118,10 +116,10 @@
     const std::function<bool(const uint32_t)>& f) const {
   const auto br = &insts_.back();
   switch (br->opcode()) {
-    case SpvOpBranch:
+    case spv::Op::OpBranch:
       return f(br->GetOperand(0).words[0]);
-    case SpvOpBranchConditional:
-    case SpvOpSwitch: {
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch: {
       bool is_first = true;
       return br->WhileEachInId([&is_first, &f](const uint32_t* idp) {
         if (!is_first) return f(*idp);
@@ -138,13 +136,13 @@
     const std::function<void(uint32_t*)>& f) {
   auto br = &insts_.back();
   switch (br->opcode()) {
-    case SpvOpBranch: {
+    case spv::Op::OpBranch: {
       uint32_t tmp_id = br->GetOperand(0).words[0];
       f(&tmp_id);
       if (tmp_id != br->GetOperand(0).words[0]) br->SetOperand(0, {tmp_id});
     } break;
-    case SpvOpBranchConditional:
-    case SpvOpSwitch: {
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch: {
       bool is_first = true;
       br->ForEachInId([&is_first, &f](uint32_t* idp) {
         if (!is_first) f(idp);
@@ -171,7 +169,8 @@
   --ii;
   if (ii == insts_.begin()) return;
   --ii;
-  if (ii->opcode() == SpvOpSelectionMerge || ii->opcode() == SpvOpLoopMerge) {
+  if (ii->opcode() == spv::Op::OpSelectionMerge ||
+      ii->opcode() == spv::Op::OpLoopMerge) {
     ii->ForEachInId([&f](const uint32_t* idp) { f(*idp); });
   }
 }
@@ -182,9 +181,9 @@
   uint32_t mbid = 0;
   if (merge_ii != cbegin()) {
     --merge_ii;
-    if (merge_ii->opcode() == SpvOpLoopMerge) {
+    if (merge_ii->opcode() == spv::Op::OpLoopMerge) {
       mbid = merge_ii->GetSingleWordInOperand(kLoopMergeMergeBlockIdInIdx);
-    } else if (merge_ii->opcode() == SpvOpSelectionMerge) {
+    } else if (merge_ii->opcode() == spv::Op::OpSelectionMerge) {
       mbid = merge_ii->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
     }
   }
@@ -204,7 +203,7 @@
   uint32_t cbid = 0;
   if (merge_ii != cbegin()) {
     --merge_ii;
-    if (merge_ii->opcode() == SpvOpLoopMerge) {
+    if (merge_ii->opcode() == spv::Op::OpLoopMerge) {
       cbid = merge_ii->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx);
     }
   }
@@ -241,9 +240,9 @@
                                         iterator iter) {
   assert(!insts_.empty());
 
-  std::unique_ptr<BasicBlock> new_block_temp =
-      MakeUnique<BasicBlock>(MakeUnique<Instruction>(
-          context, SpvOpLabel, 0, label_id, std::initializer_list<Operand>{}));
+  std::unique_ptr<BasicBlock> new_block_temp = MakeUnique<BasicBlock>(
+      MakeUnique<Instruction>(context, spv::Op::OpLabel, 0, label_id,
+                              std::initializer_list<Operand>{}));
   BasicBlock* new_block = new_block_temp.get();
   function_->InsertBasicBlockAfter(std::move(new_block_temp), this);
 
diff --git a/third_party/SPIRV-Tools/source/opt/basic_block.h b/third_party/SPIRV-Tools/source/opt/basic_block.h
index dd3b2e2..24d5fce 100644
--- a/third_party/SPIRV-Tools/source/opt/basic_block.h
+++ b/third_party/SPIRV-Tools/source/opt/basic_block.h
@@ -319,7 +319,7 @@
   Instruction* inst = &insts_.front();
   while (inst != nullptr) {
     Instruction* next_instruction = inst->NextNode();
-    if (inst->opcode() != SpvOpPhi) break;
+    if (inst->opcode() != spv::Op::OpPhi) break;
     if (!inst->WhileEachInst(f, run_on_debug_line_insts)) return false;
     inst = next_instruction;
   }
diff --git a/third_party/SPIRV-Tools/source/opt/block_merge_util.cpp b/third_party/SPIRV-Tools/source/opt/block_merge_util.cpp
index 8ae8020..a893ab5 100644
--- a/third_party/SPIRV-Tools/source/opt/block_merge_util.cpp
+++ b/third_party/SPIRV-Tools/source/opt/block_merge_util.cpp
@@ -20,7 +20,6 @@
 namespace spvtools {
 namespace opt {
 namespace blockmergeutil {
-
 namespace {
 
 // Returns true if |block| contains a merge instruction.
@@ -34,14 +33,15 @@
 
 // Returns true if |id| is the merge target of a merge instruction.
 bool IsMerge(IRContext* context, uint32_t id) {
-  return !context->get_def_use_mgr()->WhileEachUse(id, [](Instruction* user,
-                                                          uint32_t index) {
-    SpvOp op = user->opcode();
-    if ((op == SpvOpLoopMerge || op == SpvOpSelectionMerge) && index == 0u) {
-      return false;
-    }
-    return true;
-  });
+  return !context->get_def_use_mgr()->WhileEachUse(
+      id, [](Instruction* user, uint32_t index) {
+        spv::Op op = user->opcode();
+        if ((op == spv::Op::OpLoopMerge || op == spv::Op::OpSelectionMerge) &&
+            index == 0u) {
+          return false;
+        }
+        return true;
+      });
 }
 
 // Returns true if |block| is the merge target of a merge instruction.
@@ -53,8 +53,8 @@
 bool IsContinue(IRContext* context, uint32_t id) {
   return !context->get_def_use_mgr()->WhileEachUse(
       id, [](Instruction* user, uint32_t index) {
-        SpvOp op = user->opcode();
-        if (op == SpvOpLoopMerge && index == 1u) {
+        spv::Op op = user->opcode();
+        if (op == spv::Op::OpLoopMerge && index == 1u) {
           return false;
         }
         return true;
@@ -82,7 +82,7 @@
   auto ii = block->end();
   --ii;
   Instruction* br = &*ii;
-  if (br->opcode() != SpvOpBranch) {
+  if (br->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
@@ -119,12 +119,33 @@
     // The merge must be a loop merge because a selection merge cannot be
     // followed by an unconditional branch.
     BasicBlock* succ_block = context->get_instr_block(lab_id);
-    SpvOp succ_term_op = succ_block->terminator()->opcode();
-    assert(merge_inst->opcode() == SpvOpLoopMerge);
-    if (succ_term_op != SpvOpBranch && succ_term_op != SpvOpBranchConditional) {
+    spv::Op succ_term_op = succ_block->terminator()->opcode();
+    assert(merge_inst->opcode() == spv::Op::OpLoopMerge);
+    if (succ_term_op != spv::Op::OpBranch &&
+        succ_term_op != spv::Op::OpBranchConditional) {
       return false;
     }
   }
+
+  if (succ_is_merge || IsContinue(context, lab_id)) {
+    auto* struct_cfg = context->GetStructuredCFGAnalysis();
+    auto switch_block_id = struct_cfg->ContainingSwitch(block->id());
+    if (switch_block_id) {
+      auto switch_merge_id = struct_cfg->SwitchMergeBlock(switch_block_id);
+      const auto* switch_inst =
+          &*block->GetParent()->FindBlock(switch_block_id)->tail();
+      for (uint32_t i = 1; i < switch_inst->NumInOperands(); i += 2) {
+        auto target_id = switch_inst->GetSingleWordInOperand(i);
+        if (target_id == block->id() && target_id != switch_merge_id) {
+          // Case constructs must be structurally dominated by the OpSwitch.
+          // Since the successor is the merge/continue for another construct,
+          // merging the blocks would break that requirement.
+          return false;
+        }
+      }
+    }
+  }
+
   return true;
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/ccp_pass.cpp b/third_party/SPIRV-Tools/source/opt/ccp_pass.cpp
index 5f85502..63627a2 100644
--- a/third_party/SPIRV-Tools/source/opt/ccp_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/ccp_pass.cpp
@@ -29,14 +29,11 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
-
 // This SSA id is never defined nor referenced in the IR.  It is a special ID
 // which represents varying values.  When an ID is found to have a varying
 // value, its entry in the |values_| table maps to kVaryingSSAId.
-const uint32_t kVaryingSSAId = std::numeric_limits<uint32_t>::max();
-
+constexpr uint32_t kVaryingSSAId = std::numeric_limits<uint32_t>::max();
 }  // namespace
 
 bool CCPPass::IsVaryingValue(uint32_t id) const { return id == kVaryingSSAId; }
@@ -136,7 +133,7 @@
 
   // If this is a copy operation, and the RHS is a known constant, assign its
   // value to the LHS.
-  if (instr->opcode() == SpvOpCopyObject) {
+  if (instr->opcode() == spv::Op::OpCopyObject) {
     uint32_t rhs_id = instr->GetSingleWordInOperand(0);
     auto it = values_.find(rhs_id);
     if (it != values_.end()) {
@@ -211,10 +208,10 @@
 
   *dest_bb = nullptr;
   uint32_t dest_label = 0;
-  if (instr->opcode() == SpvOpBranch) {
+  if (instr->opcode() == spv::Op::OpBranch) {
     // An unconditional jump always goes to its unique destination.
     dest_label = instr->GetSingleWordInOperand(0);
-  } else if (instr->opcode() == SpvOpBranchConditional) {
+  } else if (instr->opcode() == spv::Op::OpBranchConditional) {
     // For a conditional branch, determine whether the predicate selector has a
     // known value in |values_|.  If it does, set the destination block
     // according to the selector's boolean value.
@@ -243,7 +240,7 @@
     // For an OpSwitch, extract the value taken by the switch selector and check
     // which of the target literals it matches.  The branch associated with that
     // literal is the taken branch.
-    assert(instr->opcode() == SpvOpSwitch);
+    assert(instr->opcode() == spv::Op::OpSwitch);
     if (instr->GetOperand(0).words.size() != 1) {
       // If the selector is wider than 32-bits, return varying. TODO(dnovillo):
       // Add support for wider constants.
@@ -290,7 +287,7 @@
 SSAPropagator::PropStatus CCPPass::VisitInstruction(Instruction* instr,
                                                     BasicBlock** dest_bb) {
   *dest_bb = nullptr;
-  if (instr->opcode() == SpvOpPhi) {
+  if (instr->opcode() == spv::Op::OpPhi) {
     return VisitPhi(instr);
   } else if (instr->IsBranch()) {
     return VisitBranch(instr, dest_bb);
diff --git a/third_party/SPIRV-Tools/source/opt/cfg.cpp b/third_party/SPIRV-Tools/source/opt/cfg.cpp
index 66b1aed..4c4bb25 100644
--- a/third_party/SPIRV-Tools/source/opt/cfg.cpp
+++ b/third_party/SPIRV-Tools/source/opt/cfg.cpp
@@ -29,16 +29,16 @@
 using cbb_ptr = const opt::BasicBlock*;
 
 // Universal Limit of ResultID + 1
-const int kMaxResultId = 0x400000;
+constexpr int kMaxResultId = 0x400000;
 
 }  // namespace
 
 CFG::CFG(Module* module)
     : module_(module),
       pseudo_entry_block_(std::unique_ptr<Instruction>(
-          new Instruction(module->context(), SpvOpLabel, 0, 0, {}))),
+          new Instruction(module->context(), spv::Op::OpLabel, 0, 0, {}))),
       pseudo_exit_block_(std::unique_ptr<Instruction>(new Instruction(
-          module->context(), SpvOpLabel, 0, kMaxResultId, {}))) {
+          module->context(), spv::Op::OpLabel, 0, kMaxResultId, {}))) {
   for (auto& fn : *module) {
     for (auto& blk : fn) {
       RegisterBlock(&blk);
@@ -81,13 +81,12 @@
                                  BasicBlock* end,
                                  std::list<BasicBlock*>* order) {
   assert(module_->context()->get_feature_mgr()->HasCapability(
-             SpvCapabilityShader) &&
+             spv::Capability::Shader) &&
          "This only works on structured control flow");
 
   // Compute structured successors and do DFS.
   ComputeStructuredSuccessors(func);
   auto ignore_block = [](cbb_ptr) {};
-  auto ignore_edge = [](cbb_ptr, cbb_ptr) {};
   auto terminal = [end](cbb_ptr bb) { return bb == end; };
 
   auto get_structured_successors = [this](const BasicBlock* b) {
@@ -100,8 +99,7 @@
     order->push_front(const_cast<BasicBlock*>(b));
   };
   CFA<BasicBlock>::DepthFirstTraversal(root, get_structured_successors,
-                                       ignore_block, post_order, ignore_edge,
-                                       terminal);
+                                       ignore_block, post_order, terminal);
 }
 
 void CFG::ForEachBlockInPostOrder(BasicBlock* bb,
@@ -230,7 +228,7 @@
   // Create the new header bb basic bb.
   // Leave the phi instructions behind.
   auto iter = bb->begin();
-  while (iter->opcode() == SpvOpPhi) {
+  while (iter->opcode() == spv::Op::OpPhi) {
     ++iter;
   }
 
@@ -306,7 +304,7 @@
       context, bb,
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
   bb->AddInstruction(
-      MakeUnique<Instruction>(context, SpvOpBranch, 0, 0,
+      MakeUnique<Instruction>(context, spv::Op::OpBranch, 0, 0,
                               std::initializer_list<Operand>{
                                   {SPV_OPERAND_TYPE_ID, {new_header->id()}}}));
   context->AnalyzeUses(bb->terminator());
diff --git a/third_party/SPIRV-Tools/source/opt/code_sink.cpp b/third_party/SPIRV-Tools/source/opt/code_sink.cpp
index cd77797..35a8df2 100644
--- a/third_party/SPIRV-Tools/source/opt/code_sink.cpp
+++ b/third_party/SPIRV-Tools/source/opt/code_sink.cpp
@@ -50,7 +50,8 @@
 }
 
 bool CodeSinkingPass::SinkInstruction(Instruction* inst) {
-  if (inst->opcode() != SpvOpLoad && inst->opcode() != SpvOpAccessChain) {
+  if (inst->opcode() != spv::Op::OpLoad &&
+      inst->opcode() != spv::Op::OpAccessChain) {
     return false;
   }
 
@@ -60,7 +61,7 @@
 
   if (BasicBlock* target_bb = FindNewBasicBlockFor(inst)) {
     Instruction* pos = &*target_bb->begin();
-    while (pos->opcode() == SpvOpPhi) {
+    while (pos->opcode() == spv::Op::OpPhi) {
       pos = pos->NextNode();
     }
 
@@ -79,7 +80,7 @@
   std::unordered_set<uint32_t> bbs_with_uses;
   get_def_use_mgr()->ForEachUse(
       inst, [&bbs_with_uses, this](Instruction* use, uint32_t idx) {
-        if (use->opcode() != SpvOpPhi) {
+        if (use->opcode() != spv::Op::OpPhi) {
           BasicBlock* use_bb = context()->get_instr_block(use);
           if (use_bb) {
             bbs_with_uses.insert(use_bb->id());
@@ -99,7 +100,7 @@
     // of succ_bb, then |inst| can be moved to succ_bb.  If succ_bb, has move
     // then one predecessor, then moving |inst| into succ_bb could cause it to
     // be executed more often, so the search has to stop.
-    if (bb->terminator()->opcode() == SpvOpBranch) {
+    if (bb->terminator()->opcode() == spv::Op::OpBranch) {
       uint32_t succ_bb_id = bb->terminator()->GetSingleWordInOperand(0);
       if (cfg()->preds(succ_bb_id).size() == 1) {
         bb = context()->get_instr_block(succ_bb_id);
@@ -113,7 +114,8 @@
     // instruction or an OpLoopMerge, then it is a break or continue.  We could
     // figure it out, but not worth doing it now.
     Instruction* merge_inst = bb->GetMergeInst();
-    if (merge_inst == nullptr || merge_inst->opcode() != SpvOpSelectionMerge) {
+    if (merge_inst == nullptr ||
+        merge_inst->opcode() != spv::Op::OpSelectionMerge) {
       break;
     }
 
@@ -173,7 +175,7 @@
   }
 
   Instruction* base_ptr = inst->GetBaseAddress();
-  if (base_ptr->opcode() != SpvOpVariable) {
+  if (base_ptr->opcode() != spv::Op::OpVariable) {
     return true;
   }
 
@@ -185,7 +187,8 @@
     return true;
   }
 
-  if (base_ptr->GetSingleWordInOperand(0) != SpvStorageClassUniform) {
+  if (spv::StorageClass(base_ptr->GetSingleWordInOperand(0)) !=
+      spv::StorageClass::Uniform) {
     return true;
   }
 
@@ -200,41 +203,41 @@
   bool has_sync = false;
   get_module()->ForEachInst([this, &has_sync](Instruction* inst) {
     switch (inst->opcode()) {
-      case SpvOpMemoryBarrier: {
+      case spv::Op::OpMemoryBarrier: {
         uint32_t mem_semantics_id = inst->GetSingleWordInOperand(1);
         if (IsSyncOnUniform(mem_semantics_id)) {
           has_sync = true;
         }
         break;
       }
-      case SpvOpControlBarrier:
-      case SpvOpAtomicLoad:
-      case SpvOpAtomicStore:
-      case SpvOpAtomicExchange:
-      case SpvOpAtomicIIncrement:
-      case SpvOpAtomicIDecrement:
-      case SpvOpAtomicIAdd:
-      case SpvOpAtomicFAddEXT:
-      case SpvOpAtomicISub:
-      case SpvOpAtomicSMin:
-      case SpvOpAtomicUMin:
-      case SpvOpAtomicFMinEXT:
-      case SpvOpAtomicSMax:
-      case SpvOpAtomicUMax:
-      case SpvOpAtomicFMaxEXT:
-      case SpvOpAtomicAnd:
-      case SpvOpAtomicOr:
-      case SpvOpAtomicXor:
-      case SpvOpAtomicFlagTestAndSet:
-      case SpvOpAtomicFlagClear: {
+      case spv::Op::OpControlBarrier:
+      case spv::Op::OpAtomicLoad:
+      case spv::Op::OpAtomicStore:
+      case spv::Op::OpAtomicExchange:
+      case spv::Op::OpAtomicIIncrement:
+      case spv::Op::OpAtomicIDecrement:
+      case spv::Op::OpAtomicIAdd:
+      case spv::Op::OpAtomicFAddEXT:
+      case spv::Op::OpAtomicISub:
+      case spv::Op::OpAtomicSMin:
+      case spv::Op::OpAtomicUMin:
+      case spv::Op::OpAtomicFMinEXT:
+      case spv::Op::OpAtomicSMax:
+      case spv::Op::OpAtomicUMax:
+      case spv::Op::OpAtomicFMaxEXT:
+      case spv::Op::OpAtomicAnd:
+      case spv::Op::OpAtomicOr:
+      case spv::Op::OpAtomicXor:
+      case spv::Op::OpAtomicFlagTestAndSet:
+      case spv::Op::OpAtomicFlagClear: {
         uint32_t mem_semantics_id = inst->GetSingleWordInOperand(2);
         if (IsSyncOnUniform(mem_semantics_id)) {
           has_sync = true;
         }
         break;
       }
-      case SpvOpAtomicCompareExchange:
-      case SpvOpAtomicCompareExchangeWeak:
+      case spv::Op::OpAtomicCompareExchange:
+      case spv::Op::OpAtomicCompareExchangeWeak:
         if (IsSyncOnUniform(inst->GetSingleWordInOperand(2)) ||
             IsSyncOnUniform(inst->GetSingleWordInOperand(3))) {
           has_sync = true;
@@ -259,28 +262,30 @@
 
   // If it does not affect uniform memory, then it is does not apply to uniform
   // memory.
-  if ((mem_semantics_int & SpvMemorySemanticsUniformMemoryMask) == 0) {
+  if ((mem_semantics_int & uint32_t(spv::MemorySemanticsMask::UniformMemory)) ==
+      0) {
     return false;
   }
 
   // Check if there is an acquire or release.  If so not, this it does not add
   // any memory constraints.
-  return (mem_semantics_int & (SpvMemorySemanticsAcquireMask |
-                               SpvMemorySemanticsAcquireReleaseMask |
-                               SpvMemorySemanticsReleaseMask)) != 0;
+  return (mem_semantics_int &
+          uint32_t(spv::MemorySemanticsMask::Acquire |
+                   spv::MemorySemanticsMask::AcquireRelease |
+                   spv::MemorySemanticsMask::Release)) != 0;
 }
 
 bool CodeSinkingPass::HasPossibleStore(Instruction* var_inst) {
-  assert(var_inst->opcode() == SpvOpVariable ||
-         var_inst->opcode() == SpvOpAccessChain ||
-         var_inst->opcode() == SpvOpPtrAccessChain);
+  assert(var_inst->opcode() == spv::Op::OpVariable ||
+         var_inst->opcode() == spv::Op::OpAccessChain ||
+         var_inst->opcode() == spv::Op::OpPtrAccessChain);
 
   return get_def_use_mgr()->WhileEachUser(var_inst, [this](Instruction* use) {
     switch (use->opcode()) {
-      case SpvOpStore:
+      case spv::Op::OpStore:
         return true;
-      case SpvOpAccessChain:
-      case SpvOpPtrAccessChain:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpPtrAccessChain:
         return HasPossibleStore(use);
       default:
         return false;
diff --git a/third_party/SPIRV-Tools/source/opt/combine_access_chains.cpp b/third_party/SPIRV-Tools/source/opt/combine_access_chains.cpp
index 142897a..99ec796 100644
--- a/third_party/SPIRV-Tools/source/opt/combine_access_chains.cpp
+++ b/third_party/SPIRV-Tools/source/opt/combine_access_chains.cpp
@@ -44,10 +44,10 @@
       function.entry().get(), [&modified, this](BasicBlock* block) {
         block->ForEachInst([&modified, this](Instruction* inst) {
           switch (inst->opcode()) {
-            case SpvOpAccessChain:
-            case SpvOpInBoundsAccessChain:
-            case SpvOpPtrAccessChain:
-            case SpvOpInBoundsPtrAccessChain:
+            case spv::Op::OpAccessChain:
+            case spv::Op::OpInBoundsAccessChain:
+            case spv::Op::OpPtrAccessChain:
+            case spv::Op::OpInBoundsPtrAccessChain:
               modified |= CombineAccessChain(inst);
               break;
             default:
@@ -76,10 +76,10 @@
 uint32_t CombineAccessChains::GetArrayStride(const Instruction* inst) {
   uint32_t array_stride = 0;
   context()->get_decoration_mgr()->WhileEachDecoration(
-      inst->type_id(), SpvDecorationArrayStride,
+      inst->type_id(), uint32_t(spv::Decoration::ArrayStride),
       [&array_stride](const Instruction& decoration) {
-        assert(decoration.opcode() != SpvOpDecorateId);
-        if (decoration.opcode() == SpvOpDecorate) {
+        assert(decoration.opcode() != spv::Op::OpDecorateId);
+        if (decoration.opcode() == spv::Op::OpDecorate) {
           array_stride = decoration.GetSingleWordInOperand(1);
         } else {
           array_stride = decoration.GetSingleWordInOperand(2);
@@ -200,18 +200,18 @@
 }
 
 bool CombineAccessChains::CombineAccessChain(Instruction* inst) {
-  assert((inst->opcode() == SpvOpPtrAccessChain ||
-          inst->opcode() == SpvOpAccessChain ||
-          inst->opcode() == SpvOpInBoundsAccessChain ||
-          inst->opcode() == SpvOpInBoundsPtrAccessChain) &&
+  assert((inst->opcode() == spv::Op::OpPtrAccessChain ||
+          inst->opcode() == spv::Op::OpAccessChain ||
+          inst->opcode() == spv::Op::OpInBoundsAccessChain ||
+          inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) &&
          "Wrong opcode. Expected an access chain.");
 
   Instruction* ptr_input =
       context()->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0));
-  if (ptr_input->opcode() != SpvOpAccessChain &&
-      ptr_input->opcode() != SpvOpInBoundsAccessChain &&
-      ptr_input->opcode() != SpvOpPtrAccessChain &&
-      ptr_input->opcode() != SpvOpInBoundsPtrAccessChain) {
+  if (ptr_input->opcode() != spv::Op::OpAccessChain &&
+      ptr_input->opcode() != spv::Op::OpInBoundsAccessChain &&
+      ptr_input->opcode() != spv::Op::OpPtrAccessChain &&
+      ptr_input->opcode() != spv::Op::OpInBoundsPtrAccessChain) {
     return false;
   }
 
@@ -246,7 +246,7 @@
   } else if (inst->NumInOperands() == 1) {
     // |inst| is a no-op, change it to a copy. Instruction simplification will
     // clean it up.
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
   } else {
     std::vector<Operand> new_operands;
     if (!CreateNewInputOperands(ptr_input, inst, &new_operands)) return false;
@@ -259,23 +259,25 @@
   return true;
 }
 
-SpvOp CombineAccessChains::UpdateOpcode(SpvOp base_opcode, SpvOp input_opcode) {
-  auto IsInBounds = [](SpvOp opcode) {
-    return opcode == SpvOpInBoundsPtrAccessChain ||
-           opcode == SpvOpInBoundsAccessChain;
+spv::Op CombineAccessChains::UpdateOpcode(spv::Op base_opcode,
+                                          spv::Op input_opcode) {
+  auto IsInBounds = [](spv::Op opcode) {
+    return opcode == spv::Op::OpInBoundsPtrAccessChain ||
+           opcode == spv::Op::OpInBoundsAccessChain;
   };
 
-  if (input_opcode == SpvOpInBoundsPtrAccessChain) {
-    if (!IsInBounds(base_opcode)) return SpvOpPtrAccessChain;
-  } else if (input_opcode == SpvOpInBoundsAccessChain) {
-    if (!IsInBounds(base_opcode)) return SpvOpAccessChain;
+  if (input_opcode == spv::Op::OpInBoundsPtrAccessChain) {
+    if (!IsInBounds(base_opcode)) return spv::Op::OpPtrAccessChain;
+  } else if (input_opcode == spv::Op::OpInBoundsAccessChain) {
+    if (!IsInBounds(base_opcode)) return spv::Op::OpAccessChain;
   }
 
   return input_opcode;
 }
 
-bool CombineAccessChains::IsPtrAccessChain(SpvOp opcode) {
-  return opcode == SpvOpPtrAccessChain || opcode == SpvOpInBoundsPtrAccessChain;
+bool CombineAccessChains::IsPtrAccessChain(spv::Op opcode) {
+  return opcode == spv::Op::OpPtrAccessChain ||
+         opcode == spv::Op::OpInBoundsPtrAccessChain;
 }
 
 bool CombineAccessChains::Has64BitIndices(Instruction* inst) {
diff --git a/third_party/SPIRV-Tools/source/opt/combine_access_chains.h b/third_party/SPIRV-Tools/source/opt/combine_access_chains.h
index 531209e..32ee50d 100644
--- a/third_party/SPIRV-Tools/source/opt/combine_access_chains.h
+++ b/third_party/SPIRV-Tools/source/opt/combine_access_chains.h
@@ -68,10 +68,10 @@
                       std::vector<Operand>* new_operands);
 
   // Returns the opcode to use for the combined access chain.
-  SpvOp UpdateOpcode(SpvOp base_opcode, SpvOp input_opcode);
+  spv::Op UpdateOpcode(spv::Op base_opcode, spv::Op input_opcode);
 
   // Returns true if |opcode| is a pointer access chain.
-  bool IsPtrAccessChain(SpvOp opcode);
+  bool IsPtrAccessChain(spv::Op opcode);
 
   // Returns true if |inst| (an access chain) has 64-bit indices.
   bool Has64BitIndices(Instruction* inst);
diff --git a/third_party/SPIRV-Tools/source/opt/compact_ids_pass.cpp b/third_party/SPIRV-Tools/source/opt/compact_ids_pass.cpp
index 70848d7..5a2a54b 100644
--- a/third_party/SPIRV-Tools/source/opt/compact_ids_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/compact_ids_pass.cpp
@@ -44,6 +44,11 @@
   bool modified = false;
   std::unordered_map<uint32_t, uint32_t> result_id_mapping;
 
+  // Disable automatic DebugInfo analysis for the life of the CompactIds pass.
+  // The DebugInfo manager requires the SPIR-V to be valid to run, but this is
+  // not true at all times in CompactIds as it remaps all ids.
+  context()->InvalidateAnalyses(IRContext::kAnalysisDebugInfo);
+
   context()->module()->ForEachInst(
       [&result_id_mapping, &modified](Instruction* inst) {
         auto operand = inst->begin();
diff --git a/third_party/SPIRV-Tools/source/opt/const_folding_rules.cpp b/third_party/SPIRV-Tools/source/opt/const_folding_rules.cpp
index cb36087..e91455e 100644
--- a/third_party/SPIRV-Tools/source/opt/const_folding_rules.cpp
+++ b/third_party/SPIRV-Tools/source/opt/const_folding_rules.cpp
@@ -19,8 +19,7 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-const uint32_t kExtractCompositeIdInIdx = 0;
+constexpr uint32_t kExtractCompositeIdInIdx = 0;
 
 // Returns a constants with the value NaN of the given type.  Only works for
 // 32-bit and 64-bit float point types.  Returns |nullptr| if an error occurs.
@@ -74,7 +73,7 @@
 
 // Returns a constants with the value |-val| of the given type.  Only works for
 // 32-bit and 64-bit float point types.  Returns |nullptr| if an error occurs.
-const analysis::Constant* negateFPConst(const analysis::Type* result_type,
+const analysis::Constant* NegateFPConst(const analysis::Type* result_type,
                                         const analysis::Constant* val,
                                         analysis::ConstantManager* const_mgr) {
   const analysis::Float* float_type = result_type->AsFloat();
@@ -120,11 +119,88 @@
   };
 }
 
+// Folds an OpcompositeInsert where input is a composite constant.
+ConstantFoldingRule FoldInsertWithConstants() {
+  return [](IRContext* context, Instruction* inst,
+            const std::vector<const analysis::Constant*>& constants)
+             -> const analysis::Constant* {
+    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
+    const analysis::Constant* object = constants[0];
+    const analysis::Constant* composite = constants[1];
+    if (object == nullptr || composite == nullptr) {
+      return nullptr;
+    }
+
+    // If there is more than 1 index, then each additional constant used by the
+    // index will need to be recreated to use the inserted object.
+    std::vector<const analysis::Constant*> chain;
+    std::vector<const analysis::Constant*> components;
+    const analysis::Type* type = nullptr;
+
+    // Work down hierarchy and add all the indexes, not including the final
+    // index.
+    for (uint32_t i = 2; i < inst->NumInOperands(); ++i) {
+      if (i != inst->NumInOperands() - 1) {
+        chain.push_back(composite);
+      }
+      const uint32_t index = inst->GetSingleWordInOperand(i);
+      components = composite->AsCompositeConstant()->GetComponents();
+      type = composite->AsCompositeConstant()->type();
+      composite = components[index];
+    }
+
+    // Final index in hierarchy is inserted with new object.
+    const uint32_t final_index =
+        inst->GetSingleWordInOperand(inst->NumInOperands() - 1);
+    std::vector<uint32_t> ids;
+    for (size_t i = 0; i < components.size(); i++) {
+      const analysis::Constant* constant =
+          (i == final_index) ? object : components[i];
+      Instruction* member_inst = const_mgr->GetDefiningInstruction(constant);
+      ids.push_back(member_inst->result_id());
+    }
+    const analysis::Constant* new_constant = const_mgr->GetConstant(type, ids);
+
+    // Work backwards up the chain and replace each index with new constant.
+    for (size_t i = chain.size(); i > 0; i--) {
+      // Need to insert any previous instruction into the module first.
+      // Can't just insert in types_values_begin() because it will move above
+      // where the types are declared
+      for (Module::inst_iterator inst_iter = context->types_values_begin();
+           inst_iter != context->types_values_end(); ++inst_iter) {
+        Instruction* x = &*inst_iter;
+        if (inst->result_id() == x->result_id()) {
+          const_mgr->BuildInstructionAndAddToModule(new_constant, &inst_iter);
+          break;
+        }
+      }
+
+      composite = chain[i - 1];
+      components = composite->AsCompositeConstant()->GetComponents();
+      type = composite->AsCompositeConstant()->type();
+      ids.clear();
+      for (size_t k = 0; k < components.size(); k++) {
+        const uint32_t index =
+            inst->GetSingleWordInOperand(1 + static_cast<uint32_t>(i));
+        const analysis::Constant* constant =
+            (k == index) ? new_constant : components[k];
+        const uint32_t constant_id =
+            const_mgr->FindDeclaredConstant(constant, 0);
+        ids.push_back(constant_id);
+      }
+      new_constant = const_mgr->GetConstant(type, ids);
+    }
+
+    // If multiple constants were created, only need to return the top index.
+    return new_constant;
+  };
+}
+
 ConstantFoldingRule FoldVectorShuffleWithConstants() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
-    assert(inst->opcode() == SpvOpVectorShuffle);
+    assert(inst->opcode() == spv::Op::OpVectorShuffle);
     const analysis::Constant* c1 = constants[0];
     const analysis::Constant* c2 = constants[1];
     if (c1 == nullptr || c2 == nullptr) {
@@ -180,7 +256,7 @@
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
-    assert(inst->opcode() == SpvOpVectorTimesScalar);
+    assert(inst->opcode() == spv::Op::OpVectorTimesScalar);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -255,7 +331,7 @@
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
-    assert(inst->opcode() == SpvOpVectorTimesMatrix);
+    assert(inst->opcode() == spv::Op::OpVectorTimesMatrix);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -348,7 +424,7 @@
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
-    assert(inst->opcode() == SpvOpMatrixTimesVector);
+    assert(inst->opcode() == spv::Op::OpMatrixTimesVector);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -458,9 +534,9 @@
       }
 
       uint32_t component_type_id = 0;
-      if (type_inst->opcode() == SpvOpTypeStruct) {
+      if (type_inst->opcode() == spv::Op::OpTypeStruct) {
         component_type_id = type_inst->GetSingleWordInOperand(i);
-      } else if (type_inst->opcode() == SpvOpTypeArray) {
+      } else if (type_inst->opcode() == spv::Op::OpTypeArray) {
         component_type_id = type_inst->GetSingleWordInOperand(0);
       }
 
@@ -509,7 +585,7 @@
     }
 
     const analysis::Constant* arg =
-        (inst->opcode() == SpvOpExtInst) ? constants[1] : constants[0];
+        (inst->opcode() == spv::Op::OpExtInst) ? constants[1] : constants[0];
 
     if (arg == nullptr) {
       return nullptr;
@@ -599,7 +675,7 @@
     if (!inst->IsFloatingPointFoldingAllowed()) {
       return nullptr;
     }
-    if (inst->opcode() == SpvOpExtInst) {
+    if (inst->opcode() == spv::Op::OpExtInst) {
       return FoldFPBinaryOp(scalar_rule, inst->type_id(),
                             {constants[1], constants[2]}, context);
     }
@@ -755,7 +831,7 @@
   }
 
   if (numerator->AsFloatConstant()->GetValueAsDouble() < 0.0) {
-    result = negateFPConst(result_type, result, const_mgr);
+    result = NegateFPConst(result_type, result, const_mgr);
   }
   return result;
 }
@@ -780,7 +856,7 @@
     const analysis::Constant* result =
         FoldFPScalarDivideByZero(result_type, numerator, const_mgr);
     if (result != nullptr)
-      result = negateFPConst(result_type, result, const_mgr);
+      result = NegateFPConst(result_type, result, const_mgr);
     return result;
   } else {
     return FOLD_FPARITH_OP(/)(result_type, numerator, denominator, const_mgr);
@@ -951,13 +1027,13 @@
             analysis::ConstantManager* const_mgr) -> const analysis::Constant* {
     assert(result_type != nullptr && a != nullptr);
     assert(result_type == a->type());
-    return negateFPConst(result_type, a, const_mgr);
+    return NegateFPConst(result_type, a, const_mgr);
   };
 }
 
 ConstantFoldingRule FoldFNegate() { return FoldFPUnaryOp(FoldFNegateOp()); }
 
-ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) {
+ConstantFoldingRule FoldFClampFeedingCompare(spv::Op cmp_opcode) {
   return [cmp_opcode](IRContext* context, Instruction* inst,
                       const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
@@ -985,7 +1061,7 @@
       return nullptr;
     }
 
-    if (operand_inst->opcode() != SpvOpExtInst) {
+    if (operand_inst->opcode() != spv::Op::OpExtInst) {
       return nullptr;
     }
 
@@ -1009,25 +1085,25 @@
     bool result = false;
 
     switch (cmp_opcode) {
-      case SpvOpFOrdLessThan:
-      case SpvOpFUnordLessThan:
-      case SpvOpFOrdGreaterThanEqual:
-      case SpvOpFUnordGreaterThanEqual:
+      case spv::Op::OpFOrdLessThan:
+      case spv::Op::OpFUnordLessThan:
+      case spv::Op::OpFOrdGreaterThanEqual:
+      case spv::Op::OpFUnordGreaterThanEqual:
         if (constants[0]) {
           if (min_const) {
             if (constants[0]->GetValueAsDouble() <
                 min_const->GetValueAsDouble()) {
               found_result = true;
-              result = (cmp_opcode == SpvOpFOrdLessThan ||
-                        cmp_opcode == SpvOpFUnordLessThan);
+              result = (cmp_opcode == spv::Op::OpFOrdLessThan ||
+                        cmp_opcode == spv::Op::OpFUnordLessThan);
             }
           }
           if (max_const) {
             if (constants[0]->GetValueAsDouble() >=
                 max_const->GetValueAsDouble()) {
               found_result = true;
-              result = !(cmp_opcode == SpvOpFOrdLessThan ||
-                         cmp_opcode == SpvOpFUnordLessThan);
+              result = !(cmp_opcode == spv::Op::OpFOrdLessThan ||
+                         cmp_opcode == spv::Op::OpFUnordLessThan);
             }
           }
         }
@@ -1037,8 +1113,8 @@
             if (max_const->GetValueAsDouble() <
                 constants[1]->GetValueAsDouble()) {
               found_result = true;
-              result = (cmp_opcode == SpvOpFOrdLessThan ||
-                        cmp_opcode == SpvOpFUnordLessThan);
+              result = (cmp_opcode == spv::Op::OpFOrdLessThan ||
+                        cmp_opcode == spv::Op::OpFUnordLessThan);
             }
           }
 
@@ -1046,31 +1122,31 @@
             if (min_const->GetValueAsDouble() >=
                 constants[1]->GetValueAsDouble()) {
               found_result = true;
-              result = !(cmp_opcode == SpvOpFOrdLessThan ||
-                         cmp_opcode == SpvOpFUnordLessThan);
+              result = !(cmp_opcode == spv::Op::OpFOrdLessThan ||
+                         cmp_opcode == spv::Op::OpFUnordLessThan);
             }
           }
         }
         break;
-      case SpvOpFOrdGreaterThan:
-      case SpvOpFUnordGreaterThan:
-      case SpvOpFOrdLessThanEqual:
-      case SpvOpFUnordLessThanEqual:
+      case spv::Op::OpFOrdGreaterThan:
+      case spv::Op::OpFUnordGreaterThan:
+      case spv::Op::OpFOrdLessThanEqual:
+      case spv::Op::OpFUnordLessThanEqual:
         if (constants[0]) {
           if (min_const) {
             if (constants[0]->GetValueAsDouble() <=
                 min_const->GetValueAsDouble()) {
               found_result = true;
-              result = (cmp_opcode == SpvOpFOrdLessThanEqual ||
-                        cmp_opcode == SpvOpFUnordLessThanEqual);
+              result = (cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
+                        cmp_opcode == spv::Op::OpFUnordLessThanEqual);
             }
           }
           if (max_const) {
             if (constants[0]->GetValueAsDouble() >
                 max_const->GetValueAsDouble()) {
               found_result = true;
-              result = !(cmp_opcode == SpvOpFOrdLessThanEqual ||
-                         cmp_opcode == SpvOpFUnordLessThanEqual);
+              result = !(cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
+                         cmp_opcode == spv::Op::OpFUnordLessThanEqual);
             }
           }
         }
@@ -1080,8 +1156,8 @@
             if (max_const->GetValueAsDouble() <=
                 constants[1]->GetValueAsDouble()) {
               found_result = true;
-              result = (cmp_opcode == SpvOpFOrdLessThanEqual ||
-                        cmp_opcode == SpvOpFUnordLessThanEqual);
+              result = (cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
+                        cmp_opcode == spv::Op::OpFUnordLessThanEqual);
             }
           }
 
@@ -1089,8 +1165,8 @@
             if (min_const->GetValueAsDouble() >
                 constants[1]->GetValueAsDouble()) {
               found_result = true;
-              result = !(cmp_opcode == SpvOpFOrdLessThanEqual ||
-                         cmp_opcode == SpvOpFUnordLessThanEqual);
+              result = !(cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
+                         cmp_opcode == spv::Op::OpFUnordLessThanEqual);
             }
           }
         }
@@ -1117,7 +1193,7 @@
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
-    assert(inst->opcode() == SpvOpExtInst &&
+    assert(inst->opcode() == spv::Op::OpExtInst &&
            "Expecting an extended instruction.");
     assert(inst->GetSingleWordInOperand(0) ==
                context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
@@ -1183,17 +1259,6 @@
   };
 }
 
-template <class IntType>
-IntType FoldIClamp(IntType x, IntType min_val, IntType max_val) {
-  if (x < min_val) {
-    x = min_val;
-  }
-  if (x > max_val) {
-    x = max_val;
-  }
-  return x;
-}
-
 const analysis::Constant* FoldMin(const analysis::Type* result_type,
                                   const analysis::Constant* a,
                                   const analysis::Constant* b,
@@ -1278,7 +1343,7 @@
 const analysis::Constant* FoldClamp1(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>& constants) {
-  assert(inst->opcode() == SpvOpExtInst &&
+  assert(inst->opcode() == spv::Op::OpExtInst &&
          "Expecting an extended instruction.");
   assert(inst->GetSingleWordInOperand(0) ==
              context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
@@ -1304,7 +1369,7 @@
 const analysis::Constant* FoldClamp2(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>& constants) {
-  assert(inst->opcode() == SpvOpExtInst &&
+  assert(inst->opcode() == spv::Op::OpExtInst &&
          "Expecting an extended instruction.");
   assert(inst->GetSingleWordInOperand(0) ==
              context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
@@ -1332,7 +1397,7 @@
 const analysis::Constant* FoldClamp3(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>& constants) {
-  assert(inst->opcode() == SpvOpExtInst &&
+  assert(inst->opcode() == spv::Op::OpExtInst &&
          "Expecting an extended instruction.");
   assert(inst->GetSingleWordInOperand(0) ==
              context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
@@ -1418,68 +1483,70 @@
   // applies to the instruction, the rest of the rules will not be attempted.
   // Take that into consideration.
 
-  rules_[SpvOpCompositeConstruct].push_back(FoldCompositeWithConstants());
+  rules_[spv::Op::OpCompositeConstruct].push_back(FoldCompositeWithConstants());
 
-  rules_[SpvOpCompositeExtract].push_back(FoldExtractWithConstants());
+  rules_[spv::Op::OpCompositeExtract].push_back(FoldExtractWithConstants());
+  rules_[spv::Op::OpCompositeInsert].push_back(FoldInsertWithConstants());
 
-  rules_[SpvOpConvertFToS].push_back(FoldFToI());
-  rules_[SpvOpConvertFToU].push_back(FoldFToI());
-  rules_[SpvOpConvertSToF].push_back(FoldIToF());
-  rules_[SpvOpConvertUToF].push_back(FoldIToF());
+  rules_[spv::Op::OpConvertFToS].push_back(FoldFToI());
+  rules_[spv::Op::OpConvertFToU].push_back(FoldFToI());
+  rules_[spv::Op::OpConvertSToF].push_back(FoldIToF());
+  rules_[spv::Op::OpConvertUToF].push_back(FoldIToF());
 
-  rules_[SpvOpDot].push_back(FoldOpDotWithConstants());
-  rules_[SpvOpFAdd].push_back(FoldFAdd());
-  rules_[SpvOpFDiv].push_back(FoldFDiv());
-  rules_[SpvOpFMul].push_back(FoldFMul());
-  rules_[SpvOpFSub].push_back(FoldFSub());
+  rules_[spv::Op::OpDot].push_back(FoldOpDotWithConstants());
+  rules_[spv::Op::OpFAdd].push_back(FoldFAdd());
+  rules_[spv::Op::OpFDiv].push_back(FoldFDiv());
+  rules_[spv::Op::OpFMul].push_back(FoldFMul());
+  rules_[spv::Op::OpFSub].push_back(FoldFSub());
 
-  rules_[SpvOpFOrdEqual].push_back(FoldFOrdEqual());
+  rules_[spv::Op::OpFOrdEqual].push_back(FoldFOrdEqual());
 
-  rules_[SpvOpFUnordEqual].push_back(FoldFUnordEqual());
+  rules_[spv::Op::OpFUnordEqual].push_back(FoldFUnordEqual());
 
-  rules_[SpvOpFOrdNotEqual].push_back(FoldFOrdNotEqual());
+  rules_[spv::Op::OpFOrdNotEqual].push_back(FoldFOrdNotEqual());
 
-  rules_[SpvOpFUnordNotEqual].push_back(FoldFUnordNotEqual());
+  rules_[spv::Op::OpFUnordNotEqual].push_back(FoldFUnordNotEqual());
 
-  rules_[SpvOpFOrdLessThan].push_back(FoldFOrdLessThan());
-  rules_[SpvOpFOrdLessThan].push_back(
-      FoldFClampFeedingCompare(SpvOpFOrdLessThan));
+  rules_[spv::Op::OpFOrdLessThan].push_back(FoldFOrdLessThan());
+  rules_[spv::Op::OpFOrdLessThan].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFOrdLessThan));
 
-  rules_[SpvOpFUnordLessThan].push_back(FoldFUnordLessThan());
-  rules_[SpvOpFUnordLessThan].push_back(
-      FoldFClampFeedingCompare(SpvOpFUnordLessThan));
+  rules_[spv::Op::OpFUnordLessThan].push_back(FoldFUnordLessThan());
+  rules_[spv::Op::OpFUnordLessThan].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFUnordLessThan));
 
-  rules_[SpvOpFOrdGreaterThan].push_back(FoldFOrdGreaterThan());
-  rules_[SpvOpFOrdGreaterThan].push_back(
-      FoldFClampFeedingCompare(SpvOpFOrdGreaterThan));
+  rules_[spv::Op::OpFOrdGreaterThan].push_back(FoldFOrdGreaterThan());
+  rules_[spv::Op::OpFOrdGreaterThan].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFOrdGreaterThan));
 
-  rules_[SpvOpFUnordGreaterThan].push_back(FoldFUnordGreaterThan());
-  rules_[SpvOpFUnordGreaterThan].push_back(
-      FoldFClampFeedingCompare(SpvOpFUnordGreaterThan));
+  rules_[spv::Op::OpFUnordGreaterThan].push_back(FoldFUnordGreaterThan());
+  rules_[spv::Op::OpFUnordGreaterThan].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFUnordGreaterThan));
 
-  rules_[SpvOpFOrdLessThanEqual].push_back(FoldFOrdLessThanEqual());
-  rules_[SpvOpFOrdLessThanEqual].push_back(
-      FoldFClampFeedingCompare(SpvOpFOrdLessThanEqual));
+  rules_[spv::Op::OpFOrdLessThanEqual].push_back(FoldFOrdLessThanEqual());
+  rules_[spv::Op::OpFOrdLessThanEqual].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFOrdLessThanEqual));
 
-  rules_[SpvOpFUnordLessThanEqual].push_back(FoldFUnordLessThanEqual());
-  rules_[SpvOpFUnordLessThanEqual].push_back(
-      FoldFClampFeedingCompare(SpvOpFUnordLessThanEqual));
+  rules_[spv::Op::OpFUnordLessThanEqual].push_back(FoldFUnordLessThanEqual());
+  rules_[spv::Op::OpFUnordLessThanEqual].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFUnordLessThanEqual));
 
-  rules_[SpvOpFOrdGreaterThanEqual].push_back(FoldFOrdGreaterThanEqual());
-  rules_[SpvOpFOrdGreaterThanEqual].push_back(
-      FoldFClampFeedingCompare(SpvOpFOrdGreaterThanEqual));
+  rules_[spv::Op::OpFOrdGreaterThanEqual].push_back(FoldFOrdGreaterThanEqual());
+  rules_[spv::Op::OpFOrdGreaterThanEqual].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFOrdGreaterThanEqual));
 
-  rules_[SpvOpFUnordGreaterThanEqual].push_back(FoldFUnordGreaterThanEqual());
-  rules_[SpvOpFUnordGreaterThanEqual].push_back(
-      FoldFClampFeedingCompare(SpvOpFUnordGreaterThanEqual));
+  rules_[spv::Op::OpFUnordGreaterThanEqual].push_back(
+      FoldFUnordGreaterThanEqual());
+  rules_[spv::Op::OpFUnordGreaterThanEqual].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFUnordGreaterThanEqual));
 
-  rules_[SpvOpVectorShuffle].push_back(FoldVectorShuffleWithConstants());
-  rules_[SpvOpVectorTimesScalar].push_back(FoldVectorTimesScalar());
-  rules_[SpvOpVectorTimesMatrix].push_back(FoldVectorTimesMatrix());
-  rules_[SpvOpMatrixTimesVector].push_back(FoldMatrixTimesVector());
+  rules_[spv::Op::OpVectorShuffle].push_back(FoldVectorShuffleWithConstants());
+  rules_[spv::Op::OpVectorTimesScalar].push_back(FoldVectorTimesScalar());
+  rules_[spv::Op::OpVectorTimesMatrix].push_back(FoldVectorTimesMatrix());
+  rules_[spv::Op::OpMatrixTimesVector].push_back(FoldMatrixTimesVector());
 
-  rules_[SpvOpFNegate].push_back(FoldFNegate());
-  rules_[SpvOpQuantizeToF16].push_back(FoldQuantizeToF16());
+  rules_[spv::Op::OpFNegate].push_back(FoldFNegate());
+  rules_[spv::Op::OpQuantizeToF16].push_back(FoldQuantizeToF16());
 
   // Add rules for GLSLstd450
   FeatureManager* feature_manager = context_->get_feature_mgr();
diff --git a/third_party/SPIRV-Tools/source/opt/const_folding_rules.h b/third_party/SPIRV-Tools/source/opt/const_folding_rules.h
index 41ee2aa..fa34532 100644
--- a/third_party/SPIRV-Tools/source/opt/const_folding_rules.h
+++ b/third_party/SPIRV-Tools/source/opt/const_folding_rules.h
@@ -88,7 +88,7 @@
   // Returns true if there is at least 1 folding rule for |inst|.
   const std::vector<ConstantFoldingRule>& GetRulesForInstruction(
       const Instruction* inst) const {
-    if (inst->opcode() != SpvOpExtInst) {
+    if (inst->opcode() != spv::Op::OpExtInst) {
       auto it = rules_.find(inst->opcode());
       if (it != rules_.end()) {
         return it->second.value;
@@ -108,9 +108,15 @@
   virtual void AddFoldingRules();
 
  protected:
+  struct hasher {
+    size_t operator()(const spv::Op& op) const noexcept {
+      return std::hash<uint32_t>()(uint32_t(op));
+    }
+  };
+
   // |rules[opcode]| is the set of rules that can be applied to instructions
   // with |opcode| as the opcode.
-  std::unordered_map<uint32_t, Value> rules_;
+  std::unordered_map<spv::Op, Value, hasher> rules_;
 
   // The folding rules for extended instructions.
   std::map<Key, Value> ext_rules_;
diff --git a/third_party/SPIRV-Tools/source/opt/constants.cpp b/third_party/SPIRV-Tools/source/opt/constants.cpp
index bcff08c..9930b44 100644
--- a/third_party/SPIRV-Tools/source/opt/constants.cpp
+++ b/third_party/SPIRV-Tools/source/opt/constants.cpp
@@ -306,16 +306,16 @@
   switch (inst->opcode()) {
     // OpConstant{True|False} have the value embedded in the opcode. So they
     // are not handled by the for-loop above. Here we add the value explicitly.
-    case SpvOp::SpvOpConstantTrue:
+    case spv::Op::OpConstantTrue:
       literal_words_or_ids.push_back(true);
       break;
-    case SpvOp::SpvOpConstantFalse:
+    case spv::Op::OpConstantFalse:
       literal_words_or_ids.push_back(false);
       break;
-    case SpvOp::SpvOpConstantNull:
-    case SpvOp::SpvOpConstant:
-    case SpvOp::SpvOpConstantComposite:
-    case SpvOp::SpvOpSpecConstantComposite:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpConstant:
+    case spv::Op::OpConstantComposite:
+    case spv::Op::OpSpecConstantComposite:
       break;
     default:
       return nullptr;
@@ -329,22 +329,22 @@
   uint32_t type =
       (type_id == 0) ? context()->get_type_mgr()->GetId(c->type()) : type_id;
   if (c->AsNullConstant()) {
-    return MakeUnique<Instruction>(context(), SpvOp::SpvOpConstantNull, type,
-                                   id, std::initializer_list<Operand>{});
+    return MakeUnique<Instruction>(context(), spv::Op::OpConstantNull, type, id,
+                                   std::initializer_list<Operand>{});
   } else if (const BoolConstant* bc = c->AsBoolConstant()) {
     return MakeUnique<Instruction>(
         context(),
-        bc->value() ? SpvOp::SpvOpConstantTrue : SpvOp::SpvOpConstantFalse,
-        type, id, std::initializer_list<Operand>{});
+        bc->value() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse, type,
+        id, std::initializer_list<Operand>{});
   } else if (const IntConstant* ic = c->AsIntConstant()) {
     return MakeUnique<Instruction>(
-        context(), SpvOp::SpvOpConstant, type, id,
+        context(), spv::Op::OpConstant, type, id,
         std::initializer_list<Operand>{
             Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
                     ic->words())});
   } else if (const FloatConstant* fc = c->AsFloatConstant()) {
     return MakeUnique<Instruction>(
-        context(), SpvOp::SpvOpConstant, type, id,
+        context(), spv::Op::OpConstant, type, id,
         std::initializer_list<Operand>{
             Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
                     fc->words())});
@@ -362,9 +362,9 @@
   uint32_t component_index = 0;
   for (const Constant* component_const : cc->GetComponents()) {
     uint32_t component_type_id = 0;
-    if (type_inst && type_inst->opcode() == SpvOpTypeStruct) {
+    if (type_inst && type_inst->opcode() == spv::Op::OpTypeStruct) {
       component_type_id = type_inst->GetSingleWordInOperand(component_index);
-    } else if (type_inst && type_inst->opcode() == SpvOpTypeArray) {
+    } else if (type_inst && type_inst->opcode() == spv::Op::OpTypeArray) {
       component_type_id = type_inst->GetSingleWordInOperand(0);
     }
     uint32_t id = FindDeclaredConstant(component_const, component_type_id);
@@ -381,7 +381,7 @@
   }
   uint32_t type =
       (type_id == 0) ? context()->get_type_mgr()->GetId(cc->type()) : type_id;
-  return MakeUnique<Instruction>(context(), SpvOp::SpvOpConstantComposite, type,
+  return MakeUnique<Instruction>(context(), spv::Op::OpConstantComposite, type,
                                  result_id, std::move(operands));
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/constants.h b/third_party/SPIRV-Tools/source/opt/constants.h
index c039ae0..588ca3e 100644
--- a/third_party/SPIRV-Tools/source/opt/constants.h
+++ b/third_party/SPIRV-Tools/source/opt/constants.h
@@ -163,6 +163,21 @@
     return is_zero;
   }
 
+  uint32_t GetU32BitValue() const {
+    // Relies on unsigned values smaller than 32-bit being zero extended.  See
+    // section 2.2.1 of the SPIR-V spec.
+    assert(words().size() == 1);
+    return words()[0];
+  }
+
+  uint64_t GetU64BitValue() const {
+    // Relies on unsigned values smaller than 64-bit being zero extended.  See
+    // section 2.2.1 of the SPIR-V spec.
+    assert(words().size() == 2);
+    return static_cast<uint64_t>(words()[1]) << 32 |
+           static_cast<uint64_t>(words()[0]);
+  }
+
  protected:
   ScalarConstant(const Type* ty, const std::vector<uint32_t>& w)
       : Constant(ty), words_(w) {}
@@ -189,13 +204,6 @@
     return words()[0];
   }
 
-  uint32_t GetU32BitValue() const {
-    // Relies on unsigned values smaller than 32-bit being zero extended.  See
-    // section 2.2.1 of the SPIR-V spec.
-    assert(words().size() == 1);
-    return words()[0];
-  }
-
   int64_t GetS64BitValue() const {
     // Relies on unsigned values smaller than 64-bit being sign extended.  See
     // section 2.2.1 of the SPIR-V spec.
@@ -204,14 +212,6 @@
            static_cast<uint64_t>(words()[0]);
   }
 
-  uint64_t GetU64BitValue() const {
-    // Relies on unsigned values smaller than 64-bit being zero extended.  See
-    // section 2.2.1 of the SPIR-V spec.
-    assert(words().size() == 2);
-    return static_cast<uint64_t>(words()[1]) << 32 |
-           static_cast<uint64_t>(words()[0]);
-  }
-
   // Make a copy of this IntConstant instance.
   std::unique_ptr<IntConstant> CopyIntConstant() const {
     return MakeUnique<IntConstant>(type_->AsInteger(), words_);
diff --git a/third_party/SPIRV-Tools/source/opt/control_dependence.cpp b/third_party/SPIRV-Tools/source/opt/control_dependence.cpp
index f4879e0..a153cab 100644
--- a/third_party/SPIRV-Tools/source/opt/control_dependence.cpp
+++ b/third_party/SPIRV-Tools/source/opt/control_dependence.cpp
@@ -24,7 +24,6 @@
 #include "source/opt/dominator_analysis.h"
 #include "source/opt/function.h"
 #include "source/opt/instruction.h"
-#include "spirv/unified1/spirv.h"
 
 // Computes the control dependence graph (CDG) using the algorithm in Cytron
 // 1991, "Efficiently Computing Static Single Assignment Form and the Control
@@ -49,8 +48,8 @@
   }
   const BasicBlock* source_bb = cfg.block(source_bb_id());
   const Instruction* branch = source_bb->terminator();
-  assert((branch->opcode() == SpvOpBranchConditional ||
-          branch->opcode() == SpvOpSwitch) &&
+  assert((branch->opcode() == spv::Op::OpBranchConditional ||
+          branch->opcode() == spv::Op::OpSwitch) &&
          "invalid control dependence; last instruction must be conditional "
          "branch or switch");
   return branch->GetSingleWordInOperand(0);
diff --git a/third_party/SPIRV-Tools/source/opt/convert_to_half_pass.cpp b/third_party/SPIRV-Tools/source/opt/convert_to_half_pass.cpp
index 4086e31..7a4c1f4 100644
--- a/third_party/SPIRV-Tools/source/opt/convert_to_half_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/convert_to_half_pass.cpp
@@ -18,19 +18,16 @@
 
 #include "source/opt/ir_builder.h"
 
-namespace {
-
-// Indices of operands in SPIR-V instructions
-static const int kImageSampleDrefIdInIdx = 2;
-
-}  // anonymous namespace
-
 namespace spvtools {
 namespace opt {
+namespace {
+// Indices of operands in SPIR-V instructions
+constexpr int kImageSampleDrefIdInIdx = 2;
+}  // namespace
 
 bool ConvertToHalfPass::IsArithmetic(Instruction* inst) {
   return target_ops_core_.count(inst->opcode()) != 0 ||
-         (inst->opcode() == SpvOpExtInst &&
+         (inst->opcode() == spv::Op::OpExtInst &&
           inst->GetSingleWordInOperand(0) ==
               context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
           target_ops_450_.count(inst->GetSingleWordInOperand(1)) != 0);
@@ -45,9 +42,11 @@
 bool ConvertToHalfPass::IsDecoratedRelaxed(Instruction* inst) {
   uint32_t r_id = inst->result_id();
   for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false))
-    if (r_inst->opcode() == SpvOpDecorate &&
-        r_inst->GetSingleWordInOperand(1) == SpvDecorationRelaxedPrecision)
+    if (r_inst->opcode() == spv::Op::OpDecorate &&
+        spv::Decoration(r_inst->GetSingleWordInOperand(1)) ==
+            spv::Decoration::RelaxedPrecision) {
       return true;
+    }
   return false;
 }
 
@@ -82,12 +81,12 @@
 uint32_t ConvertToHalfPass::EquivFloatTypeId(uint32_t ty_id, uint32_t width) {
   analysis::Type* reg_equiv_ty;
   Instruction* ty_inst = get_def_use_mgr()->GetDef(ty_id);
-  if (ty_inst->opcode() == SpvOpTypeMatrix)
+  if (ty_inst->opcode() == spv::Op::OpTypeMatrix)
     reg_equiv_ty = FloatMatrixType(ty_inst->GetSingleWordInOperand(1),
                                    ty_inst->GetSingleWordInOperand(0), width);
-  else if (ty_inst->opcode() == SpvOpTypeVector)
+  else if (ty_inst->opcode() == spv::Op::OpTypeVector)
     reg_equiv_ty = FloatVectorType(ty_inst->GetSingleWordInOperand(1), width);
-  else  // SpvOpTypeFloat
+  else  // spv::Op::OpTypeFloat
     reg_equiv_ty = FloatScalarType(width);
   return context()->get_type_mgr()->GetTypeInstruction(reg_equiv_ty);
 }
@@ -102,18 +101,18 @@
   InstructionBuilder builder(
       context(), inst,
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
-  if (val_inst->opcode() == SpvOpUndef)
-    cvt_inst = builder.AddNullaryOp(nty_id, SpvOpUndef);
+  if (val_inst->opcode() == spv::Op::OpUndef)
+    cvt_inst = builder.AddNullaryOp(nty_id, spv::Op::OpUndef);
   else
-    cvt_inst = builder.AddUnaryOp(nty_id, SpvOpFConvert, *val_idp);
+    cvt_inst = builder.AddUnaryOp(nty_id, spv::Op::OpFConvert, *val_idp);
   *val_idp = cvt_inst->result_id();
 }
 
 bool ConvertToHalfPass::MatConvertCleanup(Instruction* inst) {
-  if (inst->opcode() != SpvOpFConvert) return false;
+  if (inst->opcode() != spv::Op::OpFConvert) return false;
   uint32_t mty_id = inst->type_id();
   Instruction* mty_inst = get_def_use_mgr()->GetDef(mty_id);
-  if (mty_inst->opcode() != SpvOpTypeMatrix) return false;
+  if (mty_inst->opcode() != spv::Op::OpTypeMatrix) return false;
   uint32_t vty_id = mty_inst->GetSingleWordInOperand(0);
   uint32_t v_cnt = mty_inst->GetSingleWordInOperand(1);
   Instruction* vty_inst = get_def_use_mgr()->GetDef(vty_id);
@@ -130,18 +129,18 @@
   std::vector<Operand> opnds = {};
   for (uint32_t vidx = 0; vidx < v_cnt; ++vidx) {
     Instruction* ext_inst = builder.AddIdLiteralOp(
-        orig_vty_id, SpvOpCompositeExtract, orig_mat_id, vidx);
+        orig_vty_id, spv::Op::OpCompositeExtract, orig_mat_id, vidx);
     Instruction* cvt_inst =
-        builder.AddUnaryOp(vty_id, SpvOpFConvert, ext_inst->result_id());
+        builder.AddUnaryOp(vty_id, spv::Op::OpFConvert, ext_inst->result_id());
     opnds.push_back({SPV_OPERAND_TYPE_ID, {cvt_inst->result_id()}});
   }
   uint32_t mat_id = TakeNextId();
   std::unique_ptr<Instruction> mat_inst(new Instruction(
-      context(), SpvOpCompositeConstruct, mty_id, mat_id, opnds));
+      context(), spv::Op::OpCompositeConstruct, mty_id, mat_id, opnds));
   (void)builder.AddInstruction(std::move(mat_inst));
   context()->ReplaceAllUsesWith(inst->result_id(), mat_id);
   // Turn original instruction into copy so it is valid.
-  inst->SetOpcode(SpvOpCopyObject);
+  inst->SetOpcode(spv::Op::OpCopyObject);
   inst->SetResultType(EquivFloatTypeId(mty_id, orig_width));
   get_def_use_mgr()->AnalyzeInstUse(inst);
   return true;
@@ -150,10 +149,11 @@
 bool ConvertToHalfPass::RemoveRelaxedDecoration(uint32_t id) {
   return context()->get_decoration_mgr()->RemoveDecorationsFrom(
       id, [](const Instruction& dec) {
-        if (dec.opcode() == SpvOpDecorate &&
-            dec.GetSingleWordInOperand(1u) == SpvDecorationRelaxedPrecision)
+        if (dec.opcode() == spv::Op::OpDecorate &&
+            spv::Decoration(dec.GetSingleWordInOperand(1u)) ==
+                spv::Decoration::RelaxedPrecision) {
           return true;
-        else
+        } else
           return false;
       });
 }
@@ -196,8 +196,8 @@
         auto insert_before = bp->tail();
         if (insert_before != bp->begin()) {
           --insert_before;
-          if (insert_before->opcode() != SpvOpSelectionMerge &&
-              insert_before->opcode() != SpvOpLoopMerge)
+          if (insert_before->opcode() != spv::Op::OpSelectionMerge &&
+              insert_before->opcode() != spv::Op::OpLoopMerge)
             ++insert_before;
         }
         GenConvert(prev_idp, to_width, &*insert_before);
@@ -229,7 +229,8 @@
   // changed to half.
   uint32_t val_id = inst->GetSingleWordInOperand(0);
   Instruction* val_inst = get_def_use_mgr()->GetDef(val_id);
-  if (inst->type_id() == val_inst->type_id()) inst->SetOpcode(SpvOpCopyObject);
+  if (inst->type_id() == val_inst->type_id())
+    inst->SetOpcode(spv::Op::OpCopyObject);
   return true;  // modified
 }
 
@@ -251,7 +252,7 @@
 bool ConvertToHalfPass::ProcessDefault(Instruction* inst) {
   // If non-relaxed instruction has changed operands, need to convert
   // them back to float32
-  if (inst->opcode() == SpvOpPhi) return ProcessPhi(inst, 16u, 32u);
+  if (inst->opcode() == spv::Op::OpPhi) return ProcessPhi(inst, 16u, 32u);
   bool modified = false;
   inst->ForEachInId([&inst, &modified, this](uint32_t* idp) {
     if (converted_ids_.count(*idp) == 0) return;
@@ -269,9 +270,9 @@
   bool inst_relaxed = IsRelaxed(inst->result_id());
   if (IsArithmetic(inst) && inst_relaxed)
     modified = GenHalfArith(inst);
-  else if (inst->opcode() == SpvOpPhi && inst_relaxed)
+  else if (inst->opcode() == spv::Op::OpPhi && inst_relaxed)
     modified = ProcessPhi(inst, 32u, 16u);
-  else if (inst->opcode() == SpvOpFConvert)
+  else if (inst->opcode() == spv::Op::OpFConvert)
     modified = ProcessConvert(inst);
   else if (image_ops_.count(inst->opcode()) != 0)
     modified = ProcessImageRef(inst);
@@ -350,7 +351,7 @@
   };
   bool modified = context()->ProcessReachableCallTree(pfn);
   // If modified, make sure module has Float16 capability
-  if (modified) context()->AddCapability(SpvCapabilityFloat16);
+  if (modified) context()->AddCapability(spv::Capability::Float16);
   // Remove all RelaxedPrecision decorations from instructions and globals
   for (auto c_id : relaxed_ids_set_) {
     modified |= RemoveRelaxedDecoration(c_id);
@@ -371,44 +372,44 @@
 
 void ConvertToHalfPass::Initialize() {
   target_ops_core_ = {
-      SpvOpVectorExtractDynamic,
-      SpvOpVectorInsertDynamic,
-      SpvOpVectorShuffle,
-      SpvOpCompositeConstruct,
-      SpvOpCompositeInsert,
-      SpvOpCompositeExtract,
-      SpvOpCopyObject,
-      SpvOpTranspose,
-      SpvOpConvertSToF,
-      SpvOpConvertUToF,
-      // SpvOpFConvert,
-      // SpvOpQuantizeToF16,
-      SpvOpFNegate,
-      SpvOpFAdd,
-      SpvOpFSub,
-      SpvOpFMul,
-      SpvOpFDiv,
-      SpvOpFMod,
-      SpvOpVectorTimesScalar,
-      SpvOpMatrixTimesScalar,
-      SpvOpVectorTimesMatrix,
-      SpvOpMatrixTimesVector,
-      SpvOpMatrixTimesMatrix,
-      SpvOpOuterProduct,
-      SpvOpDot,
-      SpvOpSelect,
-      SpvOpFOrdEqual,
-      SpvOpFUnordEqual,
-      SpvOpFOrdNotEqual,
-      SpvOpFUnordNotEqual,
-      SpvOpFOrdLessThan,
-      SpvOpFUnordLessThan,
-      SpvOpFOrdGreaterThan,
-      SpvOpFUnordGreaterThan,
-      SpvOpFOrdLessThanEqual,
-      SpvOpFUnordLessThanEqual,
-      SpvOpFOrdGreaterThanEqual,
-      SpvOpFUnordGreaterThanEqual,
+      spv::Op::OpVectorExtractDynamic,
+      spv::Op::OpVectorInsertDynamic,
+      spv::Op::OpVectorShuffle,
+      spv::Op::OpCompositeConstruct,
+      spv::Op::OpCompositeInsert,
+      spv::Op::OpCompositeExtract,
+      spv::Op::OpCopyObject,
+      spv::Op::OpTranspose,
+      spv::Op::OpConvertSToF,
+      spv::Op::OpConvertUToF,
+      // spv::Op::OpFConvert,
+      // spv::Op::OpQuantizeToF16,
+      spv::Op::OpFNegate,
+      spv::Op::OpFAdd,
+      spv::Op::OpFSub,
+      spv::Op::OpFMul,
+      spv::Op::OpFDiv,
+      spv::Op::OpFMod,
+      spv::Op::OpVectorTimesScalar,
+      spv::Op::OpMatrixTimesScalar,
+      spv::Op::OpVectorTimesMatrix,
+      spv::Op::OpMatrixTimesVector,
+      spv::Op::OpMatrixTimesMatrix,
+      spv::Op::OpOuterProduct,
+      spv::Op::OpDot,
+      spv::Op::OpSelect,
+      spv::Op::OpFOrdEqual,
+      spv::Op::OpFUnordEqual,
+      spv::Op::OpFOrdNotEqual,
+      spv::Op::OpFUnordNotEqual,
+      spv::Op::OpFOrdLessThan,
+      spv::Op::OpFUnordLessThan,
+      spv::Op::OpFOrdGreaterThan,
+      spv::Op::OpFUnordGreaterThan,
+      spv::Op::OpFOrdLessThanEqual,
+      spv::Op::OpFUnordLessThanEqual,
+      spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThanEqual,
   };
   target_ops_450_ = {
       GLSLstd450Round, GLSLstd450RoundEven, GLSLstd450Trunc, GLSLstd450FAbs,
@@ -427,53 +428,53 @@
       GLSLstd450Ldexp, GLSLstd450Length, GLSLstd450Distance, GLSLstd450Cross,
       GLSLstd450Normalize, GLSLstd450FaceForward, GLSLstd450Reflect,
       GLSLstd450Refract, GLSLstd450NMin, GLSLstd450NMax, GLSLstd450NClamp};
-  image_ops_ = {SpvOpImageSampleImplicitLod,
-                SpvOpImageSampleExplicitLod,
-                SpvOpImageSampleDrefImplicitLod,
-                SpvOpImageSampleDrefExplicitLod,
-                SpvOpImageSampleProjImplicitLod,
-                SpvOpImageSampleProjExplicitLod,
-                SpvOpImageSampleProjDrefImplicitLod,
-                SpvOpImageSampleProjDrefExplicitLod,
-                SpvOpImageFetch,
-                SpvOpImageGather,
-                SpvOpImageDrefGather,
-                SpvOpImageRead,
-                SpvOpImageSparseSampleImplicitLod,
-                SpvOpImageSparseSampleExplicitLod,
-                SpvOpImageSparseSampleDrefImplicitLod,
-                SpvOpImageSparseSampleDrefExplicitLod,
-                SpvOpImageSparseSampleProjImplicitLod,
-                SpvOpImageSparseSampleProjExplicitLod,
-                SpvOpImageSparseSampleProjDrefImplicitLod,
-                SpvOpImageSparseSampleProjDrefExplicitLod,
-                SpvOpImageSparseFetch,
-                SpvOpImageSparseGather,
-                SpvOpImageSparseDrefGather,
-                SpvOpImageSparseTexelsResident,
-                SpvOpImageSparseRead};
+  image_ops_ = {spv::Op::OpImageSampleImplicitLod,
+                spv::Op::OpImageSampleExplicitLod,
+                spv::Op::OpImageSampleDrefImplicitLod,
+                spv::Op::OpImageSampleDrefExplicitLod,
+                spv::Op::OpImageSampleProjImplicitLod,
+                spv::Op::OpImageSampleProjExplicitLod,
+                spv::Op::OpImageSampleProjDrefImplicitLod,
+                spv::Op::OpImageSampleProjDrefExplicitLod,
+                spv::Op::OpImageFetch,
+                spv::Op::OpImageGather,
+                spv::Op::OpImageDrefGather,
+                spv::Op::OpImageRead,
+                spv::Op::OpImageSparseSampleImplicitLod,
+                spv::Op::OpImageSparseSampleExplicitLod,
+                spv::Op::OpImageSparseSampleDrefImplicitLod,
+                spv::Op::OpImageSparseSampleDrefExplicitLod,
+                spv::Op::OpImageSparseSampleProjImplicitLod,
+                spv::Op::OpImageSparseSampleProjExplicitLod,
+                spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+                spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+                spv::Op::OpImageSparseFetch,
+                spv::Op::OpImageSparseGather,
+                spv::Op::OpImageSparseDrefGather,
+                spv::Op::OpImageSparseTexelsResident,
+                spv::Op::OpImageSparseRead};
   dref_image_ops_ = {
-      SpvOpImageSampleDrefImplicitLod,
-      SpvOpImageSampleDrefExplicitLod,
-      SpvOpImageSampleProjDrefImplicitLod,
-      SpvOpImageSampleProjDrefExplicitLod,
-      SpvOpImageDrefGather,
-      SpvOpImageSparseSampleDrefImplicitLod,
-      SpvOpImageSparseSampleDrefExplicitLod,
-      SpvOpImageSparseSampleProjDrefImplicitLod,
-      SpvOpImageSparseSampleProjDrefExplicitLod,
-      SpvOpImageSparseDrefGather,
+      spv::Op::OpImageSampleDrefImplicitLod,
+      spv::Op::OpImageSampleDrefExplicitLod,
+      spv::Op::OpImageSampleProjDrefImplicitLod,
+      spv::Op::OpImageSampleProjDrefExplicitLod,
+      spv::Op::OpImageDrefGather,
+      spv::Op::OpImageSparseSampleDrefImplicitLod,
+      spv::Op::OpImageSparseSampleDrefExplicitLod,
+      spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+      spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+      spv::Op::OpImageSparseDrefGather,
   };
   closure_ops_ = {
-      SpvOpVectorExtractDynamic,
-      SpvOpVectorInsertDynamic,
-      SpvOpVectorShuffle,
-      SpvOpCompositeConstruct,
-      SpvOpCompositeInsert,
-      SpvOpCompositeExtract,
-      SpvOpCopyObject,
-      SpvOpTranspose,
-      SpvOpPhi,
+      spv::Op::OpVectorExtractDynamic,
+      spv::Op::OpVectorInsertDynamic,
+      spv::Op::OpVectorShuffle,
+      spv::Op::OpCompositeConstruct,
+      spv::Op::OpCompositeInsert,
+      spv::Op::OpCompositeExtract,
+      spv::Op::OpCopyObject,
+      spv::Op::OpTranspose,
+      spv::Op::OpPhi,
   };
   relaxed_ids_set_.clear();
   converted_ids_.clear();
diff --git a/third_party/SPIRV-Tools/source/opt/convert_to_half_pass.h b/third_party/SPIRV-Tools/source/opt/convert_to_half_pass.h
index c6e84d1..feabfba 100644
--- a/third_party/SPIRV-Tools/source/opt/convert_to_half_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/convert_to_half_pass.h
@@ -120,20 +120,26 @@
   // Initialize state for converting to half
   void Initialize();
 
+  struct hasher {
+    size_t operator()(const spv::Op& op) const noexcept {
+      return std::hash<uint32_t>()(uint32_t(op));
+    }
+  };
+
   // Set of core operations to be processed
-  std::unordered_set<uint32_t> target_ops_core_;
+  std::unordered_set<spv::Op, hasher> target_ops_core_;
 
   // Set of 450 extension operations to be processed
   std::unordered_set<uint32_t> target_ops_450_;
 
   // Set of sample operations
-  std::unordered_set<uint32_t> image_ops_;
+  std::unordered_set<spv::Op, hasher> image_ops_;
 
   // Set of dref sample operations
-  std::unordered_set<uint32_t> dref_image_ops_;
+  std::unordered_set<spv::Op, hasher> dref_image_ops_;
 
   // Set of dref sample operations
-  std::unordered_set<uint32_t> closure_ops_;
+  std::unordered_set<spv::Op, hasher> closure_ops_;
 
   // Set of ids of all relaxed instructions
   std::unordered_set<uint32_t> relaxed_ids_set_;
diff --git a/third_party/SPIRV-Tools/source/opt/convert_to_sampled_image_pass.cpp b/third_party/SPIRV-Tools/source/opt/convert_to_sampled_image_pass.cpp
index e84d357..2effc3e 100644
--- a/third_party/SPIRV-Tools/source/opt/convert_to_sampled_image_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/convert_to_sampled_image_pass.cpp
@@ -70,7 +70,7 @@
 Instruction* GetNonCopyObjectDef(analysis::DefUseManager* def_use_mgr,
                                  uint32_t inst_id) {
   Instruction* inst = def_use_mgr->GetDef(inst_id);
-  while (inst->opcode() == SpvOpCopyObject) {
+  while (inst->opcode() == spv::Op::OpCopyObject) {
     inst_id = inst->GetSingleWordInOperand(0u);
     inst = def_use_mgr->GetDef(inst_id);
   }
@@ -87,8 +87,9 @@
   bool found_binding_to_convert = false;
   for (auto decorate :
        decoration_manager->GetDecorationsFor(inst.result_id(), false)) {
-    uint32_t decoration = decorate->GetSingleWordInOperand(1u);
-    if (decoration == SpvDecorationDescriptorSet) {
+    spv::Decoration decoration =
+        spv::Decoration(decorate->GetSingleWordInOperand(1u));
+    if (decoration == spv::Decoration::DescriptorSet) {
       if (found_descriptor_set_to_convert) {
         assert(false && "A resource has two OpDecorate for the descriptor set");
         return false;
@@ -96,7 +97,7 @@
       descriptor_set_binding->descriptor_set =
           decorate->GetSingleWordInOperand(2u);
       found_descriptor_set_to_convert = true;
-    } else if (decoration == SpvDecorationBinding) {
+    } else if (decoration == spv::Decoration::Binding) {
       if (found_binding_to_convert) {
         assert(false && "A resource has two OpDecorate for the binding");
         return false;
@@ -116,7 +117,7 @@
 
 const analysis::Type* ConvertToSampledImagePass::GetVariableType(
     const Instruction& variable) const {
-  if (variable.opcode() != SpvOpVariable) return nullptr;
+  if (variable.opcode() != spv::Op::OpVariable) return nullptr;
   auto* type = context()->get_type_mgr()->GetType(variable.type_id());
   auto* pointer_type = type->AsPointer();
   if (!pointer_type) return nullptr;
@@ -124,12 +125,12 @@
   return pointer_type->pointee_type();
 }
 
-SpvStorageClass ConvertToSampledImagePass::GetStorageClass(
+spv::StorageClass ConvertToSampledImagePass::GetStorageClass(
     const Instruction& variable) const {
-  assert(variable.opcode() == SpvOpVariable);
+  assert(variable.opcode() == spv::Op::OpVariable);
   auto* type = context()->get_type_mgr()->GetType(variable.type_id());
   auto* pointer_type = type->AsPointer();
-  if (!pointer_type) return SpvStorageClassMax;
+  if (!pointer_type) return spv::StorageClass::Max;
 
   return pointer_type->storage_class();
 }
@@ -205,12 +206,12 @@
 
 void ConvertToSampledImagePass::FindUses(const Instruction* inst,
                                          std::vector<Instruction*>* uses,
-                                         uint32_t user_opcode) const {
+                                         spv::Op user_opcode) const {
   auto* def_use_mgr = context()->get_def_use_mgr();
   def_use_mgr->ForEachUser(inst, [uses, user_opcode, this](Instruction* user) {
     if (user->opcode() == user_opcode) {
       uses->push_back(user);
-    } else if (user->opcode() == SpvOpCopyObject) {
+    } else if (user->opcode() == spv::Op::OpCopyObject) {
       FindUses(user, uses, user_opcode);
     }
   });
@@ -221,21 +222,21 @@
   auto* def_use_mgr = context()->get_def_use_mgr();
   def_use_mgr->ForEachUser(image, [uses, this](Instruction* user) {
     switch (user->opcode()) {
-      case SpvOpImageFetch:
-      case SpvOpImageRead:
-      case SpvOpImageWrite:
-      case SpvOpImageQueryFormat:
-      case SpvOpImageQueryOrder:
-      case SpvOpImageQuerySizeLod:
-      case SpvOpImageQuerySize:
-      case SpvOpImageQueryLevels:
-      case SpvOpImageQuerySamples:
-      case SpvOpImageSparseFetch:
+      case spv::Op::OpImageFetch:
+      case spv::Op::OpImageRead:
+      case spv::Op::OpImageWrite:
+      case spv::Op::OpImageQueryFormat:
+      case spv::Op::OpImageQueryOrder:
+      case spv::Op::OpImageQuerySizeLod:
+      case spv::Op::OpImageQuerySize:
+      case spv::Op::OpImageQueryLevels:
+      case spv::Op::OpImageQuerySamples:
+      case spv::Op::OpImageSparseFetch:
         uses->push_back(user);
       default:
         break;
     }
-    if (user->opcode() == SpvOpCopyObject) {
+    if (user->opcode() == spv::Op::OpCopyObject) {
       FindUsesOfImage(user, uses);
     }
   });
@@ -248,7 +249,7 @@
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
   return builder.AddUnaryOp(
       GetImageTypeOfSampledImage(context()->get_type_mgr(), sampled_image),
-      SpvOpImage, sampled_image->result_id());
+      spv::Op::OpImage, sampled_image->result_id());
 }
 
 uint32_t ConvertToSampledImagePass::GetSampledImageTypeForImage(
@@ -284,7 +285,7 @@
   auto* def_use_mgr = context()->get_def_use_mgr();
   uint32_t sampler_id = sampled_image_inst->GetSingleWordInOperand(1u);
   auto* sampler_load = def_use_mgr->GetDef(sampler_id);
-  if (sampler_load->opcode() != SpvOpLoad) return false;
+  if (sampler_load->opcode() != spv::Op::OpLoad) return false;
   auto* sampler = def_use_mgr->GetDef(sampler_load->GetSingleWordInOperand(0u));
   DescriptorSetAndBinding sampler_descriptor_set_binding;
   return GetDescriptorSetBinding(*sampler, &sampler_descriptor_set_binding) &&
@@ -295,7 +296,7 @@
     Instruction* image_load, Instruction* image_extraction,
     const DescriptorSetAndBinding& image_descriptor_set_binding) {
   std::vector<Instruction*> sampled_image_users;
-  FindUses(image_load, &sampled_image_users, SpvOpSampledImage);
+  FindUses(image_load, &sampled_image_users, spv::Op::OpSampledImage);
 
   auto* def_use_mgr = context()->get_def_use_mgr();
   for (auto* sampled_image_inst : sampled_image_users) {
@@ -328,7 +329,7 @@
       context()->get_type_mgr()->GetType(sampled_image_type_id);
   if (sampled_image_type == nullptr) return false;
   auto storage_class = GetStorageClass(*image_variable);
-  if (storage_class == SpvStorageClassMax) return false;
+  if (storage_class == spv::StorageClass::Max) return false;
   analysis::Pointer sampled_image_pointer(sampled_image_type, storage_class);
 
   // Make sure |image_variable| is behind its type i.e., avoid the forward
@@ -343,7 +344,7 @@
     Instruction* image_variable,
     const DescriptorSetAndBinding& descriptor_set_binding) {
   std::vector<Instruction*> image_variable_loads;
-  FindUses(image_variable, &image_variable_loads, SpvOpLoad);
+  FindUses(image_variable, &image_variable_loads, spv::Op::OpLoad);
   if (image_variable_loads.empty()) return Status::SuccessWithoutChange;
 
   const uint32_t sampled_image_type_id =
@@ -364,14 +365,14 @@
 
 bool ConvertToSampledImagePass::DoesSampledImageReferenceImage(
     Instruction* sampled_image_inst, Instruction* image_variable) {
-  if (sampled_image_inst->opcode() != SpvOpSampledImage) return false;
+  if (sampled_image_inst->opcode() != spv::Op::OpSampledImage) return false;
   auto* def_use_mgr = context()->get_def_use_mgr();
   auto* image_load = GetNonCopyObjectDef(
       def_use_mgr, sampled_image_inst->GetSingleWordInOperand(0u));
-  if (image_load->opcode() != SpvOpLoad) return false;
+  if (image_load->opcode() != spv::Op::OpLoad) return false;
   auto* image =
       GetNonCopyObjectDef(def_use_mgr, image_load->GetSingleWordInOperand(0u));
-  return image->opcode() == SpvOpVariable &&
+  return image->opcode() == spv::Op::OpVariable &&
          image->result_id() == image_variable->result_id();
 }
 
@@ -381,10 +382,10 @@
   if (image_to_be_combined_with == nullptr) return Status::Failure;
 
   std::vector<Instruction*> sampler_variable_loads;
-  FindUses(sampler_variable, &sampler_variable_loads, SpvOpLoad);
+  FindUses(sampler_variable, &sampler_variable_loads, spv::Op::OpLoad);
   for (auto* load : sampler_variable_loads) {
     std::vector<Instruction*> sampled_image_users;
-    FindUses(load, &sampled_image_users, SpvOpSampledImage);
+    FindUses(load, &sampled_image_users, spv::Op::OpSampledImage);
     for (auto* sampled_image_inst : sampled_image_users) {
       if (!DoesSampledImageReferenceImage(sampled_image_inst,
                                           image_to_be_combined_with)) {
diff --git a/third_party/SPIRV-Tools/source/opt/convert_to_sampled_image_pass.h b/third_party/SPIRV-Tools/source/opt/convert_to_sampled_image_pass.h
index d3938af..a8b1501 100644
--- a/third_party/SPIRV-Tools/source/opt/convert_to_sampled_image_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/convert_to_sampled_image_pass.h
@@ -120,13 +120,13 @@
   const analysis::Type* GetVariableType(const Instruction& variable) const;
 
   // Returns the storage class of |variable|.
-  SpvStorageClass GetStorageClass(const Instruction& variable) const;
+  spv::StorageClass GetStorageClass(const Instruction& variable) const;
 
   // Finds |inst|'s users whose opcode is |user_opcode| or users of OpCopyObject
   // instructions of |inst| whose opcode is |user_opcode| and puts them in
   // |uses|.
   void FindUses(const Instruction* inst, std::vector<Instruction*>* uses,
-                uint32_t user_opcode) const;
+                spv::Op user_opcode) const;
 
   // Finds OpImage* instructions using |image| or OpCopyObject instructions that
   // copy |image| and puts them in |uses|.
diff --git a/third_party/SPIRV-Tools/source/opt/copy_prop_arrays.cpp b/third_party/SPIRV-Tools/source/opt/copy_prop_arrays.cpp
index 321d496..66a268f 100644
--- a/third_party/SPIRV-Tools/source/opt/copy_prop_arrays.cpp
+++ b/third_party/SPIRV-Tools/source/opt/copy_prop_arrays.cpp
@@ -22,12 +22,12 @@
 namespace opt {
 namespace {
 
-const uint32_t kLoadPointerInOperand = 0;
-const uint32_t kStorePointerInOperand = 0;
-const uint32_t kStoreObjectInOperand = 1;
-const uint32_t kCompositeExtractObjectInOperand = 0;
-const uint32_t kTypePointerStorageClassInIdx = 0;
-const uint32_t kTypePointerPointeeInIdx = 1;
+constexpr uint32_t kLoadPointerInOperand = 0;
+constexpr uint32_t kStorePointerInOperand = 0;
+constexpr uint32_t kStoreObjectInOperand = 1;
+constexpr uint32_t kCompositeExtractObjectInOperand = 0;
+constexpr uint32_t kTypePointerStorageClassInIdx = 0;
+constexpr uint32_t kTypePointerPointeeInIdx = 1;
 
 bool IsDebugDeclareOrValue(Instruction* di) {
   auto dbg_opcode = di->GetCommonDebugOpcode();
@@ -46,8 +46,8 @@
 
     BasicBlock* entry_bb = &*function.begin();
 
-    for (auto var_inst = entry_bb->begin(); var_inst->opcode() == SpvOpVariable;
-         ++var_inst) {
+    for (auto var_inst = entry_bb->begin();
+         var_inst->opcode() == spv::Op::OpVariable; ++var_inst) {
       if (!IsPointerToArrayType(var_inst->type_id())) {
         continue;
       }
@@ -76,7 +76,7 @@
 std::unique_ptr<CopyPropagateArrays::MemoryObject>
 CopyPropagateArrays::FindSourceObjectIfPossible(Instruction* var_inst,
                                                 Instruction* store_inst) {
-  assert(var_inst->opcode() == SpvOpVariable && "Expecting a variable.");
+  assert(var_inst->opcode() == spv::Op::OpVariable && "Expecting a variable.");
 
   // Check that the variable is a composite object where |store_inst|
   // dominates all of its loads.
@@ -114,7 +114,7 @@
   Instruction* store_inst = nullptr;
   get_def_use_mgr()->WhileEachUser(
       var_inst, [&store_inst, var_inst](Instruction* use) {
-        if (use->opcode() == SpvOpStore &&
+        if (use->opcode() == spv::Op::OpStore &&
             use->GetSingleWordInOperand(kStorePointerInOperand) ==
                 var_inst->result_id()) {
           if (store_inst == nullptr) {
@@ -132,7 +132,7 @@
 void CopyPropagateArrays::PropagateObject(Instruction* var_inst,
                                           MemoryObject* source,
                                           Instruction* insertion_point) {
-  assert(var_inst->opcode() == SpvOpVariable &&
+  assert(var_inst->opcode() == spv::Op::OpVariable &&
          "This function propagates variables.");
 
   Instruction* new_access_chain = BuildNewAccessChain(insertion_point, source);
@@ -151,22 +151,32 @@
     return source->GetVariable();
   }
 
+  source->BuildConstants();
+  std::vector<uint32_t> access_ids(source->AccessChain().size());
+  std::transform(
+      source->AccessChain().cbegin(), source->AccessChain().cend(),
+      access_ids.begin(), [](const AccessChainEntry& entry) {
+        assert(entry.is_result_id && "Constants needs to be built first.");
+        return entry.result_id;
+      });
+
   return builder.AddAccessChain(source->GetPointerTypeId(this),
-                                source->GetVariable()->result_id(),
-                                source->AccessChain());
+                                source->GetVariable()->result_id(), access_ids);
 }
 
 bool CopyPropagateArrays::HasNoStores(Instruction* ptr_inst) {
   return get_def_use_mgr()->WhileEachUser(ptr_inst, [this](Instruction* use) {
-    if (use->opcode() == SpvOpLoad) {
+    if (use->opcode() == spv::Op::OpLoad) {
       return true;
-    } else if (use->opcode() == SpvOpAccessChain) {
+    } else if (use->opcode() == spv::Op::OpAccessChain) {
       return HasNoStores(use);
-    } else if (use->IsDecoration() || use->opcode() == SpvOpName) {
+    } else if (use->IsDecoration() || use->opcode() == spv::Op::OpName) {
       return true;
-    } else if (use->opcode() == SpvOpStore) {
+    } else if (use->opcode() == spv::Op::OpStore) {
       return false;
-    } else if (use->opcode() == SpvOpImageTexelPointer) {
+    } else if (use->opcode() == spv::Op::OpImageTexelPointer) {
+      return true;
+    } else if (use->opcode() == spv::Op::OpEntryPoint) {
       return true;
     }
     // Some other instruction.  Be conservative.
@@ -183,19 +193,19 @@
   return get_def_use_mgr()->WhileEachUser(
       ptr_inst,
       [this, store_inst, dominator_analysis, ptr_inst](Instruction* use) {
-        if (use->opcode() == SpvOpLoad ||
-            use->opcode() == SpvOpImageTexelPointer) {
+        if (use->opcode() == spv::Op::OpLoad ||
+            use->opcode() == spv::Op::OpImageTexelPointer) {
           // TODO: If there are many load in the same BB as |store_inst| the
           // time to do the multiple traverses can add up.  Consider collecting
           // those loads and doing a single traversal.
           return dominator_analysis->Dominates(store_inst, use);
-        } else if (use->opcode() == SpvOpAccessChain) {
+        } else if (use->opcode() == spv::Op::OpAccessChain) {
           return HasValidReferencesOnly(use, store_inst);
-        } else if (use->IsDecoration() || use->opcode() == SpvOpName) {
+        } else if (use->IsDecoration() || use->opcode() == spv::Op::OpName) {
           return true;
-        } else if (use->opcode() == SpvOpStore) {
+        } else if (use->opcode() == spv::Op::OpStore) {
           // If we are storing to part of the object it is not an candidate.
-          return ptr_inst->opcode() == SpvOpVariable &&
+          return ptr_inst->opcode() == spv::Op::OpVariable &&
                  store_inst->GetSingleWordInOperand(kStorePointerInOperand) ==
                      ptr_inst->result_id();
         } else if (IsDebugDeclareOrValue(use)) {
@@ -211,15 +221,15 @@
   Instruction* result_inst = context()->get_def_use_mgr()->GetDef(result);
 
   switch (result_inst->opcode()) {
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       return BuildMemoryObjectFromLoad(result_inst);
-    case SpvOpCompositeExtract:
+    case spv::Op::OpCompositeExtract:
       return BuildMemoryObjectFromExtract(result_inst);
-    case SpvOpCompositeConstruct:
+    case spv::Op::OpCompositeConstruct:
       return BuildMemoryObjectFromCompositeConstruct(result_inst);
-    case SpvOpCopyObject:
+    case spv::Op::OpCopyObject:
       return GetSourceObjectIfAny(result_inst->GetSingleWordInOperand(0));
-    case SpvOpCompositeInsert:
+    case spv::Op::OpCompositeInsert:
       return BuildMemoryObjectFromInsert(result_inst);
     default:
       return nullptr;
@@ -241,7 +251,7 @@
   //
   // It is built in reverse order because the different |OpAccessChain|
   // instructions are visited in reverse order from which they are applied.
-  while (current_inst->opcode() == SpvOpAccessChain) {
+  while (current_inst->opcode() == spv::Op::OpAccessChain) {
     for (uint32_t i = current_inst->NumInOperands() - 1; i >= 1; --i) {
       uint32_t element_index_id = current_inst->GetSingleWordInOperand(i);
       components_in_reverse.push_back(element_index_id);
@@ -253,7 +263,7 @@
   // instruction followed by a series of |OpAccessChain| instructions, then
   // return |nullptr| because we cannot identify the owner or access chain
   // exactly.
-  if (current_inst->opcode() != SpvOpVariable) {
+  if (current_inst->opcode() != spv::Op::OpVariable) {
     return nullptr;
   }
 
@@ -266,38 +276,28 @@
 
 std::unique_ptr<CopyPropagateArrays::MemoryObject>
 CopyPropagateArrays::BuildMemoryObjectFromExtract(Instruction* extract_inst) {
-  assert(extract_inst->opcode() == SpvOpCompositeExtract &&
+  assert(extract_inst->opcode() == spv::Op::OpCompositeExtract &&
          "Expecting an OpCompositeExtract instruction.");
-  analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
-
   std::unique_ptr<MemoryObject> result = GetSourceObjectIfAny(
       extract_inst->GetSingleWordInOperand(kCompositeExtractObjectInOperand));
 
-  if (result) {
-    analysis::Integer int_type(32, false);
-    const analysis::Type* uint32_type =
-        context()->get_type_mgr()->GetRegisteredType(&int_type);
-
-    std::vector<uint32_t> components;
-    // Convert the indices in the extract instruction to a series of ids that
-    // can be used by the |OpAccessChain| instruction.
-    for (uint32_t i = 1; i < extract_inst->NumInOperands(); ++i) {
-      uint32_t index = extract_inst->GetSingleWordInOperand(i);
-      const analysis::Constant* index_const =
-          const_mgr->GetConstant(uint32_type, {index});
-      components.push_back(
-          const_mgr->GetDefiningInstruction(index_const)->result_id());
-    }
-    result->GetMember(components);
-    return result;
+  if (!result) {
+    return nullptr;
   }
-  return nullptr;
+
+  // Copy the indices of the extract instruction to |OpAccessChain| indices.
+  std::vector<AccessChainEntry> components;
+  for (uint32_t i = 1; i < extract_inst->NumInOperands(); ++i) {
+    components.push_back({false, {extract_inst->GetSingleWordInOperand(i)}});
+  }
+  result->PushIndirection(components);
+  return result;
 }
 
 std::unique_ptr<CopyPropagateArrays::MemoryObject>
 CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct(
     Instruction* conststruct_inst) {
-  assert(conststruct_inst->opcode() == SpvOpCompositeConstruct &&
+  assert(conststruct_inst->opcode() == spv::Op::OpCompositeConstruct &&
          "Expecting an OpCompositeConstruct instruction.");
 
   // If every operand in the instruction are part of the same memory object, and
@@ -315,19 +315,12 @@
     return nullptr;
   }
 
-  analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
-  const analysis::Constant* last_access =
-      const_mgr->FindDeclaredConstant(memory_object->AccessChain().back());
-  if (!last_access || !last_access->type()->AsInteger()) {
+  AccessChainEntry last_access = memory_object->AccessChain().back();
+  if (!IsAccessChainIndexValidAndEqualTo(last_access, 0)) {
     return nullptr;
   }
 
-  if (last_access->GetU32() != 0) {
-    return nullptr;
-  }
-
-  memory_object->GetParent();
-
+  memory_object->PopIndirection();
   if (memory_object->GetNumberOfMembers() !=
       conststruct_inst->NumInOperands()) {
     return nullptr;
@@ -349,13 +342,8 @@
       return nullptr;
     }
 
-    last_access =
-        const_mgr->FindDeclaredConstant(member_object->AccessChain().back());
-    if (!last_access || !last_access->type()->AsInteger()) {
-      return nullptr;
-    }
-
-    if (last_access->GetU32() != i) {
+    last_access = member_object->AccessChain().back();
+    if (!IsAccessChainIndexValidAndEqualTo(last_access, i)) {
       return nullptr;
     }
   }
@@ -364,7 +352,7 @@
 
 std::unique_ptr<CopyPropagateArrays::MemoryObject>
 CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) {
-  assert(insert_inst->opcode() == SpvOpCompositeInsert &&
+  assert(insert_inst->opcode() == spv::Op::OpCompositeInsert &&
          "Expecting an OpCompositeInsert instruction.");
 
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
@@ -409,22 +397,17 @@
     return nullptr;
   }
 
-  const analysis::Constant* last_access =
-      const_mgr->FindDeclaredConstant(memory_object->AccessChain().back());
-  if (!last_access || !last_access->type()->AsInteger()) {
+  AccessChainEntry last_access = memory_object->AccessChain().back();
+  if (!IsAccessChainIndexValidAndEqualTo(last_access, number_of_elements - 1)) {
     return nullptr;
   }
 
-  if (last_access->GetU32() != number_of_elements - 1) {
-    return nullptr;
-  }
-
-  memory_object->GetParent();
+  memory_object->PopIndirection();
 
   Instruction* current_insert =
       def_use_mgr->GetDef(insert_inst->GetSingleWordInOperand(1));
   for (uint32_t i = number_of_elements - 1; i > 0; --i) {
-    if (current_insert->opcode() != SpvOpCompositeInsert) {
+    if (current_insert->opcode() != spv::Op::OpCompositeInsert) {
       return nullptr;
     }
 
@@ -456,14 +439,9 @@
       return nullptr;
     }
 
-    const analysis::Constant* current_last_access =
-        const_mgr->FindDeclaredConstant(
-            current_memory_object->AccessChain().back());
-    if (!current_last_access || !current_last_access->type()->AsInteger()) {
-      return nullptr;
-    }
-
-    if (current_last_access->GetU32() != i - 1) {
+    AccessChainEntry current_last_access =
+        current_memory_object->AccessChain().back();
+    if (!IsAccessChainIndexValidAndEqualTo(current_last_access, i - 1)) {
       return nullptr;
     }
     current_insert =
@@ -473,6 +451,21 @@
   return memory_object;
 }
 
+bool CopyPropagateArrays::IsAccessChainIndexValidAndEqualTo(
+    const AccessChainEntry& entry, uint32_t value) const {
+  if (!entry.is_result_id) {
+    return entry.immediate == value;
+  }
+
+  analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
+  const analysis::Constant* constant =
+      const_mgr->FindDeclaredConstant(entry.result_id);
+  if (!constant || !constant->type()->AsInteger()) {
+    return false;
+  }
+  return constant->GetU32() == value;
+}
+
 bool CopyPropagateArrays::IsPointerToArrayType(uint32_t type_id) {
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   analysis::Pointer* pointer_type = type_mgr->GetType(type_id)->AsPointer();
@@ -507,7 +500,7 @@
     if (IsDebugDeclareOrValue(use)) return true;
 
     switch (use->opcode()) {
-      case SpvOpLoad: {
+      case spv::Op::OpLoad: {
         analysis::Pointer* pointer_type = type->AsPointer();
         uint32_t new_type_id = type_mgr->GetId(pointer_type->pointee_type());
 
@@ -516,7 +509,7 @@
         }
         return true;
       }
-      case SpvOpAccessChain: {
+      case spv::Op::OpAccessChain: {
         analysis::Pointer* pointer_type = type->AsPointer();
         const analysis::Type* pointee_type = pointer_type->pointee_type();
 
@@ -530,6 +523,12 @@
             // Variable index means the type is a type where every element
             // is the same type.  Use element 0 to get the type.
             access_chain.push_back(0);
+
+            // We are trying to access a struct with variable indices.
+            // This cannot happen.
+            if (pointee_type->kind() == analysis::Type::kStruct) {
+              return false;
+            }
           }
         }
 
@@ -548,7 +547,7 @@
         }
         return true;
       }
-      case SpvOpCompositeExtract: {
+      case spv::Op::OpCompositeExtract: {
         std::vector<uint32_t> access_chain;
         for (uint32_t i = 1; i < use->NumInOperands(); ++i) {
           access_chain.push_back(use->GetSingleWordInOperand(i));
@@ -566,13 +565,13 @@
         }
         return true;
       }
-      case SpvOpStore:
+      case spv::Op::OpStore:
         // If needed, we can create an element-by-element copy to change the
         // type of the value being stored.  This way we can always handled
         // stores.
         return true;
-      case SpvOpImageTexelPointer:
-      case SpvOpName:
+      case spv::Op::OpImageTexelPointer:
+      case spv::Op::OpName:
         return true;
       default:
         return use->IsDecoration();
@@ -599,8 +598,8 @@
     if (use->IsCommonDebugInstr()) {
       switch (use->GetCommonDebugOpcode()) {
         case CommonDebugInfoDebugDeclare: {
-          if (new_ptr_inst->opcode() == SpvOpVariable ||
-              new_ptr_inst->opcode() == SpvOpFunctionParameter) {
+          if (new_ptr_inst->opcode() == spv::Op::OpVariable ||
+              new_ptr_inst->opcode() == spv::Op::OpFunctionParameter) {
             context()->ForgetUses(use);
             use->SetOperand(index, {new_ptr_inst->result_id()});
             context()->AnalyzeUses(use);
@@ -641,7 +640,7 @@
     }
 
     switch (use->opcode()) {
-      case SpvOpLoad: {
+      case spv::Op::OpLoad: {
         // Replace the actual use.
         context()->ForgetUses(use);
         use->SetOperand(index, {new_ptr_inst->result_id()});
@@ -659,7 +658,7 @@
           context()->AnalyzeUses(use);
         }
       } break;
-      case SpvOpAccessChain: {
+      case spv::Op::OpAccessChain: {
         // Update the actual use.
         context()->ForgetUses(use);
         use->SetOperand(index, {new_ptr_inst->result_id()});
@@ -686,7 +685,7 @@
             pointer_type_inst->GetSingleWordInOperand(kTypePointerPointeeInIdx),
             access_chain);
 
-        SpvStorageClass storage_class = static_cast<SpvStorageClass>(
+        spv::StorageClass storage_class = static_cast<spv::StorageClass>(
             pointer_type_inst->GetSingleWordInOperand(
                 kTypePointerStorageClassInIdx));
 
@@ -701,7 +700,7 @@
           context()->AnalyzeUses(use);
         }
       } break;
-      case SpvOpCompositeExtract: {
+      case spv::Op::OpCompositeExtract: {
         // Update the actual use.
         context()->ForgetUses(use);
         use->SetOperand(index, {new_ptr_inst->result_id()});
@@ -722,7 +721,7 @@
           context()->AnalyzeUses(use);
         }
       } break;
-      case SpvOpStore:
+      case spv::Op::OpStore:
         // If the use is the pointer, then it is the single store to that
         // variable.  We do not want to replace it.  Instead, it will become
         // dead after all of the loads are removed, and ADCE will get rid of it.
@@ -745,11 +744,11 @@
           context()->AnalyzeUses(use);
         }
         break;
-      case SpvOpDecorate:
+      case spv::Op::OpDecorate:
       // We treat an OpImageTexelPointer as a load.  The result type should
       // always have the Image storage class, and should not need to be
       // updated.
-      case SpvOpImageTexelPointer:
+      case spv::Op::OpImageTexelPointer:
         // Replace the actual use.
         context()->ForgetUses(use);
         use->SetOperand(index, {new_ptr_inst->result_id()});
@@ -767,13 +766,13 @@
   for (uint32_t element_index : access_chain) {
     Instruction* type_inst = get_def_use_mgr()->GetDef(id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
         id = type_inst->GetSingleWordInOperand(0);
         break;
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         id = type_inst->GetSingleWordInOperand(element_index);
         break;
       default:
@@ -785,8 +784,8 @@
   return id;
 }
 
-void CopyPropagateArrays::MemoryObject::GetMember(
-    const std::vector<uint32_t>& access_chain) {
+void CopyPropagateArrays::MemoryObject::PushIndirection(
+    const std::vector<AccessChainEntry>& access_chain) {
   access_chain_.insert(access_chain_.end(), access_chain.begin(),
                        access_chain.end());
 }
@@ -821,23 +820,29 @@
 template <class iterator>
 CopyPropagateArrays::MemoryObject::MemoryObject(Instruction* var_inst,
                                                 iterator begin, iterator end)
-    : variable_inst_(var_inst), access_chain_(begin, end) {}
+    : variable_inst_(var_inst) {
+  std::transform(begin, end, std::back_inserter(access_chain_),
+                 [](uint32_t id) {
+                   return AccessChainEntry{true, {id}};
+                 });
+}
 
 std::vector<uint32_t> CopyPropagateArrays::MemoryObject::GetAccessIds() const {
   analysis::ConstantManager* const_mgr =
       variable_inst_->context()->get_constant_mgr();
 
-  std::vector<uint32_t> access_indices;
-  for (uint32_t id : AccessChain()) {
-    const analysis::Constant* element_index_const =
-        const_mgr->FindDeclaredConstant(id);
-    if (!element_index_const) {
-      access_indices.push_back(0);
-    } else {
-      access_indices.push_back(element_index_const->GetU32());
-    }
-  }
-  return access_indices;
+  std::vector<uint32_t> indices(AccessChain().size());
+  std::transform(AccessChain().cbegin(), AccessChain().cend(), indices.begin(),
+                 [&const_mgr](const AccessChainEntry& entry) {
+                   if (entry.is_result_id) {
+                     const analysis::Constant* constant =
+                         const_mgr->FindDeclaredConstant(entry.result_id);
+                     return constant == nullptr ? 0 : constant->GetU32();
+                   }
+
+                   return entry.immediate;
+                 });
+  return indices;
 }
 
 bool CopyPropagateArrays::MemoryObject::Contains(
@@ -858,5 +863,24 @@
   return true;
 }
 
+void CopyPropagateArrays::MemoryObject::BuildConstants() {
+  for (auto& entry : access_chain_) {
+    if (entry.is_result_id) {
+      continue;
+    }
+
+    auto context = variable_inst_->context();
+    analysis::Integer int_type(32, false);
+    const analysis::Type* uint32_type =
+        context->get_type_mgr()->GetRegisteredType(&int_type);
+    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
+    const analysis::Constant* index_const =
+        const_mgr->GetConstant(uint32_type, {entry.immediate});
+    entry.result_id =
+        const_mgr->GetDefiningInstruction(index_const)->result_id();
+    entry.is_result_id = true;
+  }
+}
+
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/copy_prop_arrays.h b/third_party/SPIRV-Tools/source/opt/copy_prop_arrays.h
index 46a508c..7486f80 100644
--- a/third_party/SPIRV-Tools/source/opt/copy_prop_arrays.h
+++ b/third_party/SPIRV-Tools/source/opt/copy_prop_arrays.h
@@ -52,6 +52,22 @@
   }
 
  private:
+  // Represents one index in the OpAccessChain instruction. It can be either
+  // an instruction's result_id (OpConstant by ex), or a immediate value.
+  // Immediate values are used to prepare the final access chain without
+  // creating OpConstant instructions until done.
+  struct AccessChainEntry {
+    bool is_result_id;
+    union {
+      uint32_t result_id;
+      uint32_t immediate;
+    };
+
+    bool operator!=(const AccessChainEntry& other) const {
+      return other.is_result_id != is_result_id || other.result_id != result_id;
+    }
+  };
+
   // The class used to identify a particular memory object.  This memory object
   // will be owned by a particular variable, meaning that the memory is part of
   // that variable.  It could be the entire variable or a member of the
@@ -70,12 +86,12 @@
     // (starting from the current member).  The elements in |access_chain| are
     // interpreted the same as the indices in the |OpAccessChain|
     // instruction.
-    void GetMember(const std::vector<uint32_t>& access_chain);
+    void PushIndirection(const std::vector<AccessChainEntry>& access_chain);
 
     // Change |this| to now represent the first enclosing object to which it
     // belongs.  (Remove the last element off the access_chain). It is invalid
     // to call this function if |this| does not represent a member of its owner.
-    void GetParent() {
+    void PopIndirection() {
       assert(IsMember());
       access_chain_.pop_back();
     }
@@ -95,7 +111,13 @@
     // member that |this| represents starting from the owning variable.  These
     // values are to be interpreted the same way the indices are in an
     // |OpAccessChain| instruction.
-    const std::vector<uint32_t>& AccessChain() const { return access_chain_; }
+    const std::vector<AccessChainEntry>& AccessChain() const {
+      return access_chain_;
+    }
+
+    // Converts all immediate values in the AccessChain their OpConstant
+    // equivalent.
+    void BuildConstants();
 
     // Returns the type id of the pointer type that can be used to point to this
     // memory object.
@@ -112,13 +134,13 @@
           var_pointer_inst->GetSingleWordInOperand(1), GetAccessIds());
 
       uint32_t member_pointer_type_id = type_mgr->FindPointerToType(
-          member_type_id, static_cast<SpvStorageClass>(
+          member_type_id, static_cast<spv::StorageClass>(
                               var_pointer_inst->GetSingleWordInOperand(0)));
       return member_pointer_type_id;
     }
 
     // Returns the storage class of the memory object.
-    SpvStorageClass GetStorageClass() const {
+    spv::StorageClass GetStorageClass() const {
       analysis::TypeManager* type_mgr =
           GetVariable()->context()->get_type_mgr();
       const analysis::Pointer* pointer_type =
@@ -137,7 +159,7 @@
     // The access chain to reach the particular member the memory object
     // represents.  It should be interpreted the same way the indices in an
     // |OpAccessChain| are interpreted.
-    std::vector<uint32_t> access_chain_;
+    std::vector<AccessChainEntry> access_chain_;
     std::vector<uint32_t> GetAccessIds() const;
   };
 
@@ -192,10 +214,14 @@
   std::unique_ptr<MemoryObject> BuildMemoryObjectFromInsert(
       Instruction* insert_inst);
 
+  // Return true if the given entry can represent the given value.
+  bool IsAccessChainIndexValidAndEqualTo(const AccessChainEntry& entry,
+                                         uint32_t value) const;
+
   // Return true if |type_id| is a pointer type whose pointee type is an array.
   bool IsPointerToArrayType(uint32_t type_id);
 
-  // Returns true of there are not stores using |ptr_inst| or something derived
+  // Returns true if there are not stores using |ptr_inst| or something derived
   // from it.
   bool HasNoStores(Instruction* ptr_inst);
 
diff --git a/third_party/SPIRV-Tools/source/opt/dataflow.cpp b/third_party/SPIRV-Tools/source/opt/dataflow.cpp
index c91fad0..8d74e41 100644
--- a/third_party/SPIRV-Tools/source/opt/dataflow.cpp
+++ b/third_party/SPIRV-Tools/source/opt/dataflow.cpp
@@ -78,7 +78,7 @@
 }
 
 void ForwardDataFlowAnalysis::EnqueueBlockSuccessors(Instruction* inst) {
-  if (inst->opcode() != SpvOpLabel) return;
+  if (inst->opcode() != spv::Op::OpLabel) return;
   context()
       .cfg()
       ->block(inst->result_id())
diff --git a/third_party/SPIRV-Tools/source/opt/dead_branch_elim_pass.cpp b/third_party/SPIRV-Tools/source/opt/dead_branch_elim_pass.cpp
index cc616ca..319b8d1 100644
--- a/third_party/SPIRV-Tools/source/opt/dead_branch_elim_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/dead_branch_elim_pass.cpp
@@ -29,28 +29,25 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
-
-const uint32_t kBranchCondTrueLabIdInIdx = 1;
-const uint32_t kBranchCondFalseLabIdInIdx = 2;
-
-}  // anonymous namespace
+constexpr uint32_t kBranchCondTrueLabIdInIdx = 1;
+constexpr uint32_t kBranchCondFalseLabIdInIdx = 2;
+}  // namespace
 
 bool DeadBranchElimPass::GetConstCondition(uint32_t condId, bool* condVal) {
   bool condIsConst;
   Instruction* cInst = get_def_use_mgr()->GetDef(condId);
   switch (cInst->opcode()) {
-    case SpvOpConstantNull:
-    case SpvOpConstantFalse: {
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpConstantFalse: {
       *condVal = false;
       condIsConst = true;
     } break;
-    case SpvOpConstantTrue: {
+    case spv::Op::OpConstantTrue: {
       *condVal = true;
       condIsConst = true;
     } break;
-    case SpvOpLogicalNot: {
+    case spv::Op::OpLogicalNot: {
       bool negVal;
       condIsConst =
           GetConstCondition(cInst->GetSingleWordInOperand(0), &negVal);
@@ -65,13 +62,13 @@
   Instruction* sInst = get_def_use_mgr()->GetDef(selId);
   uint32_t typeId = sInst->type_id();
   Instruction* typeInst = get_def_use_mgr()->GetDef(typeId);
-  if (!typeInst || (typeInst->opcode() != SpvOpTypeInt)) return false;
+  if (!typeInst || (typeInst->opcode() != spv::Op::OpTypeInt)) return false;
   // TODO(greg-lunarg): Support non-32 bit ints
   if (typeInst->GetSingleWordInOperand(0) != 32) return false;
-  if (sInst->opcode() == SpvOpConstant) {
+  if (sInst->opcode() == spv::Op::OpConstant) {
     *selVal = sInst->GetSingleWordInOperand(0);
     return true;
-  } else if (sInst->opcode() == SpvOpConstantNull) {
+  } else if (sInst->opcode() == spv::Op::OpConstantNull) {
     *selVal = 0;
     return true;
   }
@@ -81,7 +78,7 @@
 void DeadBranchElimPass::AddBranch(uint32_t labelId, BasicBlock* bp) {
   assert(get_def_use_mgr()->GetDef(labelId) != nullptr);
   std::unique_ptr<Instruction> newBranch(
-      new Instruction(context(), SpvOpBranch, 0, 0,
+      new Instruction(context(), spv::Op::OpBranch, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}}));
   context()->AnalyzeDefUse(&*newBranch);
   context()->set_instr_block(&*newBranch, bp);
@@ -115,13 +112,13 @@
     Instruction* terminator = block->terminator();
     uint32_t live_lab_id = 0;
     // Check if the terminator has a single valid successor.
-    if (terminator->opcode() == SpvOpBranchConditional) {
+    if (terminator->opcode() == spv::Op::OpBranchConditional) {
       bool condVal;
       if (GetConstCondition(terminator->GetSingleWordInOperand(0u), &condVal)) {
         live_lab_id = terminator->GetSingleWordInOperand(
             condVal ? kBranchCondTrueLabIdInIdx : kBranchCondFalseLabIdInIdx);
       }
-    } else if (terminator->opcode() == SpvOpSwitch) {
+    } else if (terminator->opcode() == spv::Op::OpSwitch) {
       uint32_t sel_val;
       if (GetConstInteger(terminator->GetSingleWordInOperand(0u), &sel_val)) {
         // Search switch operands for selector value, set live_lab_id to
@@ -194,8 +191,8 @@
                                         uint32_t live_lab_id) {
   Instruction* merge_inst = block->GetMergeInst();
   Instruction* terminator = block->terminator();
-  if (merge_inst && merge_inst->opcode() == SpvOpSelectionMerge) {
-    if (merge_inst->NextNode()->opcode() == SpvOpSwitch &&
+  if (merge_inst && merge_inst->opcode() == spv::Op::OpSelectionMerge) {
+    if (merge_inst->NextNode()->opcode() == spv::Op::OpSwitch &&
         SwitchHasNestedBreak(block->id())) {
       if (terminator->NumInOperands() == 2) {
         // We cannot remove the branch, and it already has a single case, so no
@@ -266,7 +263,7 @@
   for (auto& block : *func) {
     if (live_blocks.count(&block)) {
       for (auto iter = block.begin(); iter != block.end();) {
-        if (iter->opcode() != SpvOpPhi) {
+        if (iter->opcode() != spv::Op::OpPhi) {
           break;
         }
 
@@ -292,7 +289,7 @@
               cont_iter->second == &block && inst->NumInOperands() > 4) {
             if (get_def_use_mgr()
                     ->GetDef(inst->GetSingleWordInOperand(i - 1))
-                    ->opcode() == SpvOpUndef) {
+                    ->opcode() == spv::Op::OpUndef) {
               // Already undef incoming value, no change necessary.
               operands.push_back(inst->GetInOperand(i - 1));
               operands.push_back(inst->GetInOperand(i));
@@ -378,14 +375,14 @@
     if (unreachable_continues.count(&*ebi)) {
       uint32_t cont_id = unreachable_continues.find(&*ebi)->second->id();
       if (ebi->begin() != ebi->tail() ||
-          ebi->terminator()->opcode() != SpvOpBranch ||
+          ebi->terminator()->opcode() != spv::Op::OpBranch ||
           ebi->terminator()->GetSingleWordInOperand(0u) != cont_id) {
         // Make unreachable, but leave the label.
         KillAllInsts(&*ebi, false);
         // Add unconditional branch to header.
         assert(unreachable_continues.count(&*ebi));
         ebi->AddInstruction(MakeUnique<Instruction>(
-            context(), SpvOpBranch, 0, 0,
+            context(), spv::Op::OpBranch, 0, 0,
             std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_id}}}));
         get_def_use_mgr()->AnalyzeInstUse(&*ebi->tail());
         context()->set_instr_block(&*ebi->tail(), &*ebi);
@@ -394,12 +391,12 @@
       ++ebi;
     } else if (unreachable_merges.count(&*ebi)) {
       if (ebi->begin() != ebi->tail() ||
-          ebi->terminator()->opcode() != SpvOpUnreachable) {
+          ebi->terminator()->opcode() != spv::Op::OpUnreachable) {
         // Make unreachable, but leave the label.
         KillAllInsts(&*ebi, false);
         // Add unreachable terminator.
         ebi->AddInstruction(
-            MakeUnique<Instruction>(context(), SpvOpUnreachable, 0, 0,
+            MakeUnique<Instruction>(context(), spv::Op::OpUnreachable, 0, 0,
                                     std::initializer_list<Operand>{}));
         context()->AnalyzeUses(ebi->terminator());
         context()->set_instr_block(ebi->terminator(), &*ebi);
@@ -459,22 +456,13 @@
   };
 
   // Reorders blocks according to structured order.
-  ProcessFunction reorder_structured = [this](Function* function) {
-    std::list<BasicBlock*> order;
-    context()->cfg()->ComputeStructuredOrder(function, &*function->begin(),
-                                             &order);
-    std::vector<BasicBlock*> blocks;
-    for (auto block : order) {
-      blocks.push_back(block);
-    }
-    for (uint32_t i = 1; i < blocks.size(); ++i) {
-      function->MoveBasicBlockToAfter(blocks[i]->id(), blocks[i - 1]);
-    }
+  ProcessFunction reorder_structured = [](Function* function) {
+    function->ReorderBasicBlocksInStructuredOrder();
     return true;
   };
 
   // Structured order is more intuitive so use it where possible.
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
     context()->ProcessReachableCallTree(reorder_structured);
   } else {
     context()->ProcessReachableCallTree(reorder_dominators);
@@ -486,7 +474,8 @@
   // support required in KillNamesAndDecorates().
   // TODO(greg-lunarg): Add support for OpGroupDecorate
   for (auto& ai : get_module()->annotations())
-    if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
+    if (ai.opcode() == spv::Op::OpGroupDecorate)
+      return Status::SuccessWithoutChange;
   // Process all entry point functions
   ProcessFunction pfn = [this](Function* fp) {
     return EliminateDeadBranches(fp);
@@ -510,7 +499,7 @@
     Instruction* branch = start_block->terminator();
     uint32_t next_block_id = 0;
     switch (branch->opcode()) {
-      case SpvOpBranchConditional:
+      case spv::Op::OpBranchConditional:
         next_block_id = start_block->MergeBlockIdIfAny();
         if (next_block_id == 0) {
           // If a possible target is the |loop_merge_id| or |loop_continue_id|,
@@ -539,7 +528,7 @@
           }
         }
         break;
-      case SpvOpSwitch:
+      case spv::Op::OpSwitch:
         next_block_id = start_block->MergeBlockIdIfAny();
         if (next_block_id == 0) {
           // A switch with no merge instructions can have at most 5 targets:
@@ -587,7 +576,7 @@
           // The fall through is case 3.
         }
         break;
-      case SpvOpBranch:
+      case spv::Op::OpBranch:
         // Need to check if this is the header of a loop nested in the
         // selection construct.
         next_block_id = start_block->MergeBlockIdIfAny();
diff --git a/third_party/SPIRV-Tools/source/opt/dead_insert_elim_pass.cpp b/third_party/SPIRV-Tools/source/opt/dead_insert_elim_pass.cpp
index d877f0f..a486903 100644
--- a/third_party/SPIRV-Tools/source/opt/dead_insert_elim_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/dead_insert_elim_pass.cpp
@@ -23,32 +23,29 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
-
-const uint32_t kTypeVectorCountInIdx = 1;
-const uint32_t kTypeMatrixCountInIdx = 1;
-const uint32_t kTypeArrayLengthIdInIdx = 1;
-const uint32_t kTypeIntWidthInIdx = 0;
-const uint32_t kConstantValueInIdx = 0;
-const uint32_t kInsertObjectIdInIdx = 0;
-const uint32_t kInsertCompositeIdInIdx = 1;
-
-}  // anonymous namespace
+constexpr uint32_t kTypeVectorCountInIdx = 1;
+constexpr uint32_t kTypeMatrixCountInIdx = 1;
+constexpr uint32_t kTypeArrayLengthIdInIdx = 1;
+constexpr uint32_t kTypeIntWidthInIdx = 0;
+constexpr uint32_t kConstantValueInIdx = 0;
+constexpr uint32_t kInsertObjectIdInIdx = 0;
+constexpr uint32_t kInsertCompositeIdInIdx = 1;
+}  // namespace
 
 uint32_t DeadInsertElimPass::NumComponents(Instruction* typeInst) {
   switch (typeInst->opcode()) {
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       return typeInst->GetSingleWordInOperand(kTypeVectorCountInIdx);
     } break;
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       return typeInst->GetSingleWordInOperand(kTypeMatrixCountInIdx);
     } break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       uint32_t lenId =
           typeInst->GetSingleWordInOperand(kTypeArrayLengthIdInIdx);
       Instruction* lenInst = get_def_use_mgr()->GetDef(lenId);
-      if (lenInst->opcode() != SpvOpConstant) return 0;
+      if (lenInst->opcode() != spv::Op::OpConstant) return 0;
       uint32_t lenTypeId = lenInst->type_id();
       Instruction* lenTypeInst = get_def_use_mgr()->GetDef(lenTypeId);
       // TODO(greg-lunarg): Support non-32-bit array length
@@ -56,7 +53,7 @@
         return 0;
       return lenInst->GetSingleWordInOperand(kConstantValueInIdx);
     } break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       return typeInst->NumInOperands();
     } break;
     default: { return 0; } break;
@@ -68,10 +65,10 @@
     uint32_t extOffset, std::unordered_set<uint32_t>* visited_phis) {
   // Not currently optimizing array inserts.
   Instruction* typeInst = get_def_use_mgr()->GetDef(insertChain->type_id());
-  if (typeInst->opcode() == SpvOpTypeArray) return;
+  if (typeInst->opcode() == spv::Op::OpTypeArray) return;
   // Insert chains are only composed of inserts and phis
-  if (insertChain->opcode() != SpvOpCompositeInsert &&
-      insertChain->opcode() != SpvOpPhi)
+  if (insertChain->opcode() != spv::Op::OpCompositeInsert &&
+      insertChain->opcode() != spv::Op::OpPhi)
     return;
   // If extract indices are empty, mark all subcomponents if type
   // is constant length.
@@ -89,7 +86,7 @@
     }
   }
   Instruction* insInst = insertChain;
-  while (insInst->opcode() == SpvOpCompositeInsert) {
+  while (insInst->opcode() == spv::Op::OpCompositeInsert) {
     // If no extract indices, mark insert and inserted object (which might
     // also be an insert chain) and continue up the chain though the input
     // composite.
@@ -139,7 +136,7 @@
     insInst = get_def_use_mgr()->GetDef(compId);
   }
   // If insert chain ended with phi, do recursive call on each operand
-  if (insInst->opcode() != SpvOpPhi) return;
+  if (insInst->opcode() != spv::Op::OpPhi) return;
   // Mark phi visited to prevent potential infinite loop. If phi is already
   // visited, return to avoid infinite loop.
   if (visited_phis->count(insInst->result_id()) != 0) return;
@@ -179,17 +176,17 @@
   for (auto bi = func->begin(); bi != func->end(); ++bi) {
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
       // Only process Inserts and composite Phis
-      SpvOp op = ii->opcode();
+      spv::Op op = ii->opcode();
       Instruction* typeInst = get_def_use_mgr()->GetDef(ii->type_id());
-      if (op != SpvOpCompositeInsert &&
-          (op != SpvOpPhi || !spvOpcodeIsComposite(typeInst->opcode())))
+      if (op != spv::Op::OpCompositeInsert &&
+          (op != spv::Op::OpPhi || !spvOpcodeIsComposite(typeInst->opcode())))
         continue;
       // The marking algorithm can be expensive for large arrays and the
       // efficacy of eliminating dead inserts into arrays is questionable.
       // Skip optimizing array inserts for now. Just mark them live.
       // TODO(greg-lunarg): Eliminate dead array inserts
-      if (op == SpvOpCompositeInsert) {
-        if (typeInst->opcode() == SpvOpTypeArray) {
+      if (op == spv::Op::OpCompositeInsert) {
+        if (typeInst->opcode() == spv::Op::OpTypeArray) {
           liveInserts_.insert(ii->result_id());
           continue;
         }
@@ -198,11 +195,11 @@
       get_def_use_mgr()->ForEachUser(id, [&ii, this](Instruction* user) {
         if (user->IsCommonDebugInstr()) return;
         switch (user->opcode()) {
-          case SpvOpCompositeInsert:
-          case SpvOpPhi:
+          case spv::Op::OpCompositeInsert:
+          case spv::Op::OpPhi:
             // Use by insert or phi does not initiate marking
             break;
-          case SpvOpCompositeExtract: {
+          case spv::Op::OpCompositeExtract: {
             // Capture extract indices
             std::vector<uint32_t> extIndices;
             uint32_t icnt = 0;
@@ -226,7 +223,7 @@
   std::vector<Instruction*> dead_instructions;
   for (auto bi = func->begin(); bi != func->end(); ++bi) {
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
-      if (ii->opcode() != SpvOpCompositeInsert) continue;
+      if (ii->opcode() != spv::Op::OpCompositeInsert) continue;
       const uint32_t id = ii->result_id();
       if (liveInserts_.find(id) != liveInserts_.end()) continue;
       const uint32_t replId =
diff --git a/third_party/SPIRV-Tools/source/opt/dead_variable_elimination.cpp b/third_party/SPIRV-Tools/source/opt/dead_variable_elimination.cpp
index 2837106..e39132c 100644
--- a/third_party/SPIRV-Tools/source/opt/dead_variable_elimination.cpp
+++ b/third_party/SPIRV-Tools/source/opt/dead_variable_elimination.cpp
@@ -33,7 +33,7 @@
 
   // Get the reference count for all of the global OpVariable instructions.
   for (auto& inst : context()->types_values()) {
-    if (inst.opcode() != SpvOp::SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       continue;
     }
 
@@ -43,11 +43,11 @@
     // Check the linkage.  If it is exported, it could be reference somewhere
     // else, so we must keep the variable around.
     get_decoration_mgr()->ForEachDecoration(
-        result_id, SpvDecorationLinkageAttributes,
+        result_id, uint32_t(spv::Decoration::LinkageAttributes),
         [&count](const Instruction& linkage_instruction) {
           uint32_t last_operand = linkage_instruction.NumOperands() - 1;
-          if (linkage_instruction.GetSingleWordOperand(last_operand) ==
-              SpvLinkageTypeExport) {
+          if (spv::LinkageType(linkage_instruction.GetSingleWordOperand(
+                  last_operand)) == spv::LinkageType::Export) {
             count = kMustKeep;
           }
         });
@@ -57,7 +57,8 @@
       // at the uses and count the number of real references.
       count = 0;
       get_def_use_mgr()->ForEachUser(result_id, [&count](Instruction* user) {
-        if (!IsAnnotationInst(user->opcode()) && user->opcode() != SpvOpName) {
+        if (!IsAnnotationInst(user->opcode()) &&
+            user->opcode() != spv::Op::OpName) {
           ++count;
         }
       });
@@ -81,7 +82,7 @@
 
 void DeadVariableElimination::DeleteVariable(uint32_t result_id) {
   Instruction* inst = get_def_use_mgr()->GetDef(result_id);
-  assert(inst->opcode() == SpvOpVariable &&
+  assert(inst->opcode() == spv::Op::OpVariable &&
          "Should not be trying to delete anything other than an OpVariable.");
 
   // Look for an initializer that references another variable.  We need to know
@@ -93,7 +94,7 @@
     // TODO: Handle OpSpecConstantOP which might be defined in terms of other
     // variables.  Will probably require a unified dead code pass that does all
     // instruction types.  (Issue 906)
-    if (initializer->opcode() == SpvOpVariable) {
+    if (initializer->opcode() == spv::Op::OpVariable) {
       uint32_t initializer_id = initializer->result_id();
       size_t& count = reference_count_[initializer_id];
       if (count != kMustKeep) {
diff --git a/third_party/SPIRV-Tools/source/opt/debug_info_manager.cpp b/third_party/SPIRV-Tools/source/opt/debug_info_manager.cpp
index c1df625..0ec392f 100644
--- a/third_party/SPIRV-Tools/source/opt/debug_info_manager.cpp
+++ b/third_party/SPIRV-Tools/source/opt/debug_info_manager.cpp
@@ -1,4 +1,5 @@
-// Copyright (c) 2020 Google LLC
+// Copyright (c) 2020-2022 Google LLC
+// Copyright (c) 2022 LunarG Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -21,31 +22,31 @@
 // Constants for OpenCL.DebugInfo.100 & NonSemantic.Shader.DebugInfo.100
 // extension instructions.
 
-static const uint32_t kOpLineOperandLineIndex = 1;
-static const uint32_t kLineOperandIndexDebugFunction = 7;
-static const uint32_t kLineOperandIndexDebugLexicalBlock = 5;
-static const uint32_t kDebugFunctionOperandFunctionIndex = 13;
-static const uint32_t kDebugFunctionDefinitionOperandDebugFunctionIndex = 4;
-static const uint32_t kDebugFunctionDefinitionOperandOpFunctionIndex = 5;
-static const uint32_t kDebugFunctionOperandParentIndex = 9;
-static const uint32_t kDebugTypeCompositeOperandParentIndex = 9;
-static const uint32_t kDebugLexicalBlockOperandParentIndex = 7;
-static const uint32_t kDebugInlinedAtOperandInlinedIndex = 6;
-static const uint32_t kDebugExpressOperandOperationIndex = 4;
-static const uint32_t kDebugDeclareOperandLocalVariableIndex = 4;
-static const uint32_t kDebugDeclareOperandVariableIndex = 5;
-static const uint32_t kDebugValueOperandExpressionIndex = 6;
-static const uint32_t kDebugOperationOperandOperationIndex = 4;
-static const uint32_t kOpVariableOperandStorageClassIndex = 2;
-static const uint32_t kDebugLocalVariableOperandParentIndex = 9;
-static const uint32_t kExtInstInstructionInIdx = 1;
-static const uint32_t kDebugGlobalVariableOperandFlagsIndex = 12;
-static const uint32_t kDebugLocalVariableOperandFlagsIndex = 10;
-
 namespace spvtools {
 namespace opt {
 namespace analysis {
 namespace {
+constexpr uint32_t kOpLineOperandLineIndex = 1;
+constexpr uint32_t kLineOperandIndexDebugFunction = 7;
+constexpr uint32_t kLineOperandIndexDebugLexicalBlock = 5;
+constexpr uint32_t kLineOperandIndexDebugLine = 5;
+constexpr uint32_t kDebugFunctionOperandFunctionIndex = 13;
+constexpr uint32_t kDebugFunctionDefinitionOperandDebugFunctionIndex = 4;
+constexpr uint32_t kDebugFunctionDefinitionOperandOpFunctionIndex = 5;
+constexpr uint32_t kDebugFunctionOperandParentIndex = 9;
+constexpr uint32_t kDebugTypeCompositeOperandParentIndex = 9;
+constexpr uint32_t kDebugLexicalBlockOperandParentIndex = 7;
+constexpr uint32_t kDebugInlinedAtOperandInlinedIndex = 6;
+constexpr uint32_t kDebugExpressOperandOperationIndex = 4;
+constexpr uint32_t kDebugDeclareOperandLocalVariableIndex = 4;
+constexpr uint32_t kDebugDeclareOperandVariableIndex = 5;
+constexpr uint32_t kDebugValueOperandExpressionIndex = 6;
+constexpr uint32_t kDebugOperationOperandOperationIndex = 4;
+constexpr uint32_t kOpVariableOperandStorageClassIndex = 2;
+constexpr uint32_t kDebugLocalVariableOperandParentIndex = 9;
+constexpr uint32_t kExtInstInstructionInIdx = 1;
+constexpr uint32_t kDebugGlobalVariableOperandFlagsIndex = 12;
+constexpr uint32_t kDebugLocalVariableOperandFlagsIndex = 10;
 
 void SetInlinedOperand(Instruction* dbg_inlined_at, uint32_t inlined_operand) {
   assert(dbg_inlined_at);
@@ -154,7 +155,8 @@
 uint32_t AddNewConstInGlobals(IRContext* context, uint32_t const_value) {
   uint32_t id = context->TakeNextId();
   std::unique_ptr<Instruction> new_const(new Instruction(
-      context, SpvOpConstant, context->get_type_mgr()->GetUIntTypeId(), id,
+      context, spv::Op::OpConstant, context->get_type_mgr()->GetUIntTypeId(),
+      id,
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
            {const_value}},
@@ -210,7 +212,15 @@
         break;
     }
   } else {
-    line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex);
+    if (line->opcode() == spv::Op::OpLine) {
+      line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex);
+    } else if (line->GetShader100DebugOpcode() ==
+               NonSemanticShaderDebugInfo100DebugLine) {
+      line_number = line->GetSingleWordOperand(kLineOperandIndexDebugLine);
+    } else {
+      assert(false &&
+             "Unreachable. A line instruction must be OpLine or DebugLine");
+    }
 
     // If we need the line number as an ID, generate that constant now.
     // If Constant or DefUse managers are invalid, generate constant
@@ -219,7 +229,8 @@
     // DefUse manager which cannot be done during inlining. The extra
     // constants that may be generated here is likely not significant
     // and will likely be cleaned up in later passes.
-    if (line_number_type == spv_operand_type_t::SPV_OPERAND_TYPE_ID) {
+    if (line_number_type == spv_operand_type_t::SPV_OPERAND_TYPE_ID &&
+        line->opcode() == spv::Op::OpLine) {
       if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse) ||
           !context()->AreAnalysesValid(IRContext::Analysis::kAnalysisConstants))
         line_number = AddNewConstInGlobals(context(), line_number);
@@ -230,7 +241,7 @@
 
   uint32_t result_id = context()->TakeNextId();
   std::unique_ptr<Instruction> inlined_at(new Instruction(
-      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
+      context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
       result_id,
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {setId}},
@@ -323,8 +334,8 @@
 
   if (context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
     deref_operation = std::unique_ptr<Instruction>(new Instruction(
-        context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
-        result_id,
+        context(), spv::Op::OpExtInst,
+        context()->get_type_mgr()->GetVoidTypeId(), result_id,
         {
             {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
             {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
@@ -337,7 +348,7 @@
         NonSemanticShaderDebugInfo100Deref);
 
     deref_operation = std::unique_ptr<Instruction>(
-        new Instruction(context(), SpvOpExtInst,
+        new Instruction(context(), spv::Op::OpExtInst,
                         context()->get_type_mgr()->GetVoidTypeId(), result_id,
                         {
                             {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
@@ -379,7 +390,7 @@
 
   uint32_t result_id = context()->TakeNextId();
   std::unique_ptr<Instruction> dbg_info_none_inst(new Instruction(
-      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
+      context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
       result_id,
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
@@ -403,7 +414,7 @@
 
   uint32_t result_id = context()->TakeNextId();
   std::unique_ptr<Instruction> empty_debug_expr(new Instruction(
-      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
+      context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
       result_id,
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
@@ -516,7 +527,7 @@
   assert(scope != nullptr);
 
   std::vector<uint32_t> scope_ids;
-  if (scope->opcode() == SpvOpPhi) {
+  if (scope->opcode() == spv::Op::OpPhi) {
     scope_ids.push_back(scope->GetDebugScope().GetLexicalScope());
     for (uint32_t i = 0; i < scope->NumInOperands(); i += 2) {
       auto* value = context()->get_def_use_mgr()->GetDef(
@@ -546,10 +557,10 @@
   return false;
 }
 
-bool DebugInfoManager::AddDebugValueIfVarDeclIsVisible(
-    Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
-    Instruction* insert_pos,
-    std::unordered_set<Instruction*>* invisible_decls) {
+bool DebugInfoManager::AddDebugValueForVariable(Instruction* scope_and_line,
+                                                uint32_t variable_id,
+                                                uint32_t value_id,
+                                                Instruction* insert_pos) {
   assert(scope_and_line != nullptr);
 
   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
@@ -557,16 +568,11 @@
 
   bool modified = false;
   for (auto* dbg_decl_or_val : dbg_decl_itr->second) {
-    if (!IsDeclareVisibleToInstr(dbg_decl_or_val, scope_and_line)) {
-      if (invisible_decls) invisible_decls->insert(dbg_decl_or_val);
-      continue;
-    }
-
     // Avoid inserting the new DebugValue between OpPhi or OpVariable
     // instructions.
     Instruction* insert_before = insert_pos->NextNode();
-    while (insert_before->opcode() == SpvOpPhi ||
-           insert_before->opcode() == SpvOpVariable) {
+    while (insert_before->opcode() == spv::Op::OpPhi ||
+           insert_before->opcode() == spv::Op::OpVariable) {
       insert_before = insert_before->NextNode();
     }
     modified |= AddDebugValueForDecl(dbg_decl_or_val, value_id, insert_before,
@@ -647,9 +653,10 @@
   }
 
   auto* var = context()->get_def_use_mgr()->GetDef(var_id);
-  if (var->opcode() == SpvOpVariable &&
-      SpvStorageClass(var->GetSingleWordOperand(
-          kOpVariableOperandStorageClassIndex)) == SpvStorageClassFunction) {
+  if (var->opcode() == spv::Op::OpVariable &&
+      spv::StorageClass(
+          var->GetSingleWordOperand(kOpVariableOperandStorageClassIndex)) ==
+          spv::StorageClass::Function) {
     return var_id;
   }
   return 0;
@@ -756,8 +763,8 @@
       CommonDebugInfoDebugGlobalVariable) {
     return;
   }
-  assert(local_var->opcode() == SpvOpVariable ||
-         local_var->opcode() == SpvOpFunctionParameter);
+  assert(local_var->opcode() == spv::Op::OpVariable ||
+         local_var->opcode() == spv::Op::OpFunctionParameter);
 
   // Convert |dbg_global_var| to DebugLocalVariable
   dbg_global_var->SetInOperand(kExtInstInstructionInIdx,
@@ -774,7 +781,7 @@
 
   // Create a DebugDeclare
   std::unique_ptr<Instruction> new_dbg_decl(new Instruction(
-      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
+      context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
       context()->TakeNextId(),
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
@@ -788,7 +795,7 @@
       }));
   // Must insert after all OpVariables in block
   Instruction* insert_before = local_var;
-  while (insert_before->opcode() == SpvOpVariable)
+  while (insert_before->opcode() == spv::Op::OpVariable)
     insert_before = insert_before->NextNode();
   auto* added_dbg_decl = insert_before->InsertBefore(std::move(new_dbg_decl));
   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
@@ -849,7 +856,7 @@
     fn_id_to_dbg_fn_.erase(fn_id);
   }
   if (instr->GetShader100DebugOpcode() ==
-      NonSemanticShaderDebugInfo100DebugFunction) {
+      NonSemanticShaderDebugInfo100DebugFunctionDefinition) {
     auto fn_id = instr->GetSingleWordOperand(
         kDebugFunctionDefinitionOperandOpFunctionIndex);
     fn_id_to_dbg_fn_.erase(fn_id);
diff --git a/third_party/SPIRV-Tools/source/opt/debug_info_manager.h b/third_party/SPIRV-Tools/source/opt/debug_info_manager.h
index df34b30..abb7b9a 100644
--- a/third_party/SPIRV-Tools/source/opt/debug_info_manager.h
+++ b/third_party/SPIRV-Tools/source/opt/debug_info_manager.h
@@ -15,6 +15,7 @@
 #ifndef SOURCE_OPT_DEBUG_INFO_MANAGER_H_
 #define SOURCE_OPT_DEBUG_INFO_MANAGER_H_
 
+#include <set>
 #include <unordered_map>
 #include <unordered_set>
 
@@ -144,12 +145,10 @@
   // Generates a DebugValue instruction with value |value_id| for every local
   // variable that is in the scope of |scope_and_line| and whose memory is
   // |variable_id| and inserts it after the instruction |insert_pos|.
-  // Returns whether a DebugValue is added or not. |invisible_decls| returns
-  // DebugDeclares invisible to |scope_and_line|.
-  bool AddDebugValueIfVarDeclIsVisible(
-      Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
-      Instruction* insert_pos,
-      std::unordered_set<Instruction*>* invisible_decls);
+  // Returns whether a DebugValue is added or not.
+  bool AddDebugValueForVariable(Instruction* scope_and_line,
+                                uint32_t variable_id, uint32_t value_id,
+                                Instruction* insert_pos);
 
   // Creates a DebugValue for DebugDeclare |dbg_decl| and inserts it before
   // |insert_before|. The new DebugValue has the same line and scope as
@@ -244,9 +243,18 @@
   // operand is the function.
   std::unordered_map<uint32_t, Instruction*> fn_id_to_dbg_fn_;
 
+  // Orders Instruction* for use in associative containers (i.e. less than
+  // ordering). Unique Id is used.
+  typedef Instruction* InstPtr;
+  struct InstPtrLess {
+    bool operator()(const InstPtr& lhs, const InstPtr& rhs) const {
+      return lhs->unique_id() < rhs->unique_id();
+    }
+  };
+
   // Mapping from variable or value ids to DebugDeclare or DebugValue
   // instructions whose operand is the variable or value.
-  std::unordered_map<uint32_t, std::unordered_set<Instruction*>>
+  std::unordered_map<uint32_t, std::set<InstPtr, InstPtrLess>>
       var_id_to_dbg_decl_;
 
   // Mapping from DebugScope ids to users.
diff --git a/third_party/SPIRV-Tools/source/opt/decoration_manager.cpp b/third_party/SPIRV-Tools/source/opt/decoration_manager.cpp
index 2146c35..1393d48 100644
--- a/third_party/SPIRV-Tools/source/opt/decoration_manager.cpp
+++ b/third_party/SPIRV-Tools/source/opt/decoration_manager.cpp
@@ -22,6 +22,9 @@
 
 #include "source/opt/ir_context.h"
 
+namespace spvtools {
+namespace opt {
+namespace analysis {
 namespace {
 using InstructionVector = std::vector<const spvtools::opt::Instruction*>;
 using DecorationSet = std::set<std::u32string>;
@@ -49,10 +52,6 @@
 }
 }  // namespace
 
-namespace spvtools {
-namespace opt {
-namespace analysis {
-
 bool DecorationManager::RemoveDecorationsFrom(
     uint32_t id, std::function<bool(const Instruction&)> pred) {
   bool was_modified = false;
@@ -76,8 +75,8 @@
   // applying the group.
   std::unordered_set<const Instruction*> indirect_decorations_to_remove;
   for (Instruction* inst : decorations_info.indirect_decorations) {
-    assert(inst->opcode() == SpvOpGroupDecorate ||
-           inst->opcode() == SpvOpGroupMemberDecorate);
+    assert(inst->opcode() == spv::Op::OpGroupDecorate ||
+           inst->opcode() == spv::Op::OpGroupMemberDecorate);
 
     std::vector<Instruction*> group_decorations_to_keep;
     const uint32_t group_id = inst->GetSingleWordInOperand(0u);
@@ -99,7 +98,8 @@
     }
 
     // Otherwise, remove |id| from the targets of |group_id|
-    const uint32_t stride = inst->opcode() == SpvOpGroupDecorate ? 1u : 2u;
+    const uint32_t stride =
+        inst->opcode() == spv::Op::OpGroupDecorate ? 1u : 2u;
     for (uint32_t i = 1u; i < inst->NumInOperands();) {
       if (inst->GetSingleWordInOperand(i) != id) {
         i += stride;
@@ -212,16 +212,16 @@
           }
 
           switch (inst->opcode()) {
-            case SpvOpDecorate:
+            case spv::Op::OpDecorate:
               decorate_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpMemberDecorate:
+            case spv::Op::OpMemberDecorate:
               member_decorate_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpDecorateId:
+            case spv::Op::OpDecorateId:
               decorate_id_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpDecorateStringGOOGLE:
+            case spv::Op::OpDecorateStringGOOGLE:
               decorate_string_set->emplace(std::move(decoration_payload));
               break;
             default:
@@ -278,16 +278,16 @@
           }
 
           switch (inst->opcode()) {
-            case SpvOpDecorate:
+            case spv::Op::OpDecorate:
               decorate_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpMemberDecorate:
+            case spv::Op::OpMemberDecorate:
               member_decorate_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpDecorateId:
+            case spv::Op::OpDecorateId:
               decorate_id_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpDecorateStringGOOGLE:
+            case spv::Op::OpDecorateStringGOOGLE:
               decorate_string_set->emplace(std::move(decoration_payload));
               break;
             default:
@@ -328,10 +328,10 @@
                                               const Instruction* inst2,
                                               bool ignore_target) const {
   switch (inst1->opcode()) {
-    case SpvOpDecorate:
-    case SpvOpMemberDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
       break;
     default:
       return false;
@@ -358,17 +358,18 @@
 
 void DecorationManager::AddDecoration(Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorate: {
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorate: {
       const auto target_id = inst->GetSingleWordInOperand(0u);
       id_to_decoration_insts_[target_id].direct_decorations.push_back(inst);
       break;
     }
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate: {
-      const uint32_t start = inst->opcode() == SpvOpGroupDecorate ? 1u : 2u;
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate: {
+      const uint32_t start =
+          inst->opcode() == spv::Op::OpGroupDecorate ? 1u : 2u;
       const uint32_t stride = start;
       for (uint32_t i = start; i < inst->NumInOperands(); i += stride) {
         const auto target_id = inst->GetSingleWordInOperand(i);
@@ -384,7 +385,7 @@
   }
 }
 
-void DecorationManager::AddDecoration(SpvOp opcode,
+void DecorationManager::AddDecoration(spv::Op opcode,
                                       std::vector<Operand> opnds) {
   IRContext* ctx = module_->context();
   std::unique_ptr<Instruction> newDecoOp(
@@ -394,7 +395,7 @@
 
 void DecorationManager::AddDecoration(uint32_t inst_id, uint32_t decoration) {
   AddDecoration(
-      SpvOpDecorate,
+      spv::Op::OpDecorate,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inst_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration}}});
 }
@@ -402,7 +403,7 @@
 void DecorationManager::AddDecorationVal(uint32_t inst_id, uint32_t decoration,
                                          uint32_t decoration_value) {
   AddDecoration(
-      SpvOpDecorate,
+      spv::Op::OpDecorate,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inst_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -413,7 +414,7 @@
                                             uint32_t decoration,
                                             uint32_t decoration_value) {
   AddDecoration(
-      SpvOpMemberDecorate,
+      spv::Op::OpMemberDecorate,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inst_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {member}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration}},
@@ -436,9 +437,10 @@
       [include_linkage,
        &decorations](const std::vector<Instruction*>& direct_decorations) {
         for (Instruction* inst : direct_decorations) {
-          const bool is_linkage = inst->opcode() == SpvOpDecorate &&
-                                  inst->GetSingleWordInOperand(1u) ==
-                                      SpvDecorationLinkageAttributes;
+          const bool is_linkage =
+              inst->opcode() == spv::Op::OpDecorate &&
+              spv::Decoration(inst->GetSingleWordInOperand(1u)) ==
+                  spv::Decoration::LinkageAttributes;
           if (include_linkage || !is_linkage) decorations.push_back(inst);
         }
       };
@@ -462,14 +464,14 @@
     std::function<bool(const Instruction&)> f) {
   for (const Instruction* inst : GetDecorationsFor(id, true)) {
     switch (inst->opcode()) {
-      case SpvOpMemberDecorate:
+      case spv::Op::OpMemberDecorate:
         if (inst->GetSingleWordInOperand(2) == decoration) {
           if (!f(*inst)) return false;
         }
         break;
-      case SpvOpDecorate:
-      case SpvOpDecorateId:
-      case SpvOpDecorateStringGOOGLE:
+      case spv::Op::OpDecorate:
+      case spv::Op::OpDecorateId:
+      case spv::Op::OpDecorateStringGOOGLE:
         if (inst->GetSingleWordInOperand(1) == decoration) {
           if (!f(*inst)) return false;
         }
@@ -523,14 +525,14 @@
       decoration_list->second.indirect_decorations;
   for (Instruction* inst : indirect_decorations) {
     switch (inst->opcode()) {
-      case SpvOpGroupDecorate:
+      case spv::Op::OpGroupDecorate:
         context->ForgetUses(inst);
         // add |to| to list of decorated id's
         inst->AddOperand(
             Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {to}));
         context->AnalyzeUses(inst);
         break;
-      case SpvOpGroupMemberDecorate: {
+      case spv::Op::OpGroupMemberDecorate: {
         context->ForgetUses(inst);
         // for each (id == from), add (to, literal) as operands
         const uint32_t num_operands = inst->NumOperands();
@@ -554,13 +556,13 @@
 
 void DecorationManager::CloneDecorations(
     uint32_t from, uint32_t to,
-    const std::vector<SpvDecoration>& decorations_to_copy) {
+    const std::vector<spv::Decoration>& decorations_to_copy) {
   const auto decoration_list = id_to_decoration_insts_.find(from);
   if (decoration_list == id_to_decoration_insts_.end()) return;
   auto context = module_->context();
   for (Instruction* inst : decoration_list->second.direct_decorations) {
     if (std::find(decorations_to_copy.begin(), decorations_to_copy.end(),
-                  inst->GetSingleWordInOperand(1)) ==
+                  spv::Decoration(inst->GetSingleWordInOperand(1))) ==
         decorations_to_copy.end()) {
       continue;
     }
@@ -579,11 +581,11 @@
       decoration_list->second.indirect_decorations;
   for (Instruction* inst : indirect_decorations) {
     switch (inst->opcode()) {
-      case SpvOpGroupDecorate:
+      case spv::Op::OpGroupDecorate:
         CloneDecorations(inst->GetSingleWordInOperand(0), to,
                          decorations_to_copy);
         break;
-      case SpvOpGroupMemberDecorate: {
+      case spv::Op::OpGroupMemberDecorate: {
         assert(false && "The source id is not suppose to be a type.");
         break;
       }
@@ -599,18 +601,19 @@
   };
 
   switch (inst->opcode()) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorate: {
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorate: {
       const auto target_id = inst->GetSingleWordInOperand(0u);
       auto const iter = id_to_decoration_insts_.find(target_id);
       if (iter == id_to_decoration_insts_.end()) return;
       remove_from_container(iter->second.direct_decorations);
     } break;
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate: {
-      const uint32_t stride = inst->opcode() == SpvOpGroupDecorate ? 1u : 2u;
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate: {
+      const uint32_t stride =
+          inst->opcode() == spv::Op::OpGroupDecorate ? 1u : 2u;
       for (uint32_t i = 1u; i < inst->NumInOperands(); i += stride) {
         const auto target_id = inst->GetSingleWordInOperand(i);
         auto const iter = id_to_decoration_insts_.find(target_id);
diff --git a/third_party/SPIRV-Tools/source/opt/decoration_manager.h b/third_party/SPIRV-Tools/source/opt/decoration_manager.h
index fe78f2c..1a0d1b1 100644
--- a/third_party/SPIRV-Tools/source/opt/decoration_manager.h
+++ b/third_party/SPIRV-Tools/source/opt/decoration_manager.h
@@ -71,14 +71,14 @@
                                               bool include_linkage);
   std::vector<const Instruction*> GetDecorationsFor(uint32_t id,
                                                     bool include_linkage) const;
-  // Returns whether two IDs have the same decorations. Two SpvOpGroupDecorate
-  // instructions that apply the same decorations but to different IDs, still
-  // count as being the same.
+  // Returns whether two IDs have the same decorations. Two
+  // spv::Op::OpGroupDecorate instructions that apply the same decorations but
+  // to different IDs, still count as being the same.
   bool HaveTheSameDecorations(uint32_t id1, uint32_t id2) const;
 
-  // Returns whether two IDs have the same decorations. Two SpvOpGroupDecorate
-  // instructions that apply the same decorations but to different IDs, still
-  // count as being the same.
+  // Returns whether two IDs have the same decorations. Two
+  // spv::Op::OpGroupDecorate instructions that apply the same decorations but
+  // to different IDs, still count as being the same.
   bool HaveSubsetOfDecorations(uint32_t id1, uint32_t id2) const;
 
   // Returns whether the two decorations instructions are the same and are
@@ -123,14 +123,15 @@
   // Same as above, but only clone the decoration if the decoration operand is
   // in |decorations_to_copy|.  This function has the extra restriction that
   // |from| and |to| must not be an object, not a type.
-  void CloneDecorations(uint32_t from, uint32_t to,
-                        const std::vector<SpvDecoration>& decorations_to_copy);
+  void CloneDecorations(
+      uint32_t from, uint32_t to,
+      const std::vector<spv::Decoration>& decorations_to_copy);
 
   // Informs the decoration manager of a new decoration that it needs to track.
   void AddDecoration(Instruction* inst);
 
   // Add decoration with |opcode| and operands |opnds|.
-  void AddDecoration(SpvOp opcode, const std::vector<Operand> opnds);
+  void AddDecoration(spv::Op opcode, const std::vector<Operand> opnds);
 
   // Add |decoration| of |inst_id| to module.
   void AddDecoration(uint32_t inst_id, uint32_t decoration);
@@ -195,9 +196,9 @@
 
   // Mapping from ids to the instructions applying a decoration to those ids.
   // In other words, for each id you get all decoration instructions
-  // referencing that id, be it directly (SpvOpDecorate, SpvOpMemberDecorate
-  // and SpvOpDecorateId), or indirectly (SpvOpGroupDecorate,
-  // SpvOpMemberGroupDecorate).
+  // referencing that id, be it directly (spv::Op::OpDecorate,
+  // spv::Op::OpMemberDecorate and spv::Op::OpDecorateId), or indirectly
+  // (spv::Op::OpGroupDecorate, spv::Op::OpMemberGroupDecorate).
   std::unordered_map<uint32_t, TargetData> id_to_decoration_insts_;
   // The enclosing module.
   Module* module_;
diff --git a/third_party/SPIRV-Tools/source/opt/desc_sroa.cpp b/third_party/SPIRV-Tools/source/opt/desc_sroa.cpp
index b130ca8..8da0c86 100644
--- a/third_party/SPIRV-Tools/source/opt/desc_sroa.cpp
+++ b/third_party/SPIRV-Tools/source/opt/desc_sroa.cpp
@@ -22,8 +22,9 @@
 namespace {
 
 bool IsDecorationBinding(Instruction* inst) {
-  if (inst->opcode() != SpvOpDecorate) return false;
-  return inst->GetSingleWordInOperand(1u) == SpvDecorationBinding;
+  if (inst->opcode() != spv::Op::OpDecorate) return false;
+  return spv::Decoration(inst->GetSingleWordInOperand(1u)) ==
+         spv::Decoration::Binding;
 }
 
 }  // namespace
@@ -56,7 +57,7 @@
   bool failed = !get_def_use_mgr()->WhileEachUser(
       var->result_id(),
       [this, &access_chain_work_list, &load_work_list](Instruction* use) {
-        if (use->opcode() == SpvOpName) {
+        if (use->opcode() == spv::Op::OpName) {
           return true;
         }
 
@@ -65,11 +66,11 @@
         }
 
         switch (use->opcode()) {
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain:
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain:
             access_chain_work_list.push_back(use);
             return true;
-          case SpvOpLoad:
+          case spv::Op::OpLoad:
             load_work_list.push_back(use);
             return true;
           default:
@@ -184,7 +185,7 @@
   // Handle OpMemberDecorate instructions.
   for (auto old_decoration : get_decoration_mgr()->GetDecorationsFor(
            old_var_type->result_id(), true)) {
-    assert(old_decoration->opcode() == SpvOpMemberDecorate);
+    assert(old_decoration->opcode() == spv::Op::OpMemberDecorate);
     if (old_decoration->GetSingleWordInOperand(1u) != index) continue;
     CreateNewDecorationForMemberDecorate(old_decoration, new_var_id);
   }
@@ -212,8 +213,8 @@
 
 void DescriptorScalarReplacement::CreateNewDecorationForNewVariable(
     Instruction* old_decoration, uint32_t new_var_id, uint32_t new_binding) {
-  assert(old_decoration->opcode() == SpvOpDecorate ||
-         old_decoration->opcode() == SpvOpDecorateString);
+  assert(old_decoration->opcode() == spv::Op::OpDecorate ||
+         old_decoration->opcode() == spv::Op::OpDecorateString);
   std::unique_ptr<Instruction> new_decoration(old_decoration->Clone(context()));
   new_decoration->SetInOperand(0, {new_var_id});
 
@@ -231,25 +232,25 @@
   auto new_decorate_operand_end = old_member_decoration->end();
   operands.insert(operands.end(), new_decorate_operand_begin,
                   new_decorate_operand_end);
-  get_decoration_mgr()->AddDecoration(SpvOpDecorate, std::move(operands));
+  get_decoration_mgr()->AddDecoration(spv::Op::OpDecorate, std::move(operands));
 }
 
 uint32_t DescriptorScalarReplacement::CreateReplacementVariable(
     Instruction* var, uint32_t idx) {
   // The storage class for the new variable is the same as the original.
-  SpvStorageClass storage_class =
-      static_cast<SpvStorageClass>(var->GetSingleWordInOperand(0));
+  spv::StorageClass storage_class =
+      static_cast<spv::StorageClass>(var->GetSingleWordInOperand(0));
 
   // The type for the new variable will be a pointer to type of the elements of
   // the array.
   uint32_t ptr_type_id = var->type_id();
   Instruction* ptr_type_inst = get_def_use_mgr()->GetDef(ptr_type_id);
-  assert(ptr_type_inst->opcode() == SpvOpTypePointer &&
+  assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Variable should be a pointer to an array or structure.");
   uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand(1);
   Instruction* pointee_type_inst = get_def_use_mgr()->GetDef(pointee_type_id);
-  const bool is_array = pointee_type_inst->opcode() == SpvOpTypeArray;
-  const bool is_struct = pointee_type_inst->opcode() == SpvOpTypeStruct;
+  const bool is_array = pointee_type_inst->opcode() == spv::Op::OpTypeArray;
+  const bool is_struct = pointee_type_inst->opcode() == spv::Op::OpTypeStruct;
   assert((is_array || is_struct) &&
          "Variable should be a pointer to an array or structure.");
 
@@ -263,7 +264,7 @@
   // Create the variable.
   uint32_t id = TakeNextId();
   std::unique_ptr<Instruction> variable(
-      new Instruction(context(), SpvOpVariable, ptr_element_type_id, id,
+      new Instruction(context(), spv::Op::OpVariable, ptr_element_type_id, id,
                       std::initializer_list<Operand>{
                           {SPV_OPERAND_TYPE_STORAGE_CLASS,
                            {static_cast<uint32_t>(storage_class)}}}));
@@ -293,7 +294,7 @@
     }
 
     std::unique_ptr<Instruction> new_name(new Instruction(
-        context(), SpvOpName, 0, 0,
+        context(), spv::Op::OpName, 0, 0,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {id}},
             {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}));
@@ -315,14 +316,14 @@
   Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
 
   // If it's a pointer, look at the underlying type.
-  if (type_inst->opcode() == SpvOpTypePointer) {
+  if (type_inst->opcode() == spv::Op::OpTypePointer) {
     type_id = type_inst->GetSingleWordInOperand(1);
     type_inst = get_def_use_mgr()->GetDef(type_id);
   }
 
   // Arrays consume N*M binding numbers where N is the array length, and M is
   // the number of bindings used by each array element.
-  if (type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeArray) {
     uint32_t element_type_id = type_inst->GetSingleWordInOperand(0);
     uint32_t length_id = type_inst->GetSingleWordInOperand(1);
     const analysis::Constant* length_const =
@@ -335,7 +336,7 @@
 
   // The number of bindings consumed by a structure is the sum of the bindings
   // used by its members.
-  if (type_inst->opcode() == SpvOpTypeStruct &&
+  if (type_inst->opcode() == spv::Op::OpTypeStruct &&
       !descsroautil::IsTypeOfStructuredBuffer(context(), type_inst)) {
     uint32_t sum = 0;
     for (uint32_t i = 0; i < type_inst->NumInOperands(); i++)
@@ -353,12 +354,12 @@
   // |value| is the OpLoad instruction that has loaded |var|.
   // The function expects all users of |value| to be OpCompositeExtract
   // instructions. Otherwise the function returns false with an error message.
-  assert(value->opcode() == SpvOpLoad);
+  assert(value->opcode() == spv::Op::OpLoad);
   assert(value->GetSingleWordInOperand(0) == var->result_id());
   std::vector<Instruction*> work_list;
   bool failed = !get_def_use_mgr()->WhileEachUser(
       value->result_id(), [this, &work_list](Instruction* use) {
-        if (use->opcode() != SpvOpCompositeExtract) {
+        if (use->opcode() != spv::Op::OpCompositeExtract) {
           context()->EmitErrorMessage(
               "Variable cannot be replaced: invalid instruction", use);
           return false;
@@ -384,7 +385,7 @@
 
 bool DescriptorScalarReplacement::ReplaceCompositeExtract(
     Instruction* var, Instruction* extract) {
-  assert(extract->opcode() == SpvOpCompositeExtract);
+  assert(extract->opcode() == spv::Op::OpCompositeExtract);
   // We're currently only supporting extractions of one index at a time. If we
   // need to, we can handle cases with multiple indexes in the future.
   if (extract->NumInOperands() != 2) {
@@ -400,7 +401,7 @@
   // OpCompositeExtract.
   uint32_t load_id = TakeNextId();
   std::unique_ptr<Instruction> load(
-      new Instruction(context(), SpvOpLoad, extract->type_id(), load_id,
+      new Instruction(context(), spv::Op::OpLoad, extract->type_id(), load_id,
                       std::initializer_list<Operand>{
                           {SPV_OPERAND_TYPE_ID, {replacement_var}}}));
   Instruction* load_instr = load.get();
diff --git a/third_party/SPIRV-Tools/source/opt/desc_sroa_util.cpp b/third_party/SPIRV-Tools/source/opt/desc_sroa_util.cpp
index 1954e2c..dba3de9 100644
--- a/third_party/SPIRV-Tools/source/opt/desc_sroa_util.cpp
+++ b/third_party/SPIRV-Tools/source/opt/desc_sroa_util.cpp
@@ -17,12 +17,11 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-const uint32_t kOpAccessChainInOperandIndexes = 1;
+constexpr uint32_t kOpAccessChainInOperandIndexes = 1;
 
 // Returns the length of array type |type|.
 uint32_t GetLengthOfArrayType(IRContext* context, Instruction* type) {
-  assert(type->opcode() == SpvOpTypeArray && "type must be array");
+  assert(type->opcode() == spv::Op::OpTypeArray && "type must be array");
   uint32_t length_id = type->GetSingleWordInOperand(1);
   const analysis::Constant* length_const =
       context->get_constant_mgr()->FindDeclaredConstant(length_id);
@@ -35,20 +34,20 @@
 namespace descsroautil {
 
 bool IsDescriptorArray(IRContext* context, Instruction* var) {
-  if (var->opcode() != SpvOpVariable) {
+  if (var->opcode() != spv::Op::OpVariable) {
     return false;
   }
 
   uint32_t ptr_type_id = var->type_id();
   Instruction* ptr_type_inst = context->get_def_use_mgr()->GetDef(ptr_type_id);
-  if (ptr_type_inst->opcode() != SpvOpTypePointer) {
+  if (ptr_type_inst->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
   uint32_t var_type_id = ptr_type_inst->GetSingleWordInOperand(1);
   Instruction* var_type_inst = context->get_def_use_mgr()->GetDef(var_type_id);
-  if (var_type_inst->opcode() != SpvOpTypeArray &&
-      var_type_inst->opcode() != SpvOpTypeStruct) {
+  if (var_type_inst->opcode() != spv::Op::OpTypeArray &&
+      var_type_inst->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
@@ -59,23 +58,23 @@
   }
 
   if (!context->get_decoration_mgr()->HasDecoration(
-          var->result_id(), SpvDecorationDescriptorSet)) {
+          var->result_id(), uint32_t(spv::Decoration::DescriptorSet))) {
     return false;
   }
 
-  return context->get_decoration_mgr()->HasDecoration(var->result_id(),
-                                                      SpvDecorationBinding);
+  return context->get_decoration_mgr()->HasDecoration(
+      var->result_id(), uint32_t(spv::Decoration::Binding));
 }
 
 bool IsTypeOfStructuredBuffer(IRContext* context, const Instruction* type) {
-  if (type->opcode() != SpvOpTypeStruct) {
+  if (type->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
   // All buffers have offset decorations for members of their structure types.
   // This is how we distinguish it from a structure of descriptors.
-  return context->get_decoration_mgr()->HasDecoration(type->result_id(),
-                                                      SpvDecorationOffset);
+  return context->get_decoration_mgr()->HasDecoration(
+      type->result_id(), uint32_t(spv::Decoration::Offset));
 }
 
 const analysis::Constant* GetAccessChainIndexAsConst(
@@ -99,15 +98,15 @@
                                              Instruction* var) {
   uint32_t ptr_type_id = var->type_id();
   Instruction* ptr_type_inst = context->get_def_use_mgr()->GetDef(ptr_type_id);
-  assert(ptr_type_inst->opcode() == SpvOpTypePointer &&
+  assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Variable should be a pointer to an array or structure.");
   uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand(1);
   Instruction* pointee_type_inst =
       context->get_def_use_mgr()->GetDef(pointee_type_id);
-  if (pointee_type_inst->opcode() == SpvOpTypeArray) {
+  if (pointee_type_inst->opcode() == spv::Op::OpTypeArray) {
     return GetLengthOfArrayType(context, pointee_type_inst);
   }
-  assert(pointee_type_inst->opcode() == SpvOpTypeStruct &&
+  assert(pointee_type_inst->opcode() == spv::Op::OpTypeStruct &&
          "Variable should be a pointer to an array or structure.");
   return pointee_type_inst->NumInOperands();
 }
diff --git a/third_party/SPIRV-Tools/source/opt/dominator_analysis.cpp b/third_party/SPIRV-Tools/source/opt/dominator_analysis.cpp
index b692d26..eb6dfc9 100644
--- a/third_party/SPIRV-Tools/source/opt/dominator_analysis.cpp
+++ b/third_party/SPIRV-Tools/source/opt/dominator_analysis.cpp
@@ -64,7 +64,7 @@
 
   // We handle OpLabel instructions explicitly since they are not stored in the
   // instruction list.
-  if (current->opcode() == SpvOpLabel) {
+  if (current->opcode() == spv::Op::OpLabel) {
     return true;
   }
 
diff --git a/third_party/SPIRV-Tools/source/opt/dominator_tree.cpp b/third_party/SPIRV-Tools/source/opt/dominator_tree.cpp
index d6017bb..3c161a9 100644
--- a/third_party/SPIRV-Tools/source/opt/dominator_tree.cpp
+++ b/third_party/SPIRV-Tools/source/opt/dominator_tree.cpp
@@ -55,12 +55,10 @@
 // called on each node traversed BEFORE their children.
 template <typename BBType, typename SuccessorLambda, typename PreLambda,
           typename PostLambda>
-static void DepthFirstSearch(const BBType* bb, SuccessorLambda successors,
-                             PreLambda pre, PostLambda post) {
-  // Ignore backedge operation.
-  auto nop_backedge = [](const BBType*, const BBType*) {};
+void DepthFirstSearch(const BBType* bb, SuccessorLambda successors,
+                      PreLambda pre, PostLambda post) {
   auto no_terminal_blocks = [](const BBType*) { return false; };
-  CFA<BBType>::DepthFirstTraversal(bb, successors, pre, post, nop_backedge,
+  CFA<BBType>::DepthFirstTraversal(bb, successors, pre, post,
                                    no_terminal_blocks);
 }
 
@@ -75,9 +73,8 @@
 // PostLambda - Lamdba matching the signature of 'void (const BBType*)' will be
 // called on each node traversed after their children.
 template <typename BBType, typename SuccessorLambda, typename PostLambda>
-static void DepthFirstSearchPostOrder(const BBType* bb,
-                                      SuccessorLambda successors,
-                                      PostLambda post) {
+void DepthFirstSearchPostOrder(const BBType* bb, SuccessorLambda successors,
+                               PostLambda post) {
   // Ignore preorder operation.
   auto nop_preorder = [](const BBType*) {};
   DepthFirstSearch(bb, successors, nop_preorder, post);
@@ -105,7 +102,8 @@
   using Function = typename GetFunctionClass<BBType>::FunctionType;
 
   using BasicBlockListTy = std::vector<BasicBlock*>;
-  using BasicBlockMapTy = std::map<const BasicBlock*, BasicBlockListTy>;
+  using BasicBlockMapTy =
+      std::unordered_map<const BasicBlock*, BasicBlockListTy>;
 
  public:
   // For compliance with the dominance tree computation, entry nodes are
@@ -160,19 +158,7 @@
 template <typename BBType>
 void BasicBlockSuccessorHelper<BBType>::CreateSuccessorMap(
     Function& f, const BasicBlock* placeholder_start_node) {
-  std::map<uint32_t, BasicBlock*> id_to_BB_map;
-  auto GetSuccessorBasicBlock = [&f, &id_to_BB_map](uint32_t successor_id) {
-    BasicBlock*& Succ = id_to_BB_map[successor_id];
-    if (!Succ) {
-      for (BasicBlock& BBIt : f) {
-        if (successor_id == BBIt.id()) {
-          Succ = &BBIt;
-          break;
-        }
-      }
-    }
-    return Succ;
-  };
+  IRContext* context = f.DefInst().context();
 
   if (invert_graph_) {
     // For the post dominator tree, we see the inverted graph.
@@ -186,9 +172,8 @@
         BasicBlockListTy& pred_list = predecessors_[&bb];
         const auto& const_bb = bb;
         const_bb.ForEachSuccessorLabel(
-            [this, &pred_list, &bb,
-             &GetSuccessorBasicBlock](const uint32_t successor_id) {
-              BasicBlock* succ = GetSuccessorBasicBlock(successor_id);
+            [this, &pred_list, &bb, context](const uint32_t successor_id) {
+              BasicBlock* succ = context->get_instr_block(successor_id);
               // Inverted graph: our successors in the CFG
               // are our predecessors in the inverted graph.
               this->successors_[succ].push_back(&bb);
@@ -209,7 +194,7 @@
 
       const auto& const_bb = bb;
       const_bb.ForEachSuccessorLabel([&](const uint32_t successor_id) {
-        BasicBlock* succ = GetSuccessorBasicBlock(successor_id);
+        BasicBlock* succ = context->get_instr_block(successor_id);
         succ_list.push_back(succ);
         predecessors_[succ].push_back(&bb);
       });
diff --git a/third_party/SPIRV-Tools/source/opt/eliminate_dead_constant_pass.cpp b/third_party/SPIRV-Tools/source/opt/eliminate_dead_constant_pass.cpp
index d368bd1..d021515 100644
--- a/third_party/SPIRV-Tools/source/opt/eliminate_dead_constant_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/eliminate_dead_constant_pass.cpp
@@ -40,7 +40,7 @@
     context()->get_def_use_mgr()->ForEachUse(
         const_id, [&count](Instruction* user, uint32_t index) {
           (void)index;
-          SpvOp op = user->opcode();
+          spv::Op op = user->opcode();
           if (!(IsAnnotationInst(op) || IsDebug1Inst(op) || IsDebug2Inst(op) ||
                 IsDebug3Inst(op))) {
             ++count;
@@ -59,9 +59,9 @@
     Instruction* inst = *working_list.begin();
     // Back propagate if the instruction contains IDs in its operands.
     switch (inst->opcode()) {
-      case SpvOp::SpvOpConstantComposite:
-      case SpvOp::SpvOpSpecConstantComposite:
-      case SpvOp::SpvOpSpecConstantOp:
+      case spv::Op::OpConstantComposite:
+      case spv::Op::OpSpecConstantComposite:
+      case spv::Op::OpSpecConstantOp:
         for (uint32_t i = 0; i < inst->NumInOperands(); i++) {
           // SpecConstantOp instruction contains 'opcode' as its operand. Need
           // to exclude such operands when decreasing uses.
diff --git a/third_party/SPIRV-Tools/source/opt/eliminate_dead_functions_util.cpp b/third_party/SPIRV-Tools/source/opt/eliminate_dead_functions_util.cpp
index 1379120..cf7f92f 100644
--- a/third_party/SPIRV-Tools/source/opt/eliminate_dead_functions_util.cpp
+++ b/third_party/SPIRV-Tools/source/opt/eliminate_dead_functions_util.cpp
@@ -28,12 +28,12 @@
       ->ForEachInst(
           [context, first_func, func_iter, &seen_func_end,
            &to_kill](Instruction* inst) {
-            if (inst->opcode() == SpvOpFunctionEnd) {
+            if (inst->opcode() == spv::Op::OpFunctionEnd) {
               seen_func_end = true;
             }
             // Move non-semantic instructions to the previous function or
             // global values if this is the first function.
-            if (seen_func_end && inst->opcode() == SpvOpExtInst) {
+            if (seen_func_end && inst->opcode() == spv::Op::OpExtInst) {
               assert(inst->IsNonSemanticInstruction());
               if (to_kill.find(inst) != to_kill.end()) return;
               std::unique_ptr<Instruction> clone(inst->Clone(context));
diff --git a/third_party/SPIRV-Tools/source/opt/eliminate_dead_input_components_pass.cpp b/third_party/SPIRV-Tools/source/opt/eliminate_dead_input_components_pass.cpp
index f383136..637a33b 100644
--- a/third_party/SPIRV-Tools/source/opt/eliminate_dead_input_components_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/eliminate_dead_input_components_pass.cpp
@@ -23,28 +23,28 @@
 #include "source/opt/ir_context.h"
 #include "source/util/bit_vector.h"
 
-namespace {
-
-const uint32_t kAccessChainBaseInIdx = 0;
-const uint32_t kAccessChainIndex0InIdx = 1;
-const uint32_t kConstantValueInIdx = 0;
-const uint32_t kVariableStorageClassInIdx = 0;
-
-}  // namespace
-
 namespace spvtools {
 namespace opt {
+namespace {
+constexpr uint32_t kAccessChainBaseInIdx = 0;
+constexpr uint32_t kAccessChainIndex0InIdx = 1;
+constexpr uint32_t kConstantValueInIdx = 0;
+}  // namespace
 
 Pass::Status EliminateDeadInputComponentsPass::Process() {
-  // Current functionality assumes shader capability
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  // Process non-vertex only if explicitly allowed.
+  auto stage = context()->GetStage();
+  if (stage != spv::ExecutionModel::Vertex && vertex_shader_only_)
+    return Status::SuccessWithoutChange;
+  // Current functionality assumes shader capability.
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return Status::SuccessWithoutChange;
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   bool modified = false;
-  std::vector<std::pair<Instruction*, unsigned>> arrays_to_change;
+  std::vector<Instruction*> vars_to_move;
   for (auto& var : context()->types_values()) {
-    if (var.opcode() != SpvOpVariable) {
+    if (var.opcode() != spv::Op::OpVariable) {
       continue;
     }
     analysis::Type* var_type = type_mgr->GetType(var.type_id());
@@ -52,29 +52,63 @@
     if (ptr_type == nullptr) {
       continue;
     }
-    if (ptr_type->storage_class() != SpvStorageClassInput) {
-      continue;
+    if (output_instead_) {
+      if (ptr_type->storage_class() != spv::StorageClass::Output) {
+        continue;
+      }
+    } else {
+      if (ptr_type->storage_class() != spv::StorageClass::Input) {
+        continue;
+      }
     }
     const analysis::Array* arr_type = ptr_type->pointee_type()->AsArray();
-    if (arr_type == nullptr) {
+    if (arr_type != nullptr) {
+      // Only process array if input of vertex shader, or output of
+      // fragment shader. Otherwise, if one shader has a runtime index and the
+      // other does not, interface incompatibility can occur.
+      if (!((ptr_type->storage_class() == spv::StorageClass::Input &&
+             stage == spv::ExecutionModel::Vertex) ||
+            (ptr_type->storage_class() == spv::StorageClass::Output &&
+             stage == spv::ExecutionModel::Fragment)))
+        continue;
+      unsigned arr_len_id = arr_type->LengthId();
+      Instruction* arr_len_inst = def_use_mgr->GetDef(arr_len_id);
+      if (arr_len_inst->opcode() != spv::Op::OpConstant) {
+        continue;
+      }
+      // SPIR-V requires array size is >= 1, so this works for signed or
+      // unsigned size.
+      unsigned original_max =
+          arr_len_inst->GetSingleWordInOperand(kConstantValueInIdx) - 1;
+      unsigned max_idx = FindMaxIndex(var, original_max);
+      if (max_idx != original_max) {
+        ChangeArrayLength(var, max_idx + 1);
+        vars_to_move.push_back(&var);
+        modified = true;
+      }
       continue;
     }
-    unsigned arr_len_id = arr_type->LengthId();
-    Instruction* arr_len_inst = def_use_mgr->GetDef(arr_len_id);
-    if (arr_len_inst->opcode() != SpvOpConstant) {
-      continue;
-    }
-    // SPIR-V requires array size is >= 1, so this works for signed or
-    // unsigned size
-    unsigned original_max =
-        arr_len_inst->GetSingleWordInOperand(kConstantValueInIdx) - 1;
+    const analysis::Struct* struct_type = ptr_type->pointee_type()->AsStruct();
+    if (struct_type == nullptr) continue;
+    const auto elt_types = struct_type->element_types();
+    unsigned original_max = static_cast<unsigned>(elt_types.size()) - 1;
     unsigned max_idx = FindMaxIndex(var, original_max);
     if (max_idx != original_max) {
-      ChangeArrayLength(var, max_idx + 1);
+      ChangeStructLength(var, max_idx + 1);
+      vars_to_move.push_back(&var);
       modified = true;
     }
   }
 
+  // Move changed vars after their new type instruction to preserve backward
+  // referencing.
+  for (auto var : vars_to_move) {
+    auto type_id = var->type_id();
+    auto type_inst = def_use_mgr->GetDef(type_id);
+    var->RemoveFromList();
+    var->InsertAfter(type_inst);
+  }
+
   return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
 }
 
@@ -82,18 +116,19 @@
                                                         unsigned original_max) {
   unsigned max = 0;
   bool seen_non_const_ac = false;
-  assert(var.opcode() == SpvOpVariable && "must be variable");
+  assert(var.opcode() == spv::Op::OpVariable && "must be variable");
   context()->get_def_use_mgr()->WhileEachUser(
       var.result_id(), [&max, &seen_non_const_ac, var, this](Instruction* use) {
         auto use_opcode = use->opcode();
-        if (use_opcode == SpvOpLoad || use_opcode == SpvOpCopyMemory ||
-            use_opcode == SpvOpCopyMemorySized ||
-            use_opcode == SpvOpCopyObject) {
+        if (use_opcode == spv::Op::OpLoad || use_opcode == spv::Op::OpStore ||
+            use_opcode == spv::Op::OpCopyMemory ||
+            use_opcode == spv::Op::OpCopyMemorySized ||
+            use_opcode == spv::Op::OpCopyObject) {
           seen_non_const_ac = true;
           return false;
         }
-        if (use->opcode() != SpvOpAccessChain &&
-            use->opcode() != SpvOpInBoundsAccessChain) {
+        if (use->opcode() != spv::Op::OpAccessChain &&
+            use->opcode() != spv::Op::OpInBoundsAccessChain) {
           return true;
         }
         // OpAccessChain with no indices currently not optimized
@@ -105,7 +140,7 @@
         USE_ASSERT(base_id == var.result_id() && "unexpected base");
         unsigned idx_id = use->GetSingleWordInOperand(kAccessChainIndex0InIdx);
         Instruction* idx_inst = context()->get_def_use_mgr()->GetDef(idx_id);
-        if (idx_inst->opcode() != SpvOpConstant) {
+        if (idx_inst->opcode() != spv::Op::OpConstant) {
           seen_non_const_ac = true;
           return false;
         }
@@ -116,30 +151,57 @@
   return seen_non_const_ac ? original_max : max;
 }
 
-void EliminateDeadInputComponentsPass::ChangeArrayLength(Instruction& arr,
+void EliminateDeadInputComponentsPass::ChangeArrayLength(Instruction& arr_var,
                                                          unsigned length) {
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
-  analysis::Pointer* ptr_type = type_mgr->GetType(arr.type_id())->AsPointer();
+  analysis::Pointer* ptr_type =
+      type_mgr->GetType(arr_var.type_id())->AsPointer();
   const analysis::Array* arr_ty = ptr_type->pointee_type()->AsArray();
   assert(arr_ty && "expecting array type");
   uint32_t length_id = const_mgr->GetUIntConst(length);
   analysis::Array new_arr_ty(arr_ty->element_type(),
                              arr_ty->GetConstantLengthInfo(length_id, length));
   analysis::Type* reg_new_arr_ty = type_mgr->GetRegisteredType(&new_arr_ty);
-  analysis::Pointer new_ptr_ty(reg_new_arr_ty, SpvStorageClassInput);
+  analysis::Pointer new_ptr_ty(reg_new_arr_ty, ptr_type->storage_class());
   analysis::Type* reg_new_ptr_ty = type_mgr->GetRegisteredType(&new_ptr_ty);
   uint32_t new_ptr_ty_id = type_mgr->GetTypeInstruction(reg_new_ptr_ty);
-  arr.SetResultType(new_ptr_ty_id);
-  def_use_mgr->AnalyzeInstUse(&arr);
-  // Move array OpVariable instruction after its new type to preserve order
-  USE_ASSERT(arr.GetSingleWordInOperand(kVariableStorageClassInIdx) !=
-                 SpvStorageClassFunction &&
-             "cannot move Function variable");
-  Instruction* new_ptr_ty_inst = def_use_mgr->GetDef(new_ptr_ty_id);
-  arr.RemoveFromList();
-  arr.InsertAfter(new_ptr_ty_inst);
+  arr_var.SetResultType(new_ptr_ty_id);
+  def_use_mgr->AnalyzeInstUse(&arr_var);
+}
+
+void EliminateDeadInputComponentsPass::ChangeStructLength(
+    Instruction& struct_var, unsigned length) {
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  analysis::Pointer* ptr_type =
+      type_mgr->GetType(struct_var.type_id())->AsPointer();
+  const analysis::Struct* struct_ty = ptr_type->pointee_type()->AsStruct();
+  assert(struct_ty && "expecting struct type");
+  const auto orig_elt_types = struct_ty->element_types();
+  std::vector<const analysis::Type*> new_elt_types;
+  for (unsigned u = 0; u < length; ++u)
+    new_elt_types.push_back(orig_elt_types[u]);
+  analysis::Struct new_struct_ty(new_elt_types);
+  uint32_t old_struct_ty_id = type_mgr->GetTypeInstruction(struct_ty);
+  std::vector<Instruction*> decorations =
+      context()->get_decoration_mgr()->GetDecorationsFor(old_struct_ty_id,
+                                                         true);
+  for (auto dec : decorations) {
+    if (dec->opcode() == spv::Op::OpMemberDecorate) {
+      uint32_t midx = dec->GetSingleWordInOperand(1);
+      if (midx >= length) continue;
+    }
+    type_mgr->AttachDecoration(*dec, &new_struct_ty);
+  }
+  analysis::Type* reg_new_struct_ty =
+      type_mgr->GetRegisteredType(&new_struct_ty);
+  analysis::Pointer new_ptr_ty(reg_new_struct_ty, ptr_type->storage_class());
+  analysis::Type* reg_new_ptr_ty = type_mgr->GetRegisteredType(&new_ptr_ty);
+  uint32_t new_ptr_ty_id = type_mgr->GetTypeInstruction(reg_new_ptr_ty);
+  struct_var.SetResultType(new_ptr_ty_id);
+  analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
+  def_use_mgr->AnalyzeInstUse(&struct_var);
 }
 
 }  // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/eliminate_dead_input_components_pass.h b/third_party/SPIRV-Tools/source/opt/eliminate_dead_input_components_pass.h
index b77857f..111366e 100644
--- a/third_party/SPIRV-Tools/source/opt/eliminate_dead_input_components_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/eliminate_dead_input_components_pass.h
@@ -28,9 +28,14 @@
 // See optimizer.hpp for documentation.
 class EliminateDeadInputComponentsPass : public Pass {
  public:
-  explicit EliminateDeadInputComponentsPass() {}
+  explicit EliminateDeadInputComponentsPass(bool output_instead = false,
+                                            bool vertex_shader_only = true)
+      : output_instead_(output_instead),
+        vertex_shader_only_(vertex_shader_only) {}
 
-  const char* name() const override { return "reduce-load-size"; }
+  const char* name() const override {
+    return "eliminate-dead-input-components";
+  }
   Status Process() override;
 
   // Return the mask of preserved Analyses.
@@ -51,6 +56,15 @@
 
   // Change the length of the array |inst| to |length|
   void ChangeArrayLength(Instruction& inst, unsigned length);
+
+  // Change the length of the struct |struct_var| to |length|
+  void ChangeStructLength(Instruction& struct_var, unsigned length);
+
+  // Process output variables instead
+  bool output_instead_;
+
+  // Only process vertex shaders
+  bool vertex_shader_only_;
 };
 
 }  // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/eliminate_dead_members_pass.cpp b/third_party/SPIRV-Tools/source/opt/eliminate_dead_members_pass.cpp
index 52aca52..1c98502 100644
--- a/third_party/SPIRV-Tools/source/opt/eliminate_dead_members_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/eliminate_dead_members_pass.cpp
@@ -17,17 +17,16 @@
 #include "ir_builder.h"
 #include "source/opt/ir_context.h"
 
+namespace spvtools {
+namespace opt {
 namespace {
-const uint32_t kRemovedMember = 0xFFFFFFFF;
-const uint32_t kSpecConstOpOpcodeIdx = 0;
+constexpr uint32_t kRemovedMember = 0xFFFFFFFF;
+constexpr uint32_t kSpecConstOpOpcodeIdx = 0;
 constexpr uint32_t kArrayElementTypeIdx = 0;
 }  // namespace
 
-namespace spvtools {
-namespace opt {
-
 Pass::Status EliminateDeadMembersPass::Process() {
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return Status::SuccessWithoutChange;
 
   FindLiveMembers();
@@ -41,27 +40,27 @@
   // Until we have implemented the rewriting of OpSpecConsantOp instructions,
   // we have to mark them as fully used just to be safe.
   for (auto& inst : get_module()->types_values()) {
-    if (inst.opcode() == SpvOpSpecConstantOp) {
-      switch (inst.GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) {
-        case SpvOpCompositeExtract:
+    if (inst.opcode() == spv::Op::OpSpecConstantOp) {
+      switch (spv::Op(inst.GetSingleWordInOperand(kSpecConstOpOpcodeIdx))) {
+        case spv::Op::OpCompositeExtract:
           MarkMembersAsLiveForExtract(&inst);
           break;
-        case SpvOpCompositeInsert:
+        case spv::Op::OpCompositeInsert:
           // Nothing specific to do.
           break;
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain:
-        case SpvOpPtrAccessChain:
-        case SpvOpInBoundsPtrAccessChain:
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain:
+        case spv::Op::OpPtrAccessChain:
+        case spv::Op::OpInBoundsPtrAccessChain:
           assert(false && "Not implemented yet.");
           break;
         default:
           break;
       }
-    } else if (inst.opcode() == SpvOpVariable) {
-      switch (inst.GetSingleWordInOperand(0)) {
-        case SpvStorageClassInput:
-        case SpvStorageClassOutput:
+    } else if (inst.opcode() == spv::Op::OpVariable) {
+      switch (spv::StorageClass(inst.GetSingleWordInOperand(0))) {
+        case spv::StorageClass::Input:
+        case spv::StorageClass::Output:
           MarkPointeeTypeAsFullUsed(inst.type_id());
           break;
         default:
@@ -86,34 +85,34 @@
 
 void EliminateDeadMembersPass::FindLiveMembers(const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpStore:
+    case spv::Op::OpStore:
       MarkMembersAsLiveForStore(inst);
       break;
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       MarkMembersAsLiveForCopyMemory(inst);
       break;
-    case SpvOpCompositeExtract:
+    case spv::Op::OpCompositeExtract:
       MarkMembersAsLiveForExtract(inst);
       break;
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       MarkMembersAsLiveForAccessChain(inst);
       break;
-    case SpvOpReturnValue:
+    case spv::Op::OpReturnValue:
       // This should be an issue only if we are returning from the entry point.
       // However, for now I will keep it more conservative because functions are
       // often inlined leaving only the entry points.
       MarkOperandTypeAsFullyUsed(inst, 0);
       break;
-    case SpvOpArrayLength:
+    case spv::Op::OpArrayLength:
       MarkMembersAsLiveForArrayLength(inst);
       break;
-    case SpvOpLoad:
-    case SpvOpCompositeInsert:
-    case SpvOpCompositeConstruct:
+    case spv::Op::OpLoad:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCompositeConstruct:
       break;
     default:
       // This path is here for safety.  All instructions that can reference
@@ -131,7 +130,7 @@
   // memory that is read outside of the shader.  Other passes can remove all
   // store to memory that is not visible outside of the shader, so we do not
   // complicate the code for now.
-  assert(inst->opcode() == SpvOpStore);
+  assert(inst->opcode() == spv::Op::OpStore);
   uint32_t object_id = inst->GetSingleWordInOperand(1);
   Instruction* object_inst = context()->get_def_use_mgr()->GetDef(object_id);
   uint32_t object_type_id = object_inst->type_id();
@@ -143,15 +142,15 @@
   assert(type_inst != nullptr);
 
   switch (type_inst->opcode()) {
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       // Mark every member and its type as fully used.
       for (uint32_t i = 0; i < type_inst->NumInOperands(); ++i) {
         used_members_[type_id].insert(i);
         MarkTypeAsFullyUsed(type_inst->GetSingleWordInOperand(i));
       }
       break;
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       MarkTypeAsFullyUsed(
           type_inst->GetSingleWordInOperand(kArrayElementTypeIdx));
       break;
@@ -162,7 +161,7 @@
 
 void EliminateDeadMembersPass::MarkPointeeTypeAsFullUsed(uint32_t ptr_type_id) {
   Instruction* ptr_type_inst = get_def_use_mgr()->GetDef(ptr_type_id);
-  assert(ptr_type_inst->opcode() == SpvOpTypePointer);
+  assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer);
   MarkTypeAsFullyUsed(ptr_type_inst->GetSingleWordInOperand(1));
 }
 
@@ -178,12 +177,13 @@
 
 void EliminateDeadMembersPass::MarkMembersAsLiveForExtract(
     const Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeExtract ||
-         (inst->opcode() == SpvOpSpecConstantOp &&
-          inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
-              SpvOpCompositeExtract));
+  assert(inst->opcode() == spv::Op::OpCompositeExtract ||
+         (inst->opcode() == spv::Op::OpSpecConstantOp &&
+          spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) ==
+              spv::Op::OpCompositeExtract));
 
-  uint32_t first_operand = (inst->opcode() == SpvOpSpecConstantOp ? 1 : 0);
+  uint32_t first_operand =
+      (inst->opcode() == spv::Op::OpSpecConstantOp ? 1 : 0);
   uint32_t composite_id = inst->GetSingleWordInOperand(first_operand);
   Instruction* composite_inst = get_def_use_mgr()->GetDef(composite_id);
   uint32_t type_id = composite_inst->type_id();
@@ -192,14 +192,14 @@
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     uint32_t member_idx = inst->GetSingleWordInOperand(i);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         used_members_[type_id].insert(member_idx);
         type_id = type_inst->GetSingleWordInOperand(member_idx);
         break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
@@ -210,10 +210,10 @@
 
 void EliminateDeadMembersPass::MarkMembersAsLiveForAccessChain(
     const Instruction* inst) {
-  assert(inst->opcode() == SpvOpAccessChain ||
-         inst->opcode() == SpvOpInBoundsAccessChain ||
-         inst->opcode() == SpvOpPtrAccessChain ||
-         inst->opcode() == SpvOpInBoundsPtrAccessChain);
+  assert(inst->opcode() == spv::Op::OpAccessChain ||
+         inst->opcode() == spv::Op::OpInBoundsAccessChain ||
+         inst->opcode() == spv::Op::OpPtrAccessChain ||
+         inst->opcode() == spv::Op::OpInBoundsPtrAccessChain);
 
   uint32_t pointer_id = inst->GetSingleWordInOperand(0);
   Instruction* pointer_inst = get_def_use_mgr()->GetDef(pointer_id);
@@ -225,14 +225,14 @@
 
   // For a pointer access chain, we need to skip the |element| index.  It is not
   // a reference to the member of a struct, and it does not change the type.
-  uint32_t i = (inst->opcode() == SpvOpAccessChain ||
-                        inst->opcode() == SpvOpInBoundsAccessChain
+  uint32_t i = (inst->opcode() == spv::Op::OpAccessChain ||
+                        inst->opcode() == spv::Op::OpInBoundsAccessChain
                     ? 1
                     : 2);
   for (; i < inst->NumInOperands(); ++i) {
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         const analysis::IntConstant* member_idx =
             const_mgr->FindDeclaredConstant(inst->GetSingleWordInOperand(i))
                 ->AsIntConstant();
@@ -242,10 +242,10 @@
         used_members_[type_id].insert(index);
         type_id = type_inst->GetSingleWordInOperand(index);
       } break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
@@ -263,7 +263,7 @@
 
 void EliminateDeadMembersPass::MarkMembersAsLiveForArrayLength(
     const Instruction* inst) {
-  assert(inst->opcode() == SpvOpArrayLength);
+  assert(inst->opcode() == spv::Op::OpArrayLength);
   uint32_t object_id = inst->GetSingleWordInOperand(0);
   Instruction* object_inst = get_def_use_mgr()->GetDef(object_id);
   uint32_t pointer_type_id = object_inst->type_id();
@@ -278,7 +278,7 @@
   // First update all of the OpTypeStruct instructions.
   get_module()->ForEachInst([&modified, this](Instruction* inst) {
     switch (inst->opcode()) {
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         modified |= UpdateOpTypeStruct(inst);
         break;
       default:
@@ -289,47 +289,47 @@
   // Now update all of the instructions that reference the OpTypeStructs.
   get_module()->ForEachInst([&modified, this](Instruction* inst) {
     switch (inst->opcode()) {
-      case SpvOpMemberName:
+      case spv::Op::OpMemberName:
         modified |= UpdateOpMemberNameOrDecorate(inst);
         break;
-      case SpvOpMemberDecorate:
+      case spv::Op::OpMemberDecorate:
         modified |= UpdateOpMemberNameOrDecorate(inst);
         break;
-      case SpvOpGroupMemberDecorate:
+      case spv::Op::OpGroupMemberDecorate:
         modified |= UpdateOpGroupMemberDecorate(inst);
         break;
-      case SpvOpSpecConstantComposite:
-      case SpvOpConstantComposite:
-      case SpvOpCompositeConstruct:
+      case spv::Op::OpSpecConstantComposite:
+      case spv::Op::OpConstantComposite:
+      case spv::Op::OpCompositeConstruct:
         modified |= UpdateConstantComposite(inst);
         break;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
-      case SpvOpPtrAccessChain:
-      case SpvOpInBoundsPtrAccessChain:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
+      case spv::Op::OpPtrAccessChain:
+      case spv::Op::OpInBoundsPtrAccessChain:
         modified |= UpdateAccessChain(inst);
         break;
-      case SpvOpCompositeExtract:
+      case spv::Op::OpCompositeExtract:
         modified |= UpdateCompsiteExtract(inst);
         break;
-      case SpvOpCompositeInsert:
+      case spv::Op::OpCompositeInsert:
         modified |= UpdateCompositeInsert(inst);
         break;
-      case SpvOpArrayLength:
+      case spv::Op::OpArrayLength:
         modified |= UpdateOpArrayLength(inst);
         break;
-      case SpvOpSpecConstantOp:
-        switch (inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) {
-          case SpvOpCompositeExtract:
+      case spv::Op::OpSpecConstantOp:
+        switch (spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx))) {
+          case spv::Op::OpCompositeExtract:
             modified |= UpdateCompsiteExtract(inst);
             break;
-          case SpvOpCompositeInsert:
+          case spv::Op::OpCompositeInsert:
             modified |= UpdateCompositeInsert(inst);
             break;
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain:
-          case SpvOpPtrAccessChain:
-          case SpvOpInBoundsPtrAccessChain:
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain:
+          case spv::Op::OpPtrAccessChain:
+          case spv::Op::OpInBoundsPtrAccessChain:
             assert(false && "Not implemented yet.");
             break;
           default:
@@ -344,7 +344,7 @@
 }
 
 bool EliminateDeadMembersPass::UpdateOpTypeStruct(Instruction* inst) {
-  assert(inst->opcode() == SpvOpTypeStruct);
+  assert(inst->opcode() == spv::Op::OpTypeStruct);
 
   const auto& live_members = used_members_[inst->result_id()];
   if (live_members.size() == inst->NumInOperands()) {
@@ -362,8 +362,8 @@
 }
 
 bool EliminateDeadMembersPass::UpdateOpMemberNameOrDecorate(Instruction* inst) {
-  assert(inst->opcode() == SpvOpMemberName ||
-         inst->opcode() == SpvOpMemberDecorate);
+  assert(inst->opcode() == spv::Op::OpMemberName ||
+         inst->opcode() == spv::Op::OpMemberDecorate);
 
   uint32_t type_id = inst->GetSingleWordInOperand(0);
   auto live_members = used_members_.find(type_id);
@@ -388,7 +388,7 @@
 }
 
 bool EliminateDeadMembersPass::UpdateOpGroupMemberDecorate(Instruction* inst) {
-  assert(inst->opcode() == SpvOpGroupMemberDecorate);
+  assert(inst->opcode() == spv::Op::OpGroupMemberDecorate);
 
   bool modified = false;
 
@@ -429,9 +429,9 @@
 }
 
 bool EliminateDeadMembersPass::UpdateConstantComposite(Instruction* inst) {
-  assert(inst->opcode() == SpvOpSpecConstantComposite ||
-         inst->opcode() == SpvOpConstantComposite ||
-         inst->opcode() == SpvOpCompositeConstruct);
+  assert(inst->opcode() == spv::Op::OpSpecConstantComposite ||
+         inst->opcode() == spv::Op::OpConstantComposite ||
+         inst->opcode() == spv::Op::OpCompositeConstruct);
   uint32_t type_id = inst->type_id();
 
   bool modified = false;
@@ -450,10 +450,10 @@
 }
 
 bool EliminateDeadMembersPass::UpdateAccessChain(Instruction* inst) {
-  assert(inst->opcode() == SpvOpAccessChain ||
-         inst->opcode() == SpvOpInBoundsAccessChain ||
-         inst->opcode() == SpvOpPtrAccessChain ||
-         inst->opcode() == SpvOpInBoundsPtrAccessChain);
+  assert(inst->opcode() == spv::Op::OpAccessChain ||
+         inst->opcode() == spv::Op::OpInBoundsAccessChain ||
+         inst->opcode() == spv::Op::OpPtrAccessChain ||
+         inst->opcode() == spv::Op::OpInBoundsPtrAccessChain);
 
   uint32_t pointer_id = inst->GetSingleWordInOperand(0);
   Instruction* pointer_inst = get_def_use_mgr()->GetDef(pointer_id);
@@ -467,8 +467,8 @@
   new_operands.emplace_back(inst->GetInOperand(0));
 
   // For pointer access chains we want to copy the element operand.
-  if (inst->opcode() == SpvOpPtrAccessChain ||
-      inst->opcode() == SpvOpInBoundsPtrAccessChain) {
+  if (inst->opcode() == spv::Op::OpPtrAccessChain ||
+      inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) {
     new_operands.emplace_back(inst->GetInOperand(1));
   }
 
@@ -476,7 +476,7 @@
        i < inst->NumInOperands(); ++i) {
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         const analysis::IntConstant* member_idx =
             const_mgr->FindDeclaredConstant(inst->GetSingleWordInOperand(i))
                 ->AsIntConstant();
@@ -501,10 +501,10 @@
         // index.
         type_id = type_inst->GetSingleWordInOperand(new_member_idx);
       } break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         new_operands.emplace_back(inst->GetInOperand(i));
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
@@ -539,13 +539,13 @@
 }
 
 bool EliminateDeadMembersPass::UpdateCompsiteExtract(Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeExtract ||
-         (inst->opcode() == SpvOpSpecConstantOp &&
-          inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
-              SpvOpCompositeExtract));
+  assert(inst->opcode() == spv::Op::OpCompositeExtract ||
+         (inst->opcode() == spv::Op::OpSpecConstantOp &&
+          spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) ==
+              spv::Op::OpCompositeExtract));
 
   uint32_t first_operand = 0;
-  if (inst->opcode() == SpvOpSpecConstantOp) {
+  if (inst->opcode() == spv::Op::OpSpecConstantOp) {
     first_operand = 1;
   }
   uint32_t object_id = inst->GetSingleWordInOperand(first_operand);
@@ -569,15 +569,15 @@
 
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         // The type will have already been rewritten, so use the new member
         // index.
         type_id = type_inst->GetSingleWordInOperand(new_member_idx);
         break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
@@ -594,13 +594,13 @@
 }
 
 bool EliminateDeadMembersPass::UpdateCompositeInsert(Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeInsert ||
-         (inst->opcode() == SpvOpSpecConstantOp &&
-          inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
-              SpvOpCompositeInsert));
+  assert(inst->opcode() == spv::Op::OpCompositeInsert ||
+         (inst->opcode() == spv::Op::OpSpecConstantOp &&
+          spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) ==
+              spv::Op::OpCompositeInsert));
 
   uint32_t first_operand = 0;
-  if (inst->opcode() == SpvOpSpecConstantOp) {
+  if (inst->opcode() == spv::Op::OpSpecConstantOp) {
     first_operand = 1;
   }
 
@@ -630,15 +630,15 @@
 
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         // The type will have already been rewritten, so use the new member
         // index.
         type_id = type_inst->GetSingleWordInOperand(new_member_idx);
         break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
diff --git a/third_party/SPIRV-Tools/source/opt/eliminate_dead_output_stores_pass.cpp b/third_party/SPIRV-Tools/source/opt/eliminate_dead_output_stores_pass.cpp
new file mode 100644
index 0000000..f2f64f8
--- /dev/null
+++ b/third_party/SPIRV-Tools/source/opt/eliminate_dead_output_stores_pass.cpp
@@ -0,0 +1,237 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+// Copyright (c) 2022 LunarG Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "source/opt/eliminate_dead_output_stores_pass.h"
+
+#include "source/opt/instruction.h"
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace opt {
+namespace {
+constexpr uint32_t kDecorationLocationInIdx = 2;
+constexpr uint32_t kOpDecorateMemberMemberInIdx = 1;
+constexpr uint32_t kOpDecorateBuiltInLiteralInIdx = 2;
+constexpr uint32_t kOpDecorateMemberBuiltInLiteralInIdx = 3;
+constexpr uint32_t kOpAccessChainIdx0InIdx = 1;
+constexpr uint32_t kOpConstantValueInIdx = 0;
+}  // namespace
+
+Pass::Status EliminateDeadOutputStoresPass::Process() {
+  // Current functionality assumes shader capability
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
+    return Status::SuccessWithoutChange;
+  Pass::Status status = DoDeadOutputStoreElimination();
+  return status;
+}
+
+void EliminateDeadOutputStoresPass::InitializeElimination() {
+  kill_list_.clear();
+}
+
+bool EliminateDeadOutputStoresPass::IsLiveBuiltin(uint32_t bi) {
+  return live_builtins_->find(bi) != live_builtins_->end();
+}
+
+bool EliminateDeadOutputStoresPass::AnyLocsAreLive(uint32_t start,
+                                                   uint32_t count) {
+  auto finish = start + count;
+  for (uint32_t u = start; u < finish; ++u) {
+    if (live_locs_->find(u) != live_locs_->end()) return true;
+  }
+  return false;
+}
+
+void EliminateDeadOutputStoresPass::KillAllStoresOfRef(Instruction* ref) {
+  analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
+  if (ref->opcode() == spv::Op::OpStore) {
+    kill_list_.push_back(ref);
+    return;
+  }
+  assert((ref->opcode() == spv::Op::OpAccessChain ||
+          ref->opcode() == spv::Op::OpInBoundsAccessChain) &&
+         "unexpected use of output variable");
+  def_use_mgr->ForEachUser(ref, [this](Instruction* user) {
+    if (user->opcode() == spv::Op::OpStore) kill_list_.push_back(user);
+  });
+}
+
+void EliminateDeadOutputStoresPass::KillAllDeadStoresOfLocRef(
+    Instruction* ref, Instruction* var) {
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr();
+  analysis::LivenessManager* live_mgr = context()->get_liveness_mgr();
+  // Find variable location if present.
+  uint32_t start_loc = 0;
+  auto var_id = var->result_id();
+  bool no_loc = deco_mgr->WhileEachDecoration(
+      var_id, uint32_t(spv::Decoration::Location),
+      [&start_loc](const Instruction& deco) {
+        assert(deco.opcode() == spv::Op::OpDecorate && "unexpected decoration");
+        start_loc = deco.GetSingleWordInOperand(kDecorationLocationInIdx);
+        return false;
+      });
+  // Find patch decoration if present
+  bool is_patch = !deco_mgr->WhileEachDecoration(
+      var_id, uint32_t(spv::Decoration::Patch), [](const Instruction& deco) {
+        if (deco.opcode() != spv::Op::OpDecorate)
+          assert(false && "unexpected decoration");
+        return false;
+      });
+  // Compute offset and final type of reference. If no location found
+  // or any stored locations are live, return without removing stores.
+  auto ptr_type = type_mgr->GetType(var->type_id())->AsPointer();
+  assert(ptr_type && "unexpected var type");
+  auto var_type = ptr_type->pointee_type();
+  uint32_t ref_loc = start_loc;
+  auto curr_type = var_type;
+  if (ref->opcode() == spv::Op::OpAccessChain ||
+      ref->opcode() == spv::Op::OpInBoundsAccessChain) {
+    live_mgr->AnalyzeAccessChainLoc(ref, &curr_type, &ref_loc, &no_loc,
+                                    is_patch, /* input */ false);
+  }
+  if (no_loc || AnyLocsAreLive(ref_loc, live_mgr->GetLocSize(curr_type)))
+    return;
+  // Kill all stores based on this reference
+  KillAllStoresOfRef(ref);
+}
+
+void EliminateDeadOutputStoresPass::KillAllDeadStoresOfBuiltinRef(
+    Instruction* ref, Instruction* var) {
+  auto deco_mgr = context()->get_decoration_mgr();
+  auto def_use_mgr = context()->get_def_use_mgr();
+  auto type_mgr = context()->get_type_mgr();
+  auto live_mgr = context()->get_liveness_mgr();
+  // Search for builtin decoration of base variable
+  uint32_t builtin = uint32_t(spv::BuiltIn::Max);
+  auto var_id = var->result_id();
+  (void)deco_mgr->WhileEachDecoration(
+      var_id, uint32_t(spv::Decoration::BuiltIn),
+      [&builtin](const Instruction& deco) {
+        assert(deco.opcode() == spv::Op::OpDecorate && "unexpected decoration");
+        builtin = deco.GetSingleWordInOperand(kOpDecorateBuiltInLiteralInIdx);
+        return false;
+      });
+  // If analyzed builtin and not live, kill stores.
+  if (builtin != uint32_t(spv::BuiltIn::Max)) {
+    if (live_mgr->IsAnalyzedBuiltin(builtin) && !IsLiveBuiltin(builtin))
+      KillAllStoresOfRef(ref);
+    return;
+  }
+  // Search for builtin decoration on indexed member
+  auto ref_op = ref->opcode();
+  if (ref_op != spv::Op::OpAccessChain &&
+      ref_op != spv::Op::OpInBoundsAccessChain) {
+    return;
+  }
+  uint32_t in_idx = kOpAccessChainIdx0InIdx;
+  analysis::Type* var_type = type_mgr->GetType(var->type_id());
+  analysis::Pointer* ptr_type = var_type->AsPointer();
+  auto curr_type = ptr_type->pointee_type();
+  auto arr_type = curr_type->AsArray();
+  if (arr_type) {
+    curr_type = arr_type->element_type();
+    ++in_idx;
+  }
+  auto str_type = curr_type->AsStruct();
+  auto str_type_id = type_mgr->GetId(str_type);
+  auto member_idx_id = ref->GetSingleWordInOperand(in_idx);
+  auto member_idx_inst = def_use_mgr->GetDef(member_idx_id);
+  assert(member_idx_inst->opcode() == spv::Op::OpConstant &&
+         "unexpected non-constant index");
+  auto ac_idx = member_idx_inst->GetSingleWordInOperand(kOpConstantValueInIdx);
+  (void)deco_mgr->WhileEachDecoration(
+      str_type_id, uint32_t(spv::Decoration::BuiltIn),
+      [ac_idx, &builtin](const Instruction& deco) {
+        assert(deco.opcode() == spv::Op::OpMemberDecorate &&
+               "unexpected decoration");
+        auto deco_idx =
+            deco.GetSingleWordInOperand(kOpDecorateMemberMemberInIdx);
+        if (deco_idx == ac_idx) {
+          builtin =
+              deco.GetSingleWordInOperand(kOpDecorateMemberBuiltInLiteralInIdx);
+          return false;
+        }
+        return true;
+      });
+  assert(builtin != uint32_t(spv::BuiltIn::Max) && "builtin not found");
+  // If analyzed builtin and not live, kill stores.
+  if (live_mgr->IsAnalyzedBuiltin(builtin) && !IsLiveBuiltin(builtin))
+    KillAllStoresOfRef(ref);
+}
+
+Pass::Status EliminateDeadOutputStoresPass::DoDeadOutputStoreElimination() {
+  // Current implementation only supports vert, tesc, tese, geom shaders
+  auto stage = context()->GetStage();
+  if (stage != spv::ExecutionModel::Vertex &&
+      stage != spv::ExecutionModel::TessellationControl &&
+      stage != spv::ExecutionModel::TessellationEvaluation &&
+      stage != spv::ExecutionModel::Geometry)
+    return Status::Failure;
+  InitializeElimination();
+  analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr();
+  // Process all output variables
+  for (auto& var : context()->types_values()) {
+    if (var.opcode() != spv::Op::OpVariable) {
+      continue;
+    }
+    analysis::Type* var_type = type_mgr->GetType(var.type_id());
+    analysis::Pointer* ptr_type = var_type->AsPointer();
+    if (ptr_type->storage_class() != spv::StorageClass::Output) {
+      continue;
+    }
+    // If builtin decoration on variable, process as builtin.
+    auto var_id = var.result_id();
+    bool is_builtin = false;
+    if (deco_mgr->HasDecoration(var_id, uint32_t(spv::Decoration::BuiltIn))) {
+      is_builtin = true;
+    } else {
+      // If interface block with builtin members, process as builtin.
+      // Strip off outer array type if present.
+      auto curr_type = ptr_type->pointee_type();
+      auto arr_type = curr_type->AsArray();
+      if (arr_type) curr_type = arr_type->element_type();
+      auto str_type = curr_type->AsStruct();
+      if (str_type) {
+        auto str_type_id = type_mgr->GetId(str_type);
+        if (deco_mgr->HasDecoration(str_type_id,
+                                    uint32_t(spv::Decoration::BuiltIn)))
+          is_builtin = true;
+      }
+    }
+    // For each store or access chain using var, if dead builtin or all its
+    // locations are dead, kill store or all access chain's stores
+    def_use_mgr->ForEachUser(
+        var_id, [this, &var, is_builtin](Instruction* user) {
+          auto op = user->opcode();
+          if (op == spv::Op::OpEntryPoint || op == spv::Op::OpName ||
+              op == spv::Op::OpDecorate)
+            return;
+          if (is_builtin)
+            KillAllDeadStoresOfBuiltinRef(user, &var);
+          else
+            KillAllDeadStoresOfLocRef(user, &var);
+        });
+  }
+  for (auto& kinst : kill_list_) context()->KillInst(kinst);
+
+  return kill_list_.empty() ? Status::SuccessWithoutChange
+                            : Status::SuccessWithChange;
+}
+
+}  // namespace opt
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/eliminate_dead_output_stores_pass.h b/third_party/SPIRV-Tools/source/opt/eliminate_dead_output_stores_pass.h
new file mode 100644
index 0000000..13785f3
--- /dev/null
+++ b/third_party/SPIRV-Tools/source/opt/eliminate_dead_output_stores_pass.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+// Copyright (c) 2022 LunarG Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SOURCE_OPT_ELIMINATE_DEAD_OUTPUT_STORES_H_
+#define SOURCE_OPT_ELIMINATE_DEAD_OUTPUT_STORES_H_
+
+#include <unordered_set>
+
+#include "source/opt/ir_context.h"
+#include "source/opt/module.h"
+#include "source/opt/pass.h"
+
+namespace spvtools {
+namespace opt {
+
+// See optimizer.hpp for documentation.
+class EliminateDeadOutputStoresPass : public Pass {
+ public:
+  explicit EliminateDeadOutputStoresPass(
+      std::unordered_set<uint32_t>* live_locs,
+      std::unordered_set<uint32_t>* live_builtins)
+      : live_locs_(live_locs), live_builtins_(live_builtins) {}
+
+  const char* name() const override { return "eliminate-dead-output-stores"; }
+  Status Process() override;
+
+  // Return the mask of preserved Analyses.
+  IRContext::Analysis GetPreservedAnalyses() override {
+    return IRContext::kAnalysisDefUse |
+           IRContext::kAnalysisInstrToBlockMapping |
+           IRContext::kAnalysisCombinators | IRContext::kAnalysisCFG |
+           IRContext::kAnalysisDominatorAnalysis |
+           IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
+           IRContext::kAnalysisConstants | IRContext::kAnalysisTypes;
+  }
+
+ private:
+  // Initialize elimination
+  void InitializeElimination();
+
+  // Do dead output store analysis
+  Status DoDeadOutputStoreAnalysis();
+
+  // Do dead output store analysis
+  Status DoDeadOutputStoreElimination();
+
+  // Mark all locations live
+  void MarkAllLocsLive();
+
+  // Kill all stores resulting from |ref|.
+  void KillAllStoresOfRef(Instruction* ref);
+
+  // Kill all dead stores resulting from |user| of loc-based |var|.
+  void KillAllDeadStoresOfLocRef(Instruction* user, Instruction* var);
+
+  // Kill all dead stores resulting from |user| of builtin |var|.
+  void KillAllDeadStoresOfBuiltinRef(Instruction* user, Instruction* var);
+
+  // Return true if any of |count| locations starting at location |start| are
+  // live.
+  bool AnyLocsAreLive(uint32_t start, uint32_t count);
+
+  // Return true if builtin |bi| is live.
+  bool IsLiveBuiltin(uint32_t bi);
+
+  std::unordered_set<uint32_t>* live_locs_;
+  std::unordered_set<uint32_t>* live_builtins_;
+
+  std::vector<Instruction*> kill_list_;
+};
+
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // SOURCE_OPT_ELIMINATE_DEAD_OUTPUT_STORES_H_
diff --git a/third_party/SPIRV-Tools/source/opt/feature_manager.cpp b/third_party/SPIRV-Tools/source/opt/feature_manager.cpp
index a590271..2a1c006 100644
--- a/third_party/SPIRV-Tools/source/opt/feature_manager.cpp
+++ b/third_party/SPIRV-Tools/source/opt/feature_manager.cpp
@@ -36,7 +36,7 @@
 }
 
 void FeatureManager::AddExtension(Instruction* ext) {
-  assert(ext->opcode() == SpvOpExtension &&
+  assert(ext->opcode() == spv::Op::OpExtension &&
          "Expecting an extension instruction.");
 
   const std::string name = ext->GetInOperand(0u).AsString();
@@ -51,27 +51,27 @@
   extensions_.Remove(ext);
 }
 
-void FeatureManager::AddCapability(SpvCapability cap) {
+void FeatureManager::AddCapability(spv::Capability cap) {
   if (capabilities_.Contains(cap)) return;
 
   capabilities_.Add(cap);
 
   spv_operand_desc desc = {};
-  if (SPV_SUCCESS ==
-      grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc)) {
+  if (SPV_SUCCESS == grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
+                                            uint32_t(cap), &desc)) {
     CapabilitySet(desc->numCapabilities, desc->capabilities)
-        .ForEach([this](SpvCapability c) { AddCapability(c); });
+        .ForEach([this](spv::Capability c) { AddCapability(c); });
   }
 }
 
-void FeatureManager::RemoveCapability(SpvCapability cap) {
+void FeatureManager::RemoveCapability(spv::Capability cap) {
   if (!capabilities_.Contains(cap)) return;
   capabilities_.Remove(cap);
 }
 
 void FeatureManager::AddCapabilities(Module* module) {
   for (Instruction& inst : module->capabilities()) {
-    AddCapability(static_cast<SpvCapability>(inst.GetSingleWordInOperand(0)));
+    AddCapability(static_cast<spv::Capability>(inst.GetSingleWordInOperand(0)));
   }
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/feature_manager.h b/third_party/SPIRV-Tools/source/opt/feature_manager.h
index 68c8e9a..b96988d 100644
--- a/third_party/SPIRV-Tools/source/opt/feature_manager.h
+++ b/third_party/SPIRV-Tools/source/opt/feature_manager.h
@@ -34,12 +34,12 @@
   void RemoveExtension(Extension extension);
 
   // Returns true if |cap| is an enabled capability in the module.
-  bool HasCapability(SpvCapability cap) const {
+  bool HasCapability(spv::Capability cap) const {
     return capabilities_.Contains(cap);
   }
 
   // Removes the given |capability| from the current FeatureManager.
-  void RemoveCapability(SpvCapability capability);
+  void RemoveCapability(spv::Capability capability);
 
   // Analyzes |module| and records enabled extensions and capabilities.
   void Analyze(Module* module);
@@ -66,7 +66,7 @@
 
   // Adds the given |capability| and all implied capabilities into the current
   // FeatureManager.
-  void AddCapability(SpvCapability capability);
+  void AddCapability(spv::Capability capability);
 
   // Add the extension |ext| to the feature manager.
   void AddExtension(Instruction* ext);
diff --git a/third_party/SPIRV-Tools/source/opt/fix_func_call_arguments.cpp b/third_party/SPIRV-Tools/source/opt/fix_func_call_arguments.cpp
index d140fb4..f3486be 100644
--- a/third_party/SPIRV-Tools/source/opt/fix_func_call_arguments.cpp
+++ b/third_party/SPIRV-Tools/source/opt/fix_func_call_arguments.cpp
@@ -29,7 +29,7 @@
   if (ModuleHasASingleFunction()) return Status::SuccessWithoutChange;
   for (auto& func : *get_module()) {
     func.ForEachInst([this, &modified](Instruction* inst) {
-      if (inst->opcode() == SpvOpFunctionCall) {
+      if (inst->opcode() == spv::Op::OpFunctionCall) {
         modified |= FixFuncCallArguments(inst);
       }
     });
@@ -44,7 +44,7 @@
     Operand& op = func_call_inst->GetInOperand(i);
     if (op.type != SPV_OPERAND_TYPE_ID) continue;
     Instruction* operand_inst = get_def_use_mgr()->GetDef(op.AsId());
-    if (operand_inst->opcode() == SpvOpAccessChain) {
+    if (operand_inst->opcode() == spv::Op::OpAccessChain) {
       uint32_t var_id =
           ReplaceAccessChainFuncCallArguments(func_call_inst, operand_inst);
       func_call_inst->SetInOperand(i, {var_id});
@@ -71,10 +71,11 @@
   Instruction* op_type =
       get_def_use_mgr()->GetDef(op_ptr_type->GetSingleWordInOperand(1));
   uint32_t varType = context()->get_type_mgr()->FindPointerToType(
-      op_type->result_id(), SpvStorageClassFunction);
+      op_type->result_id(), spv::StorageClass::Function);
   // Create new variable
   builder.SetInsertPoint(variable_insertion_point);
-  Instruction* var = builder.AddVariable(varType, SpvStorageClassFunction);
+  Instruction* var =
+      builder.AddVariable(varType, uint32_t(spv::StorageClass::Function));
   // Load access chain to the new variable before function call
   builder.SetInsertPoint(func_call_inst);
 
diff --git a/third_party/SPIRV-Tools/source/opt/fix_storage_class.cpp b/third_party/SPIRV-Tools/source/opt/fix_storage_class.cpp
index 04eb132..5597e82 100644
--- a/third_party/SPIRV-Tools/source/opt/fix_storage_class.cpp
+++ b/third_party/SPIRV-Tools/source/opt/fix_storage_class.cpp
@@ -26,7 +26,7 @@
   bool modified = false;
 
   get_module()->ForEachInst([this, &modified](Instruction* inst) {
-    if (inst->opcode() == SpvOpVariable) {
+    if (inst->opcode() == spv::Op::OpVariable) {
       std::set<uint32_t> seen;
       std::vector<std::pair<Instruction*, uint32_t>> uses;
       get_def_use_mgr()->ForEachUse(inst,
@@ -37,7 +37,7 @@
       for (auto& use : uses) {
         modified |= PropagateStorageClass(
             use.first,
-            static_cast<SpvStorageClass>(inst->GetSingleWordInOperand(0)),
+            static_cast<spv::StorageClass>(inst->GetSingleWordInOperand(0)),
             &seen);
         assert(seen.empty() && "Seen was not properly reset.");
         modified |=
@@ -50,14 +50,14 @@
 }
 
 bool FixStorageClass::PropagateStorageClass(Instruction* inst,
-                                            SpvStorageClass storage_class,
+                                            spv::StorageClass storage_class,
                                             std::set<uint32_t>* seen) {
   if (!IsPointerResultType(inst)) {
     return false;
   }
 
   if (IsPointerToStorageClass(inst, storage_class)) {
-    if (inst->opcode() == SpvOpPhi) {
+    if (inst->opcode() == spv::Op::OpPhi) {
       if (!seen->insert(inst->result_id()).second) {
         return false;
       }
@@ -71,34 +71,34 @@
       modified |= PropagateStorageClass(use, storage_class, seen);
     }
 
-    if (inst->opcode() == SpvOpPhi) {
+    if (inst->opcode() == spv::Op::OpPhi) {
       seen->erase(inst->result_id());
     }
     return modified;
   }
 
   switch (inst->opcode()) {
-    case SpvOpAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpCopyObject:
-    case SpvOpPhi:
-    case SpvOpSelect:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpPhi:
+    case spv::Op::OpSelect:
       FixInstructionStorageClass(inst, storage_class, seen);
       return true;
-    case SpvOpFunctionCall:
+    case spv::Op::OpFunctionCall:
       // We cannot be sure of the actual connection between the storage class
       // of the parameter and the storage class of the result, so we should not
       // do anything.  If the result type needs to be fixed, the function call
       // should be inlined.
       return false;
-    case SpvOpImageTexelPointer:
-    case SpvOpLoad:
-    case SpvOpStore:
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
-    case SpvOpVariable:
-    case SpvOpBitcast:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
+    case spv::Op::OpVariable:
+    case spv::Op::OpBitcast:
       // Nothing to change for these opcode.  The result type is the same
       // regardless of the storage class of the operand.
       return false;
@@ -109,9 +109,9 @@
   }
 }
 
-void FixStorageClass::FixInstructionStorageClass(Instruction* inst,
-                                                 SpvStorageClass storage_class,
-                                                 std::set<uint32_t>* seen) {
+void FixStorageClass::FixInstructionStorageClass(
+    Instruction* inst, spv::StorageClass storage_class,
+    std::set<uint32_t>* seen) {
   assert(IsPointerResultType(inst) &&
          "The result type of the instruction must be a pointer.");
 
@@ -126,10 +126,10 @@
 }
 
 void FixStorageClass::ChangeResultStorageClass(
-    Instruction* inst, SpvStorageClass storage_class) const {
+    Instruction* inst, spv::StorageClass storage_class) const {
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   Instruction* result_type_inst = get_def_use_mgr()->GetDef(inst->type_id());
-  assert(result_type_inst->opcode() == SpvOpTypePointer);
+  assert(result_type_inst->opcode() == spv::Op::OpTypePointer);
   uint32_t pointee_type_id = result_type_inst->GetSingleWordInOperand(1);
   uint32_t new_result_type_id =
       type_mgr->FindPointerToType(pointee_type_id, storage_class);
@@ -147,7 +147,7 @@
 }
 
 bool FixStorageClass::IsPointerToStorageClass(Instruction* inst,
-                                              SpvStorageClass storage_class) {
+                                              spv::StorageClass storage_class) {
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   analysis::Type* pType = type_mgr->GetType(inst->type_id());
   const analysis::Pointer* result_type = pType->AsPointer();
@@ -180,39 +180,39 @@
   // particular type, then we want find that type.
   uint32_t new_type_id = 0;
   switch (inst->opcode()) {
-    case SpvOpAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       if (op_idx == 2) {
         new_type_id = WalkAccessChainType(inst, type_id);
       }
       break;
-    case SpvOpCopyObject:
+    case spv::Op::OpCopyObject:
       new_type_id = type_id;
       break;
-    case SpvOpPhi:
+    case spv::Op::OpPhi:
       if (seen->insert(inst->result_id()).second) {
         new_type_id = type_id;
       }
       break;
-    case SpvOpSelect:
+    case spv::Op::OpSelect:
       if (op_idx > 2) {
         new_type_id = type_id;
       }
       break;
-    case SpvOpFunctionCall:
+    case spv::Op::OpFunctionCall:
       // We cannot be sure of the actual connection between the type
       // of the parameter and the type of the result, so we should not
       // do anything.  If the result type needs to be fixed, the function call
       // should be inlined.
       return false;
-    case SpvOpLoad: {
+    case spv::Op::OpLoad: {
       Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
       new_type_id = type_inst->GetSingleWordInOperand(1);
       break;
     }
-    case SpvOpStore: {
+    case spv::Op::OpStore: {
       uint32_t obj_id = inst->GetSingleWordInOperand(1);
       Instruction* obj_inst = get_def_use_mgr()->GetDef(obj_id);
       uint32_t obj_type_id = obj_inst->type_id();
@@ -237,18 +237,18 @@
         context()->UpdateDefUse(inst);
       }
     } break;
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       // TODO: May need to expand the copy as we do with the stores.
       break;
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
       // TODO: DXC does not seem to generate code that will require changes to
       // these opcode.  The can be implemented when they come up.
       break;
-    case SpvOpImageTexelPointer:
-    case SpvOpBitcast:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpBitcast:
       // Nothing to change for these opcode.  The result type is the same
       // regardless of the type of the operand.
       return false;
@@ -278,7 +278,7 @@
       PropagateType(use.first, new_type_id, use.second, seen);
     }
 
-    if (inst->opcode() == SpvOpPhi) {
+    if (inst->opcode() == spv::Op::OpPhi) {
       seen->erase(inst->result_id());
     }
   }
@@ -288,12 +288,12 @@
 uint32_t FixStorageClass::WalkAccessChainType(Instruction* inst, uint32_t id) {
   uint32_t start_idx = 0;
   switch (inst->opcode()) {
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
       start_idx = 1;
       break;
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       start_idx = 2;
       break;
     default:
@@ -302,19 +302,19 @@
   }
 
   Instruction* orig_type_inst = get_def_use_mgr()->GetDef(id);
-  assert(orig_type_inst->opcode() == SpvOpTypePointer);
+  assert(orig_type_inst->opcode() == spv::Op::OpTypePointer);
   id = orig_type_inst->GetSingleWordInOperand(1);
 
   for (uint32_t i = start_idx; i < inst->NumInOperands(); ++i) {
     Instruction* type_inst = get_def_use_mgr()->GetDef(id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
         id = type_inst->GetSingleWordInOperand(0);
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         const analysis::Constant* index_const =
             context()->get_constant_mgr()->FindDeclaredConstant(
                 inst->GetSingleWordInOperand(i));
@@ -330,8 +330,8 @@
   }
 
   return context()->get_type_mgr()->FindPointerToType(
-      id,
-      static_cast<SpvStorageClass>(orig_type_inst->GetSingleWordInOperand(0)));
+      id, static_cast<spv::StorageClass>(
+              orig_type_inst->GetSingleWordInOperand(0)));
 }
 
 // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/fix_storage_class.h b/third_party/SPIRV-Tools/source/opt/fix_storage_class.h
index e72e864..6c67acd 100644
--- a/third_party/SPIRV-Tools/source/opt/fix_storage_class.h
+++ b/third_party/SPIRV-Tools/source/opt/fix_storage_class.h
@@ -48,7 +48,7 @@
   // appropriate, and propagates the change to the users of |inst| as well.
   // Returns true of any changes were made.
   // |seen| is used to track OpPhi instructions that should not be processed.
-  bool PropagateStorageClass(Instruction* inst, SpvStorageClass storage_class,
+  bool PropagateStorageClass(Instruction* inst, spv::StorageClass storage_class,
                              std::set<uint32_t>* seen);
 
   // Changes the storage class of the result of |inst| to |storage_class|.
@@ -58,13 +58,13 @@
   // |seen| is used to track OpPhi instructions that should not be processed by
   // |PropagateStorageClass|
   void FixInstructionStorageClass(Instruction* inst,
-                                  SpvStorageClass storage_class,
+                                  spv::StorageClass storage_class,
                                   std::set<uint32_t>* seen);
 
   // Changes the storage class of the result of |inst| to |storage_class|.  The
   // result type of |inst| must be a pointer.
   void ChangeResultStorageClass(Instruction* inst,
-                                SpvStorageClass storage_class) const;
+                                spv::StorageClass storage_class) const;
 
   // Returns true if the result type of |inst| is a pointer.
   bool IsPointerResultType(Instruction* inst);
@@ -72,7 +72,7 @@
   // Returns true if the result of |inst| is a pointer to storage class
   // |storage_class|.
   bool IsPointerToStorageClass(Instruction* inst,
-                               SpvStorageClass storage_class);
+                               spv::StorageClass storage_class);
 
   // Change |inst| to match that operand |op_idx| now has type |type_id|, and
   // adjust any uses of |inst| accordingly. Returns true if the code changed.
diff --git a/third_party/SPIRV-Tools/source/opt/flatten_decoration_pass.cpp b/third_party/SPIRV-Tools/source/opt/flatten_decoration_pass.cpp
index f4de911..c878c09 100644
--- a/third_party/SPIRV-Tools/source/opt/flatten_decoration_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/flatten_decoration_pass.cpp
@@ -49,16 +49,16 @@
   // Rely on unordered_map::operator[] to create its entries on first access.
   for (const auto& inst : annotations) {
     switch (inst.opcode()) {
-      case SpvOp::SpvOpDecorationGroup:
+      case spv::Op::OpDecorationGroup:
         group_ids.insert(inst.result_id());
         break;
-      case SpvOp::SpvOpGroupDecorate: {
+      case spv::Op::OpGroupDecorate: {
         Words& words = normal_uses[inst.GetSingleWordInOperand(0)];
         for (uint32_t i = 1; i < inst.NumInOperandWords(); i++) {
           words.push_back(inst.GetSingleWordInOperand(i));
         }
       } break;
-      case SpvOp::SpvOpGroupMemberDecorate: {
+      case spv::Op::OpGroupMemberDecorate: {
         Words& words = member_uses[inst.GetSingleWordInOperand(0)];
         for (uint32_t i = 1; i < inst.NumInOperandWords(); i++) {
           words.push_back(inst.GetSingleWordInOperand(i));
@@ -77,12 +77,12 @@
     // Should we replace this instruction?
     bool replace = false;
     switch (inst_iter->opcode()) {
-      case SpvOp::SpvOpDecorationGroup:
-      case SpvOp::SpvOpGroupDecorate:
-      case SpvOp::SpvOpGroupMemberDecorate:
+      case spv::Op::OpDecorationGroup:
+      case spv::Op::OpGroupDecorate:
+      case spv::Op::OpGroupMemberDecorate:
         replace = true;
         break;
-      case SpvOp::SpvOpDecorate: {
+      case spv::Op::OpDecorate: {
         // If this decoration targets a group, then replace it
         // by sets of normal and member decorations.
         const uint32_t group = inst_iter->GetSingleWordOperand(0);
@@ -115,7 +115,7 @@
             operands.insert(operands.end(), decoration_operands_iter,
                             inst_iter->end());
             std::unique_ptr<Instruction> new_inst(new Instruction(
-                context(), SpvOp::SpvOpMemberDecorate, 0, 0, operands));
+                context(), spv::Op::OpMemberDecorate, 0, 0, operands));
             inst_iter = inst_iter.InsertBefore(std::move(new_inst));
             ++inst_iter;
             replace = true;
@@ -146,7 +146,7 @@
   if (!group_ids.empty()) {
     for (auto debug_inst_iter = context()->debug2_begin();
          debug_inst_iter != context()->debug2_end();) {
-      if (debug_inst_iter->opcode() == SpvOp::SpvOpName) {
+      if (debug_inst_iter->opcode() == spv::Op::OpName) {
         const uint32_t target = debug_inst_iter->GetSingleWordOperand(0);
         if (group_ids.count(target)) {
           debug_inst_iter = debug_inst_iter.Erase();
diff --git a/third_party/SPIRV-Tools/source/opt/fold.cpp b/third_party/SPIRV-Tools/source/opt/fold.cpp
index b903da6..3c234c4 100644
--- a/third_party/SPIRV-Tools/source/opt/fold.cpp
+++ b/third_party/SPIRV-Tools/source/opt/fold.cpp
@@ -42,23 +42,24 @@
 
 }  // namespace
 
-uint32_t InstructionFolder::UnaryOperate(SpvOp opcode, uint32_t operand) const {
+uint32_t InstructionFolder::UnaryOperate(spv::Op opcode,
+                                         uint32_t operand) const {
   switch (opcode) {
     // Arthimetics
-    case SpvOp::SpvOpSNegate: {
+    case spv::Op::OpSNegate: {
       int32_t s_operand = static_cast<int32_t>(operand);
       if (s_operand == std::numeric_limits<int32_t>::min()) {
         return s_operand;
       }
       return -s_operand;
     }
-    case SpvOp::SpvOpNot:
+    case spv::Op::OpNot:
       return ~operand;
-    case SpvOp::SpvOpLogicalNot:
+    case spv::Op::OpLogicalNot:
       return !static_cast<bool>(operand);
-    case SpvOp::SpvOpUConvert:
+    case spv::Op::OpUConvert:
       return operand;
-    case SpvOp::SpvOpSConvert:
+    case spv::Op::OpSConvert:
       return operand;
     default:
       assert(false &&
@@ -67,31 +68,31 @@
   }
 }
 
-uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
+uint32_t InstructionFolder::BinaryOperate(spv::Op opcode, uint32_t a,
                                           uint32_t b) const {
   switch (opcode) {
     // Arthimetics
-    case SpvOp::SpvOpIAdd:
+    case spv::Op::OpIAdd:
       return a + b;
-    case SpvOp::SpvOpISub:
+    case spv::Op::OpISub:
       return a - b;
-    case SpvOp::SpvOpIMul:
+    case spv::Op::OpIMul:
       return a * b;
-    case SpvOp::SpvOpUDiv:
+    case spv::Op::OpUDiv:
       if (b != 0) {
         return a / b;
       } else {
         // Dividing by 0 is undefined, so we will just pick 0.
         return 0;
       }
-    case SpvOp::SpvOpSDiv:
+    case spv::Op::OpSDiv:
       if (b != 0u) {
         return (static_cast<int32_t>(a)) / (static_cast<int32_t>(b));
       } else {
         // Dividing by 0 is undefined, so we will just pick 0.
         return 0;
       }
-    case SpvOp::SpvOpSRem: {
+    case spv::Op::OpSRem: {
       // The sign of non-zero result comes from the first operand: a. This is
       // guaranteed by C++11 rules for integer division operator. The division
       // result is rounded toward zero, so the result of '%' has the sign of
@@ -103,10 +104,10 @@
         return 0;
       }
     }
-    case SpvOp::SpvOpSMod: {
+    case spv::Op::OpSMod: {
       // The sign of non-zero result comes from the second operand: b
       if (b != 0u) {
-        int32_t rem = BinaryOperate(SpvOp::SpvOpSRem, a, b);
+        int32_t rem = BinaryOperate(spv::Op::OpSRem, a, b);
         int32_t b_prim = static_cast<int32_t>(b);
         return (rem + b_prim) % b_prim;
       } else {
@@ -114,7 +115,7 @@
         return 0;
       }
     }
-    case SpvOp::SpvOpUMod:
+    case spv::Op::OpUMod:
       if (b != 0u) {
         return (a % b);
       } else {
@@ -123,7 +124,7 @@
       }
 
     // Shifting
-    case SpvOp::SpvOpShiftRightLogical:
+    case spv::Op::OpShiftRightLogical:
       if (b >= 32) {
         // This is undefined behaviour when |b| > 32.  Choose 0 for consistency.
         // When |b| == 32, doing the shift in C++ in undefined, but the result
@@ -131,7 +132,7 @@
         return 0;
       }
       return a >> b;
-    case SpvOp::SpvOpShiftRightArithmetic:
+    case spv::Op::OpShiftRightArithmetic:
       if (b > 32) {
         // This is undefined behaviour.  Choose 0 for consistency.
         return 0;
@@ -146,7 +147,7 @@
         }
       }
       return (static_cast<int32_t>(a)) >> b;
-    case SpvOp::SpvOpShiftLeftLogical:
+    case spv::Op::OpShiftLeftLogical:
       if (b >= 32) {
         // This is undefined behaviour when |b| > 32.  Choose 0 for consistency.
         // When |b| == 32, doing the shift in C++ in undefined, but the result
@@ -156,43 +157,43 @@
       return a << b;
 
     // Bitwise operations
-    case SpvOp::SpvOpBitwiseOr:
+    case spv::Op::OpBitwiseOr:
       return a | b;
-    case SpvOp::SpvOpBitwiseAnd:
+    case spv::Op::OpBitwiseAnd:
       return a & b;
-    case SpvOp::SpvOpBitwiseXor:
+    case spv::Op::OpBitwiseXor:
       return a ^ b;
 
     // Logical
-    case SpvOp::SpvOpLogicalEqual:
+    case spv::Op::OpLogicalEqual:
       return (static_cast<bool>(a)) == (static_cast<bool>(b));
-    case SpvOp::SpvOpLogicalNotEqual:
+    case spv::Op::OpLogicalNotEqual:
       return (static_cast<bool>(a)) != (static_cast<bool>(b));
-    case SpvOp::SpvOpLogicalOr:
+    case spv::Op::OpLogicalOr:
       return (static_cast<bool>(a)) || (static_cast<bool>(b));
-    case SpvOp::SpvOpLogicalAnd:
+    case spv::Op::OpLogicalAnd:
       return (static_cast<bool>(a)) && (static_cast<bool>(b));
 
     // Comparison
-    case SpvOp::SpvOpIEqual:
+    case spv::Op::OpIEqual:
       return a == b;
-    case SpvOp::SpvOpINotEqual:
+    case spv::Op::OpINotEqual:
       return a != b;
-    case SpvOp::SpvOpULessThan:
+    case spv::Op::OpULessThan:
       return a < b;
-    case SpvOp::SpvOpSLessThan:
+    case spv::Op::OpSLessThan:
       return (static_cast<int32_t>(a)) < (static_cast<int32_t>(b));
-    case SpvOp::SpvOpUGreaterThan:
+    case spv::Op::OpUGreaterThan:
       return a > b;
-    case SpvOp::SpvOpSGreaterThan:
+    case spv::Op::OpSGreaterThan:
       return (static_cast<int32_t>(a)) > (static_cast<int32_t>(b));
-    case SpvOp::SpvOpULessThanEqual:
+    case spv::Op::OpULessThanEqual:
       return a <= b;
-    case SpvOp::SpvOpSLessThanEqual:
+    case spv::Op::OpSLessThanEqual:
       return (static_cast<int32_t>(a)) <= (static_cast<int32_t>(b));
-    case SpvOp::SpvOpUGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
       return a >= b;
-    case SpvOp::SpvOpSGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
       return (static_cast<int32_t>(a)) >= (static_cast<int32_t>(b));
     default:
       assert(false &&
@@ -201,10 +202,10 @@
   }
 }
 
-uint32_t InstructionFolder::TernaryOperate(SpvOp opcode, uint32_t a, uint32_t b,
-                                           uint32_t c) const {
+uint32_t InstructionFolder::TernaryOperate(spv::Op opcode, uint32_t a,
+                                           uint32_t b, uint32_t c) const {
   switch (opcode) {
-    case SpvOp::SpvOpSelect:
+    case spv::Op::OpSelect:
       return (static_cast<bool>(a)) ? b : c;
     default:
       assert(false &&
@@ -214,7 +215,7 @@
 }
 
 uint32_t InstructionFolder::OperateWords(
-    SpvOp opcode, const std::vector<uint32_t>& operand_words) const {
+    spv::Op opcode, const std::vector<uint32_t>& operand_words) const {
   switch (operand_words.size()) {
     case 1:
       return UnaryOperate(opcode, operand_words.front());
@@ -233,7 +234,7 @@
   auto identity_map = [](uint32_t id) { return id; };
   Instruction* folded_inst = FoldInstructionToConstant(inst, identity_map);
   if (folded_inst != nullptr) {
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {folded_inst->result_id()}}});
     return true;
   }
@@ -256,7 +257,7 @@
 // result in 32 bit word. Scalar constants with longer than 32-bit width are
 // not accepted in this function.
 uint32_t InstructionFolder::FoldScalars(
-    SpvOp opcode,
+    spv::Op opcode,
     const std::vector<const analysis::Constant*>& operands) const {
   assert(IsFoldableOpcode(opcode) &&
          "Unhandled instruction opcode in FoldScalars");
@@ -282,7 +283,7 @@
 bool InstructionFolder::FoldBinaryIntegerOpToConstant(
     Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map,
     uint32_t* result) const {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   analysis::ConstantManager* const_manger = context_->get_constant_mgr();
 
   uint32_t ids[2];
@@ -300,7 +301,7 @@
 
   switch (opcode) {
     // Arthimetics
-    case SpvOp::SpvOpIMul:
+    case spv::Op::OpIMul:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr && constants[i]->IsZero()) {
           *result = 0;
@@ -308,11 +309,11 @@
         }
       }
       break;
-    case SpvOp::SpvOpUDiv:
-    case SpvOp::SpvOpSDiv:
-    case SpvOp::SpvOpSRem:
-    case SpvOp::SpvOpSMod:
-    case SpvOp::SpvOpUMod:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpUMod:
       // This changes undefined behaviour (ie divide by 0) into a 0.
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr && constants[i]->IsZero()) {
@@ -323,8 +324,8 @@
       break;
 
     // Shifting
-    case SpvOp::SpvOpShiftRightLogical:
-    case SpvOp::SpvOpShiftLeftLogical:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftLeftLogical:
       if (constants[1] != nullptr) {
         // When shifting by a value larger than the size of the result, the
         // result is undefined.  We are setting the undefined behaviour to a
@@ -339,7 +340,7 @@
       break;
 
     // Bitwise operations
-    case SpvOp::SpvOpBitwiseOr:
+    case spv::Op::OpBitwiseOr:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr) {
           // TODO: Change the mask against a value based on the bit width of the
@@ -353,7 +354,7 @@
         }
       }
       break;
-    case SpvOp::SpvOpBitwiseAnd:
+    case spv::Op::OpBitwiseAnd:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr) {
           if (constants[i]->IsZero()) {
@@ -365,7 +366,7 @@
       break;
 
     // Comparison
-    case SpvOp::SpvOpULessThan:
+    case spv::Op::OpULessThan:
       if (constants[0] != nullptr &&
           constants[0]->GetU32BitValue() == UINT32_MAX) {
         *result = false;
@@ -376,7 +377,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpSLessThan:
+    case spv::Op::OpSLessThan:
       if (constants[0] != nullptr &&
           constants[0]->GetS32BitValue() == INT32_MAX) {
         *result = false;
@@ -388,7 +389,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpUGreaterThan:
+    case spv::Op::OpUGreaterThan:
       if (constants[0] != nullptr && constants[0]->IsZero()) {
         *result = false;
         return true;
@@ -399,7 +400,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpSGreaterThan:
+    case spv::Op::OpSGreaterThan:
       if (constants[0] != nullptr &&
           constants[0]->GetS32BitValue() == INT32_MIN) {
         *result = false;
@@ -411,7 +412,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpULessThanEqual:
+    case spv::Op::OpULessThanEqual:
       if (constants[0] != nullptr && constants[0]->IsZero()) {
         *result = true;
         return true;
@@ -422,7 +423,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpSLessThanEqual:
+    case spv::Op::OpSLessThanEqual:
       if (constants[0] != nullptr &&
           constants[0]->GetS32BitValue() == INT32_MIN) {
         *result = true;
@@ -434,7 +435,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpUGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
       if (constants[0] != nullptr &&
           constants[0]->GetU32BitValue() == UINT32_MAX) {
         *result = true;
@@ -445,7 +446,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpSGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
       if (constants[0] != nullptr &&
           constants[0]->GetS32BitValue() == INT32_MAX) {
         *result = true;
@@ -466,7 +467,7 @@
 bool InstructionFolder::FoldBinaryBooleanOpToConstant(
     Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map,
     uint32_t* result) const {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   analysis::ConstantManager* const_manger = context_->get_constant_mgr();
 
   uint32_t ids[2];
@@ -484,7 +485,7 @@
 
   switch (opcode) {
     // Logical
-    case SpvOp::SpvOpLogicalOr:
+    case spv::Op::OpLogicalOr:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr) {
           if (constants[i]->value()) {
@@ -494,7 +495,7 @@
         }
       }
       break;
-    case SpvOp::SpvOpLogicalAnd:
+    case spv::Op::OpLogicalAnd:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr) {
           if (!constants[i]->value()) {
@@ -526,7 +527,7 @@
 }
 
 std::vector<uint32_t> InstructionFolder::FoldVectors(
-    SpvOp opcode, uint32_t num_dims,
+    spv::Op opcode, uint32_t num_dims,
     const std::vector<const analysis::Constant*>& operands) const {
   assert(IsFoldableOpcode(opcode) &&
          "Unhandled instruction opcode in FoldVectors");
@@ -570,44 +571,44 @@
   return result;
 }
 
-bool InstructionFolder::IsFoldableOpcode(SpvOp opcode) const {
+bool InstructionFolder::IsFoldableOpcode(spv::Op opcode) const {
   // NOTE: Extend to more opcodes as new cases are handled in the folder
   // functions.
   switch (opcode) {
-    case SpvOp::SpvOpBitwiseAnd:
-    case SpvOp::SpvOpBitwiseOr:
-    case SpvOp::SpvOpBitwiseXor:
-    case SpvOp::SpvOpIAdd:
-    case SpvOp::SpvOpIEqual:
-    case SpvOp::SpvOpIMul:
-    case SpvOp::SpvOpINotEqual:
-    case SpvOp::SpvOpISub:
-    case SpvOp::SpvOpLogicalAnd:
-    case SpvOp::SpvOpLogicalEqual:
-    case SpvOp::SpvOpLogicalNot:
-    case SpvOp::SpvOpLogicalNotEqual:
-    case SpvOp::SpvOpLogicalOr:
-    case SpvOp::SpvOpNot:
-    case SpvOp::SpvOpSDiv:
-    case SpvOp::SpvOpSelect:
-    case SpvOp::SpvOpSGreaterThan:
-    case SpvOp::SpvOpSGreaterThanEqual:
-    case SpvOp::SpvOpShiftLeftLogical:
-    case SpvOp::SpvOpShiftRightArithmetic:
-    case SpvOp::SpvOpShiftRightLogical:
-    case SpvOp::SpvOpSLessThan:
-    case SpvOp::SpvOpSLessThanEqual:
-    case SpvOp::SpvOpSMod:
-    case SpvOp::SpvOpSNegate:
-    case SpvOp::SpvOpSRem:
-    case SpvOp::SpvOpSConvert:
-    case SpvOp::SpvOpUConvert:
-    case SpvOp::SpvOpUDiv:
-    case SpvOp::SpvOpUGreaterThan:
-    case SpvOp::SpvOpUGreaterThanEqual:
-    case SpvOp::SpvOpULessThan:
-    case SpvOp::SpvOpULessThanEqual:
-    case SpvOp::SpvOpUMod:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpIMul:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpISub:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpNot:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpSelect:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpSMod:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpUMod:
       return true;
     default:
       return false;
@@ -627,8 +628,7 @@
     Instruction* inst, std::function<uint32_t(uint32_t)> id_map) const {
   analysis::ConstantManager* const_mgr = context_->get_constant_mgr();
 
-  if (!inst->IsFoldableByFoldScalar() &&
-      !GetConstantFoldingRules().HasFoldingRule(inst)) {
+  if (!inst->IsFoldableByFoldScalar() && !HasConstFoldingRule(inst)) {
     return nullptr;
   }
   // Collect the values of the constant parameters.
@@ -686,11 +686,11 @@
 
 bool InstructionFolder::IsFoldableType(Instruction* type_inst) const {
   // Support 32-bit integers.
-  if (type_inst->opcode() == SpvOpTypeInt) {
+  if (type_inst->opcode() == spv::Op::OpTypeInt) {
     return type_inst->GetSingleWordInOperand(0) == 32;
   }
   // Support booleans.
-  if (type_inst->opcode() == SpvOpTypeBool) {
+  if (type_inst->opcode() == spv::Op::OpTypeBool) {
     return true;
   }
   // Nothing else yet.
@@ -700,7 +700,7 @@
 bool InstructionFolder::FoldInstruction(Instruction* inst) const {
   bool modified = false;
   Instruction* folded_inst(inst);
-  while (folded_inst->opcode() != SpvOpCopyObject &&
+  while (folded_inst->opcode() != spv::Op::OpCopyObject &&
          FoldInstructionInternal(&*folded_inst)) {
     modified = true;
   }
diff --git a/third_party/SPIRV-Tools/source/opt/fold.h b/third_party/SPIRV-Tools/source/opt/fold.h
index 9e7c470..9a131d0 100644
--- a/third_party/SPIRV-Tools/source/opt/fold.h
+++ b/third_party/SPIRV-Tools/source/opt/fold.h
@@ -55,7 +55,7 @@
   // IsFoldableOpcode test. If any error occurs during folding, the folder will
   // fail with a call to assert.
   uint32_t FoldScalars(
-      SpvOp opcode,
+      spv::Op opcode,
       const std::vector<const analysis::Constant*>& operands) const;
 
   // Returns the result of performing an operation with the given |opcode| over
@@ -72,12 +72,12 @@
   // IsFoldableOpcode test. If any error occurs during folding, the folder will
   // fail with a call to assert.
   std::vector<uint32_t> FoldVectors(
-      SpvOp opcode, uint32_t num_dims,
+      spv::Op opcode, uint32_t num_dims,
       const std::vector<const analysis::Constant*>& operands) const;
 
   // Returns true if |opcode| represents an operation handled by FoldScalars or
   // FoldVectors.
-  bool IsFoldableOpcode(SpvOp opcode) const;
+  bool IsFoldableOpcode(spv::Op opcode) const;
 
   // Returns true if |cst| is supported by FoldScalars and FoldVectors.
   bool IsFoldableConstant(const analysis::Constant* cst) const;
@@ -126,22 +126,22 @@
 
   // Returns the single-word result from performing the given unary operation on
   // the operand value which is passed in as a 32-bit word.
-  uint32_t UnaryOperate(SpvOp opcode, uint32_t operand) const;
+  uint32_t UnaryOperate(spv::Op opcode, uint32_t operand) const;
 
   // Returns the single-word result from performing the given binary operation
   // on the operand values which are passed in as two 32-bit word.
-  uint32_t BinaryOperate(SpvOp opcode, uint32_t a, uint32_t b) const;
+  uint32_t BinaryOperate(spv::Op opcode, uint32_t a, uint32_t b) const;
 
   // Returns the single-word result from performing the given ternary operation
   // on the operand values which are passed in as three 32-bit word.
-  uint32_t TernaryOperate(SpvOp opcode, uint32_t a, uint32_t b,
+  uint32_t TernaryOperate(spv::Op opcode, uint32_t a, uint32_t b,
                           uint32_t c) const;
 
   // Returns the single-word result from performing the given operation on the
   // operand words. This only works with 32-bit operations and uses boolean
   // convention that 0u is false, and anything else is boolean true.
   // TODO(qining): Support operands other than 32-bit wide.
-  uint32_t OperateWords(SpvOp opcode,
+  uint32_t OperateWords(spv::Op opcode,
                         const std::vector<uint32_t>& operand_words) const;
 
   bool FoldInstructionInternal(Instruction* inst) const;
diff --git a/third_party/SPIRV-Tools/source/opt/fold_spec_constant_op_and_composite_pass.cpp b/third_party/SPIRV-Tools/source/opt/fold_spec_constant_op_and_composite_pass.cpp
index 85f11fd..132be0c 100644
--- a/third_party/SPIRV-Tools/source/opt/fold_spec_constant_op_and_composite_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/fold_spec_constant_op_and_composite_pass.cpp
@@ -28,6 +28,7 @@
 
 Pass::Status FoldSpecConstantOpAndCompositePass::Process() {
   bool modified = false;
+  analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
   // Traverse through all the constant defining instructions. For Normal
   // Constants whose values are determined and do not depend on OpUndef
   // instructions, records their values in two internal maps: id_to_const_val_
@@ -62,17 +63,17 @@
     // used in OpSpecConstant{Composite|Op} instructions.
     // TODO(qining): If the constant or its type has decoration, we may need
     // to skip it.
-    if (context()->get_constant_mgr()->GetType(inst) &&
-        !context()->get_constant_mgr()->GetType(inst)->decoration_empty())
+    if (const_mgr->GetType(inst) &&
+        !const_mgr->GetType(inst)->decoration_empty())
       continue;
-    switch (SpvOp opcode = inst->opcode()) {
+    switch (spv::Op opcode = inst->opcode()) {
       // Records the values of Normal Constants.
-      case SpvOp::SpvOpConstantTrue:
-      case SpvOp::SpvOpConstantFalse:
-      case SpvOp::SpvOpConstant:
-      case SpvOp::SpvOpConstantNull:
-      case SpvOp::SpvOpConstantComposite:
-      case SpvOp::SpvOpSpecConstantComposite: {
+      case spv::Op::OpConstantTrue:
+      case spv::Op::OpConstantFalse:
+      case spv::Op::OpConstant:
+      case spv::Op::OpConstantNull:
+      case spv::Op::OpConstantComposite:
+      case spv::Op::OpSpecConstantComposite: {
         // A Constant instance will be created if the given instruction is a
         // Normal Constant whose value(s) are fixed. Note that for a composite
         // Spec Constant defined with OpSpecConstantComposite instruction, if
@@ -80,15 +81,14 @@
         // Constant will be turned in to a Normal Constant. In that case, a
         // Constant instance should also be created successfully and recorded
         // in the id_to_const_val_ and const_val_to_id_ mapps.
-        if (auto const_value =
-                context()->get_constant_mgr()->GetConstantFromInst(inst)) {
+        if (auto const_value = const_mgr->GetConstantFromInst(inst)) {
           // Need to replace the OpSpecConstantComposite instruction with a
           // corresponding OpConstantComposite instruction.
-          if (opcode == SpvOp::SpvOpSpecConstantComposite) {
-            inst->SetOpcode(SpvOp::SpvOpConstantComposite);
+          if (opcode == spv::Op::OpSpecConstantComposite) {
+            inst->SetOpcode(spv::Op::OpConstantComposite);
             modified = true;
           }
-          context()->get_constant_mgr()->MapConstantToInst(const_value, inst);
+          const_mgr->MapConstantToInst(const_value, inst);
         }
         break;
       }
@@ -99,7 +99,7 @@
       // Constants will be added to id_to_const_val_ and const_val_to_id_ so
       // that we can use the new Normal Constants when folding following Spec
       // Constants.
-      case SpvOp::SpvOpSpecConstantOp:
+      case spv::Op::OpSpecConstantOp:
         modified |= ProcessOpSpecConstantOp(&inst_iter);
         break;
       default:
@@ -118,11 +118,11 @@
          "The first in-operand of OpSpecConstantOp instruction must be of "
          "SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER type");
 
-  switch (static_cast<SpvOp>(inst->GetSingleWordInOperand(0))) {
-    case SpvOp::SpvOpCompositeExtract:
-    case SpvOp::SpvOpVectorShuffle:
-    case SpvOp::SpvOpCompositeInsert:
-    case SpvOp::SpvOpQuantizeToF16:
+  switch (static_cast<spv::Op>(inst->GetSingleWordInOperand(0))) {
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpQuantizeToF16:
       folded_inst = FoldWithInstructionFolder(pos);
       break;
     default:
@@ -144,17 +144,9 @@
   return true;
 }
 
-uint32_t FoldSpecConstantOpAndCompositePass::GetTypeComponent(
-    uint32_t typeId, uint32_t element) const {
-  Instruction* type = context()->get_def_use_mgr()->GetDef(typeId);
-  uint32_t subtype = type->GetTypeComponent(element);
-  assert(subtype != 0);
-
-  return subtype;
-}
-
 Instruction* FoldSpecConstantOpAndCompositePass::FoldWithInstructionFolder(
     Module::inst_iterator* inst_iter_ptr) {
+  analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
   // If one of operands to the instruction is not a
   // constant, then we cannot fold this spec constant.
   for (uint32_t i = 1; i < (*inst_iter_ptr)->NumInOperands(); i++) {
@@ -164,7 +156,7 @@
       continue;
     }
     uint32_t id = operand.words[0];
-    if (context()->get_constant_mgr()->FindDeclaredConstant(id) == nullptr) {
+    if (const_mgr->FindDeclaredConstant(id) == nullptr) {
       return nullptr;
     }
   }
@@ -173,7 +165,7 @@
   // instruction and pass it to the instruction folder.
   std::unique_ptr<Instruction> inst((*inst_iter_ptr)->Clone(context()));
   inst->SetOpcode(
-      static_cast<SpvOp>((*inst_iter_ptr)->GetSingleWordInOperand(0)));
+      static_cast<spv::Op>((*inst_iter_ptr)->GetSingleWordInOperand(0)));
   inst->RemoveOperand(2);
 
   // We want the current instruction to be replaced by an |OpConstant*|
@@ -211,89 +203,10 @@
     new_const_inst->InsertAfter(insert_pos);
     get_def_use_mgr()->AnalyzeInstDefUse(new_const_inst);
   }
+  const_mgr->MapInst(new_const_inst);
   return new_const_inst;
 }
 
-Instruction* FoldSpecConstantOpAndCompositePass::DoVectorShuffle(
-    Module::inst_iterator* pos) {
-  Instruction* inst = &**pos;
-  analysis::Vector* result_vec_type =
-      context()->get_constant_mgr()->GetType(inst)->AsVector();
-  assert(inst->NumInOperands() - 1 > 2 &&
-         "OpSpecConstantOp DoVectorShuffle instruction requires more than 2 "
-         "operands (2 vector ids and at least one literal operand");
-  assert(result_vec_type &&
-         "The result of VectorShuffle must be of type vector");
-
-  // A temporary null constants that can be used as the components of the result
-  // vector. This is needed when any one of the vector operands are null
-  // constant.
-  const analysis::Constant* null_component_constants = nullptr;
-
-  // Get a concatenated vector of scalar constants. The vector should be built
-  // with the components from the first and the second operand of VectorShuffle.
-  std::vector<const analysis::Constant*> concatenated_components;
-  // Note that for OpSpecConstantOp, the second in-operand is the first id
-  // operand. The first in-operand is the spec opcode.
-  for (uint32_t i : {1, 2}) {
-    assert(inst->GetInOperand(i).type == SPV_OPERAND_TYPE_ID &&
-           "The vector operand must have a SPV_OPERAND_TYPE_ID type");
-    uint32_t operand_id = inst->GetSingleWordInOperand(i);
-    auto operand_const =
-        context()->get_constant_mgr()->FindDeclaredConstant(operand_id);
-    if (!operand_const) return nullptr;
-    const analysis::Type* operand_type = operand_const->type();
-    assert(operand_type->AsVector() &&
-           "The first two operand of VectorShuffle must be of vector type");
-    if (auto vec_const = operand_const->AsVectorConstant()) {
-      // case 1: current operand is a non-null vector constant.
-      concatenated_components.insert(concatenated_components.end(),
-                                     vec_const->GetComponents().begin(),
-                                     vec_const->GetComponents().end());
-    } else if (operand_const->AsNullConstant()) {
-      // case 2: current operand is a null vector constant. Create a temporary
-      // null scalar constant as the component.
-      if (!null_component_constants) {
-        const analysis::Type* component_type =
-            operand_type->AsVector()->element_type();
-        null_component_constants =
-            context()->get_constant_mgr()->GetConstant(component_type, {});
-      }
-      // Append the null scalar consts to the concatenated components
-      // vector.
-      concatenated_components.insert(concatenated_components.end(),
-                                     operand_type->AsVector()->element_count(),
-                                     null_component_constants);
-    } else {
-      // no other valid cases
-      return nullptr;
-    }
-  }
-  // Create null component constants if there are any. The component constants
-  // must be added to the module before the dependee composite constants to
-  // satisfy SSA def-use dominance.
-  if (null_component_constants) {
-    context()->get_constant_mgr()->BuildInstructionAndAddToModule(
-        null_component_constants, pos);
-  }
-  // Create the new vector constant with the selected components.
-  std::vector<const analysis::Constant*> selected_components;
-  for (uint32_t i = 3; i < inst->NumInOperands(); i++) {
-    assert(inst->GetInOperand(i).type == SPV_OPERAND_TYPE_LITERAL_INTEGER &&
-           "The literal operand must of type SPV_OPERAND_TYPE_LITERAL_INTEGER");
-    uint32_t literal = inst->GetSingleWordInOperand(i);
-    assert(literal < concatenated_components.size() &&
-           "Literal index out of bound of the concatenated vector");
-    selected_components.push_back(concatenated_components[literal]);
-  }
-  auto new_vec_const = MakeUnique<analysis::VectorConstant>(
-      result_vec_type, selected_components);
-  auto reg_vec_const =
-      context()->get_constant_mgr()->RegisterConstant(std::move(new_vec_const));
-  return context()->get_constant_mgr()->BuildInstructionAndAddToModule(
-      reg_vec_const, pos);
-}
-
 namespace {
 // A helper function to check the type for component wise operations. Returns
 // true if the type:
@@ -374,9 +287,9 @@
 Instruction* FoldSpecConstantOpAndCompositePass::DoComponentWiseOperation(
     Module::inst_iterator* pos) {
   const Instruction* inst = &**pos;
-  const analysis::Type* result_type =
-      context()->get_constant_mgr()->GetType(inst);
-  SpvOp spec_opcode = static_cast<SpvOp>(inst->GetSingleWordInOperand(0));
+  analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
+  const analysis::Type* result_type = const_mgr->GetType(inst);
+  spv::Op spec_opcode = static_cast<spv::Op>(inst->GetSingleWordInOperand(0));
   // Check and collect operands.
   std::vector<const analysis::Constant*> operands;
 
@@ -400,10 +313,9 @@
     // Scalar operation
     const uint32_t result_val =
         context()->get_instruction_folder().FoldScalars(spec_opcode, operands);
-    auto result_const = context()->get_constant_mgr()->GetConstant(
+    auto result_const = const_mgr->GetConstant(
         result_type, EncodeIntegerAsWords(*result_type, result_val));
-    return context()->get_constant_mgr()->BuildInstructionAndAddToModule(
-        result_const, pos);
+    return const_mgr->BuildInstructionAndAddToModule(result_const, pos);
   } else if (result_type->AsVector()) {
     // Vector operation
     const analysis::Type* element_type =
@@ -414,11 +326,10 @@
                                                         operands);
     std::vector<const analysis::Constant*> result_vector_components;
     for (const uint32_t r : result_vec) {
-      if (auto rc = context()->get_constant_mgr()->GetConstant(
+      if (auto rc = const_mgr->GetConstant(
               element_type, EncodeIntegerAsWords(*element_type, r))) {
         result_vector_components.push_back(rc);
-        if (!context()->get_constant_mgr()->BuildInstructionAndAddToModule(
-                rc, pos)) {
+        if (!const_mgr->BuildInstructionAndAddToModule(rc, pos)) {
           assert(false &&
                  "Failed to build and insert constant declaring instruction "
                  "for the given vector component constant");
@@ -429,10 +340,8 @@
     }
     auto new_vec_const = MakeUnique<analysis::VectorConstant>(
         result_type->AsVector(), result_vector_components);
-    auto reg_vec_const = context()->get_constant_mgr()->RegisterConstant(
-        std::move(new_vec_const));
-    return context()->get_constant_mgr()->BuildInstructionAndAddToModule(
-        reg_vec_const, pos);
+    auto reg_vec_const = const_mgr->RegisterConstant(std::move(new_vec_const));
+    return const_mgr->BuildInstructionAndAddToModule(reg_vec_const, pos);
   } else {
     // Cannot process invalid component wise operation. The result of component
     // wise operation must be of integer or bool scalar or vector of
diff --git a/third_party/SPIRV-Tools/source/opt/fold_spec_constant_op_and_composite_pass.h b/third_party/SPIRV-Tools/source/opt/fold_spec_constant_op_and_composite_pass.h
index 361d3ca..9a8fb40 100644
--- a/third_party/SPIRV-Tools/source/opt/fold_spec_constant_op_and_composite_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/fold_spec_constant_op_and_composite_pass.h
@@ -58,22 +58,11 @@
   // |inst_iter_ptr| using the instruction folder.
   Instruction* FoldWithInstructionFolder(Module::inst_iterator* inst_iter_ptr);
 
-  // Try to fold the OpSpecConstantOp VectorShuffle instruction pointed by the
-  // given instruction iterator to a normal constant defining instruction.
-  // Returns the pointer to the new constant defining instruction if succeeded.
-  // Otherwise return nullptr.
-  Instruction* DoVectorShuffle(Module::inst_iterator* inst_iter_ptr);
-
   // Try to fold the OpSpecConstantOp <component wise operations> instruction
   // pointed by the given instruction iterator to a normal constant defining
   // instruction. Returns the pointer to the new constant defining instruction
   // if succeeded, otherwise return nullptr.
   Instruction* DoComponentWiseOperation(Module::inst_iterator* inst_iter_ptr);
-
-  // Returns the |element|'th subtype of |type|.
-  //
-  // |type| must be a composite type.
-  uint32_t GetTypeComponent(uint32_t type, uint32_t element) const;
 };
 
 }  // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/folding_rules.cpp b/third_party/SPIRV-Tools/source/opt/folding_rules.cpp
index 2d778b9..1a4c03d 100644
--- a/third_party/SPIRV-Tools/source/opt/folding_rules.cpp
+++ b/third_party/SPIRV-Tools/source/opt/folding_rules.cpp
@@ -27,15 +27,15 @@
 namespace opt {
 namespace {
 
-const uint32_t kExtractCompositeIdInIdx = 0;
-const uint32_t kInsertObjectIdInIdx = 0;
-const uint32_t kInsertCompositeIdInIdx = 1;
-const uint32_t kExtInstSetIdInIdx = 0;
-const uint32_t kExtInstInstructionInIdx = 1;
-const uint32_t kFMixXIdInIdx = 2;
-const uint32_t kFMixYIdInIdx = 3;
-const uint32_t kFMixAIdInIdx = 4;
-const uint32_t kStoreObjectInIdx = 1;
+constexpr uint32_t kExtractCompositeIdInIdx = 0;
+constexpr uint32_t kInsertObjectIdInIdx = 0;
+constexpr uint32_t kInsertCompositeIdInIdx = 1;
+constexpr uint32_t kExtInstSetIdInIdx = 0;
+constexpr uint32_t kExtInstInstructionInIdx = 1;
+constexpr uint32_t kFMixXIdInIdx = 2;
+constexpr uint32_t kFMixYIdInIdx = 3;
+constexpr uint32_t kFMixAIdInIdx = 4;
+constexpr uint32_t kStoreObjectInIdx = 1;
 
 // Some image instructions may contain an "image operands" argument.
 // Returns the operand index for the "image operands".
@@ -43,33 +43,33 @@
 int32_t ImageOperandsMaskInOperandIndex(Instruction* inst) {
   const auto opcode = inst->opcode();
   switch (opcode) {
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageRead:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseRead:
       return inst->NumOperands() > 4 ? 2 : -1;
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
       return inst->NumOperands() > 5 ? 3 : -1;
-    case SpvOpImageWrite:
+    case spv::Op::OpImageWrite:
       return inst->NumOperands() > 3 ? 3 : -1;
     default:
       return -1;
@@ -136,25 +136,28 @@
     const analysis::IntConstant* c) {
   assert(c != nullptr);
   uint32_t width = c->type()->AsInteger()->width();
-  assert(width == 32 || width == 64);
+  assert(width == 8 || width == 16 || width == 32 || width == 64);
   if (width == 64) {
     uint64_t uval = static_cast<uint64_t>(c->GetU64());
     return ExtractInts(uval);
   }
-  return {c->GetU32()};
+  // Section 2.2.1 of the SPIR-V spec guarantees that all integer types
+  // smaller than 32-bits are automatically zero or sign extended to 32-bits.
+  return {c->GetU32BitValue()};
 }
 
 std::vector<uint32_t> GetWordsFromScalarFloatConstant(
     const analysis::FloatConstant* c) {
   assert(c != nullptr);
   uint32_t width = c->type()->AsFloat()->width();
-  assert(width == 32 || width == 64);
+  assert(width == 16 || width == 32 || width == 64);
   if (width == 64) {
     utils::FloatProxy<double> result(c->GetDouble());
     return result.GetWords();
   }
-  utils::FloatProxy<float> result(c->GetFloat());
-  return result.GetWords();
+  // Section 2.2.1 of the SPIR-V spec guarantees that all floating-point types
+  // smaller than 32-bits are automatically zero extended to 32-bits.
+  return {c->GetU32BitValue()};
 }
 
 std::vector<uint32_t> GetWordsFromNumericScalarOrVectorConstant(
@@ -301,7 +304,7 @@
 FoldingRule ReciprocalFDiv() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv);
+    assert(inst->opcode() == spv::Op::OpFDiv);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -330,7 +333,7 @@
         // Don't fold a null constant.
         return false;
       }
-      inst->SetOpcode(SpvOpFMul);
+      inst->SetOpcode(spv::Op::OpFMul);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0u)}},
            {SPV_OPERAND_TYPE_ID, {id}}});
@@ -345,7 +348,8 @@
 FoldingRule MergeNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFNegate || inst->opcode() == SpvOpSNegate);
+    assert(inst->opcode() == spv::Op::OpFNegate ||
+           inst->opcode() == spv::Op::OpSNegate);
     (void)constants;
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -359,7 +363,7 @@
 
     if (op_inst->opcode() == inst->opcode()) {
       // Elide negates.
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {op_inst->GetSingleWordInOperand(0u)}}});
       return true;
@@ -379,7 +383,8 @@
 FoldingRule MergeNegateMulDivArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFNegate || inst->opcode() == SpvOpSNegate);
+    assert(inst->opcode() == spv::Op::OpFNegate ||
+           inst->opcode() == spv::Op::OpSNegate);
     (void)constants;
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
@@ -395,9 +400,10 @@
     uint32_t width = ElementWidth(type);
     if (width != 32 && width != 64) return false;
 
-    SpvOp opcode = op_inst->opcode();
-    if (opcode == SpvOpFMul || opcode == SpvOpFDiv || opcode == SpvOpIMul ||
-        opcode == SpvOpSDiv || opcode == SpvOpUDiv) {
+    spv::Op opcode = op_inst->opcode();
+    if (opcode == spv::Op::OpFMul || opcode == spv::Op::OpFDiv ||
+        opcode == spv::Op::OpIMul || opcode == spv::Op::OpSDiv ||
+        opcode == spv::Op::OpUDiv) {
       std::vector<const analysis::Constant*> op_constants =
           const_mgr->GetOperandConstants(op_inst);
       // Merge negate into mul or div if one operand is constant.
@@ -410,7 +416,8 @@
                                     : op_inst->GetSingleWordInOperand(1u);
         // Change this instruction to a mul/div.
         inst->SetOpcode(op_inst->opcode());
-        if (opcode == SpvOpFDiv || opcode == SpvOpUDiv || opcode == SpvOpSDiv) {
+        if (opcode == spv::Op::OpFDiv || opcode == spv::Op::OpUDiv ||
+            opcode == spv::Op::OpSDiv) {
           uint32_t op0 = zero_is_variable ? non_const_id : neg_id;
           uint32_t op1 = zero_is_variable ? neg_id : non_const_id;
           inst->SetInOperands(
@@ -437,7 +444,8 @@
 FoldingRule MergeNegateAddSubArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFNegate || inst->opcode() == SpvOpSNegate);
+    assert(inst->opcode() == spv::Op::OpFNegate ||
+           inst->opcode() == spv::Op::OpSNegate);
     (void)constants;
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
@@ -453,14 +461,16 @@
     uint32_t width = ElementWidth(type);
     if (width != 32 && width != 64) return false;
 
-    if (op_inst->opcode() == SpvOpFAdd || op_inst->opcode() == SpvOpFSub ||
-        op_inst->opcode() == SpvOpIAdd || op_inst->opcode() == SpvOpISub) {
+    if (op_inst->opcode() == spv::Op::OpFAdd ||
+        op_inst->opcode() == spv::Op::OpFSub ||
+        op_inst->opcode() == spv::Op::OpIAdd ||
+        op_inst->opcode() == spv::Op::OpISub) {
       std::vector<const analysis::Constant*> op_constants =
           const_mgr->GetOperandConstants(op_inst);
       if (op_constants[0] || op_constants[1]) {
         bool zero_is_variable = op_constants[0] == nullptr;
-        bool is_add = (op_inst->opcode() == SpvOpFAdd) ||
-                      (op_inst->opcode() == SpvOpIAdd);
+        bool is_add = (op_inst->opcode() == spv::Op::OpFAdd) ||
+                      (op_inst->opcode() == spv::Op::OpIAdd);
         bool swap_operands = !is_add || zero_is_variable;
         bool negate_const = is_add;
         const analysis::Constant* c = ConstInput(op_constants);
@@ -478,7 +488,8 @@
         uint32_t op1 =
             zero_is_variable ? const_id : op_inst->GetSingleWordInOperand(1u);
         if (swap_operands) std::swap(op0, op1);
-        inst->SetOpcode(HasFloatingPoint(type) ? SpvOpFSub : SpvOpISub);
+        inst->SetOpcode(HasFloatingPoint(type) ? spv::Op::OpFSub
+                                               : spv::Op::OpISub);
         inst->SetInOperands(
             {{SPV_OPERAND_TYPE_ID, {op0}}, {SPV_OPERAND_TYPE_ID, {op1}}});
         return true;
@@ -509,7 +520,7 @@
 // id. Returns 0 if the result is not a valid value. The input types must be
 // Float.
 uint32_t PerformFloatingPointOperation(analysis::ConstantManager* const_mgr,
-                                       SpvOp opcode,
+                                       spv::Op opcode,
                                        const analysis::Constant* input1,
                                        const analysis::Constant* input2) {
   const analysis::Type* type = input1->type();
@@ -532,17 +543,17 @@
   }                                                                          \
   static_assert(true, "require extra semicolon")
   switch (opcode) {
-    case SpvOpFMul:
+    case spv::Op::OpFMul:
       FOLD_OP(*);
       break;
-    case SpvOpFDiv:
+    case spv::Op::OpFDiv:
       if (HasZero(input2)) return 0;
       FOLD_OP(/);
       break;
-    case SpvOpFAdd:
+    case spv::Op::OpFAdd:
       FOLD_OP(+);
       break;
-    case SpvOpFSub:
+    case spv::Op::OpFSub:
       FOLD_OP(-);
       break;
     default:
@@ -558,7 +569,8 @@
 // id. Returns 0 if the result is not a valid value. The input types must be
 // Integers.
 uint32_t PerformIntegerOperation(analysis::ConstantManager* const_mgr,
-                                 SpvOp opcode, const analysis::Constant* input1,
+                                 spv::Op opcode,
+                                 const analysis::Constant* input1,
                                  const analysis::Constant* input2) {
   assert(input1->type()->AsInteger());
   const analysis::Integer* type = input1->type()->AsInteger();
@@ -579,17 +591,17 @@
   }                                                      \
   static_assert(true, "require extra semicolon")
   switch (opcode) {
-    case SpvOpIMul:
+    case spv::Op::OpIMul:
       FOLD_OP(*);
       break;
-    case SpvOpSDiv:
-    case SpvOpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpUDiv:
       assert(false && "Should not merge integer division");
       break;
-    case SpvOpIAdd:
+    case spv::Op::OpIAdd:
       FOLD_OP(+);
       break;
-    case SpvOpISub:
+    case spv::Op::OpISub:
       FOLD_OP(-);
       break;
     default:
@@ -604,7 +616,7 @@
 // Performs |input1| |opcode| |input2| and returns the merged constant result
 // id. Returns 0 if the result is not a valid value. The input types must be
 // Integers, Floats or Vectors of such.
-uint32_t PerformOperation(analysis::ConstantManager* const_mgr, SpvOp opcode,
+uint32_t PerformOperation(analysis::ConstantManager* const_mgr, spv::Op opcode,
                           const analysis::Constant* input1,
                           const analysis::Constant* input2) {
   assert(input1 && input2);
@@ -664,7 +676,8 @@
 FoldingRule MergeMulMulArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFMul || inst->opcode() == SpvOpIMul);
+    assert(inst->opcode() == spv::Op::OpFMul ||
+           inst->opcode() == spv::Op::OpIMul);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -716,7 +729,7 @@
 FoldingRule MergeMulDivArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFMul);
+    assert(inst->opcode() == spv::Op::OpFMul);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
 
@@ -730,10 +743,10 @@
     for (uint32_t i = 0; i < 2; i++) {
       uint32_t op_id = inst->GetSingleWordInOperand(i);
       Instruction* op_inst = def_use_mgr->GetDef(op_id);
-      if (op_inst->opcode() == SpvOpFDiv) {
+      if (op_inst->opcode() == spv::Op::OpFDiv) {
         if (op_inst->GetSingleWordInOperand(1) ==
             inst->GetSingleWordInOperand(1 - i)) {
-          inst->SetOpcode(SpvOpCopyObject);
+          inst->SetOpcode(spv::Op::OpCopyObject);
           inst->SetInOperands(
               {{SPV_OPERAND_TYPE_ID, {op_inst->GetSingleWordInOperand(0)}}});
           return true;
@@ -746,7 +759,7 @@
     Instruction* other_inst = NonConstInput(context, constants[0], inst);
     if (!other_inst->IsFloatingPointFoldingAllowed()) return false;
 
-    if (other_inst->opcode() == SpvOpFDiv) {
+    if (other_inst->opcode() == spv::Op::OpFDiv) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -790,7 +803,8 @@
 FoldingRule MergeMulNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFMul || inst->opcode() == SpvOpIMul);
+    assert(inst->opcode() == spv::Op::OpFMul ||
+           inst->opcode() == spv::Op::OpIMul);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -806,8 +820,8 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFNegate ||
-        other_inst->opcode() == SpvOpSNegate) {
+    if (other_inst->opcode() == spv::Op::OpFNegate ||
+        other_inst->opcode() == spv::Op::OpSNegate) {
       uint32_t neg_id = NegateConstant(const_mgr, const_input1);
 
       inst->SetInOperands(
@@ -830,7 +844,7 @@
 FoldingRule MergeDivDivArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv);
+    assert(inst->opcode() == spv::Op::OpFDiv);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -853,10 +867,10 @@
 
       bool other_first_is_variable = other_constants[0] == nullptr;
 
-      SpvOp merge_op = inst->opcode();
+      spv::Op merge_op = inst->opcode();
       if (other_first_is_variable) {
         // Constants magnify.
-        merge_op = SpvOpFMul;
+        merge_op = spv::Op::OpFMul;
       }
 
       // This is an x / (*) case. Swap the inputs. Doesn't harm multiply
@@ -870,10 +884,10 @@
                                   ? other_inst->GetSingleWordInOperand(0u)
                                   : other_inst->GetSingleWordInOperand(1u);
 
-      SpvOp op = inst->opcode();
+      spv::Op op = inst->opcode();
       if (!first_is_variable && !other_first_is_variable) {
         // Effectively div of 1/x, so change to multiply.
-        op = SpvOpFMul;
+        op = spv::Op::OpFMul;
       }
 
       uint32_t op1 = merged_id;
@@ -901,7 +915,7 @@
 FoldingRule MergeDivMulArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv);
+    assert(inst->opcode() == spv::Op::OpFDiv);
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
 
@@ -915,11 +929,11 @@
     uint32_t op_id = inst->GetSingleWordInOperand(0);
     Instruction* op_inst = def_use_mgr->GetDef(op_id);
 
-    if (op_inst->opcode() == SpvOpFMul) {
+    if (op_inst->opcode() == spv::Op::OpFMul) {
       for (uint32_t i = 0; i < 2; i++) {
         if (op_inst->GetSingleWordInOperand(i) ==
             inst->GetSingleWordInOperand(1)) {
-          inst->SetOpcode(SpvOpCopyObject);
+          inst->SetOpcode(spv::Op::OpCopyObject);
           inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                                 {op_inst->GetSingleWordInOperand(1 - i)}}});
           return true;
@@ -933,7 +947,7 @@
     if (!other_inst->IsFloatingPointFoldingAllowed()) return false;
 
     bool first_is_variable = constants[0] == nullptr;
-    if (other_inst->opcode() == SpvOpFMul) {
+    if (other_inst->opcode() == spv::Op::OpFMul) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -973,7 +987,7 @@
 FoldingRule MergeDivNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv);
+    assert(inst->opcode() == spv::Op::OpFDiv);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     if (!inst->IsFloatingPointFoldingAllowed()) return false;
 
@@ -983,7 +997,7 @@
     if (!other_inst->IsFloatingPointFoldingAllowed()) return false;
 
     bool first_is_variable = constants[0] == nullptr;
-    if (other_inst->opcode() == SpvOpFNegate) {
+    if (other_inst->opcode() == spv::Op::OpFNegate) {
       uint32_t neg_id = NegateConstant(const_mgr, const_input1);
 
       if (first_is_variable) {
@@ -1009,7 +1023,8 @@
 FoldingRule MergeAddNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     bool uses_float = HasFloatingPoint(type);
@@ -1021,9 +1036,10 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpSNegate ||
-        other_inst->opcode() == SpvOpFNegate) {
-      inst->SetOpcode(HasFloatingPoint(type) ? SpvOpFSub : SpvOpISub);
+    if (other_inst->opcode() == spv::Op::OpSNegate ||
+        other_inst->opcode() == spv::Op::OpFNegate) {
+      inst->SetOpcode(HasFloatingPoint(type) ? spv::Op::OpFSub
+                                             : spv::Op::OpISub);
       uint32_t const_id = constants[0] ? inst->GetSingleWordInOperand(0u)
                                        : inst->GetSingleWordInOperand(1u);
       inst->SetInOperands(
@@ -1042,7 +1058,8 @@
 FoldingRule MergeSubNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFSub || inst->opcode() == SpvOpISub);
+    assert(inst->opcode() == spv::Op::OpFSub ||
+           inst->opcode() == spv::Op::OpISub);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -1058,15 +1075,15 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpSNegate ||
-        other_inst->opcode() == SpvOpFNegate) {
+    if (other_inst->opcode() == spv::Op::OpSNegate ||
+        other_inst->opcode() == spv::Op::OpFNegate) {
       uint32_t op1 = 0;
       uint32_t op2 = 0;
-      SpvOp opcode = inst->opcode();
+      spv::Op opcode = inst->opcode();
       if (constants[0] != nullptr) {
         op1 = other_inst->GetSingleWordInOperand(0u);
         op2 = inst->GetSingleWordInOperand(0u);
-        opcode = HasFloatingPoint(type) ? SpvOpFAdd : SpvOpIAdd;
+        opcode = HasFloatingPoint(type) ? spv::Op::OpFAdd : spv::Op::OpIAdd;
       } else {
         op1 = NegateConstant(const_mgr, const_input1);
         op2 = other_inst->GetSingleWordInOperand(0u);
@@ -1090,7 +1107,8 @@
 FoldingRule MergeAddAddArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1106,8 +1124,8 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFAdd ||
-        other_inst->opcode() == SpvOpIAdd) {
+    if (other_inst->opcode() == spv::Op::OpFAdd ||
+        other_inst->opcode() == spv::Op::OpIAdd) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -1137,7 +1155,8 @@
 FoldingRule MergeAddSubArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1153,15 +1172,15 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFSub ||
-        other_inst->opcode() == SpvOpISub) {
+    if (other_inst->opcode() == spv::Op::OpFSub ||
+        other_inst->opcode() == spv::Op::OpISub) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
       if (!const_input2) return false;
 
       bool first_is_variable = other_constants[0] == nullptr;
-      SpvOp op = inst->opcode();
+      spv::Op op = inst->opcode();
       uint32_t op1 = 0;
       uint32_t op2 = 0;
       if (first_is_variable) {
@@ -1196,7 +1215,8 @@
 FoldingRule MergeSubAddArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFSub || inst->opcode() == SpvOpISub);
+    assert(inst->opcode() == spv::Op::OpFSub ||
+           inst->opcode() == spv::Op::OpISub);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1212,8 +1232,8 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFAdd ||
-        other_inst->opcode() == SpvOpIAdd) {
+    if (other_inst->opcode() == spv::Op::OpFAdd ||
+        other_inst->opcode() == spv::Op::OpIAdd) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -1228,7 +1248,7 @@
       // Subtract the constants.
       uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(),
                                             const_input1, const_input2);
-      SpvOp op = inst->opcode();
+      spv::Op op = inst->opcode();
       uint32_t op1 = 0;
       uint32_t op2 = 0;
       if (constants[0] == nullptr) {
@@ -1261,7 +1281,8 @@
 FoldingRule MergeSubSubArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFSub || inst->opcode() == SpvOpISub);
+    assert(inst->opcode() == spv::Op::OpFSub ||
+           inst->opcode() == spv::Op::OpISub);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1277,8 +1298,8 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFSub ||
-        other_inst->opcode() == SpvOpISub) {
+    if (other_inst->opcode() == spv::Op::OpFSub ||
+        other_inst->opcode() == spv::Op::OpISub) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -1289,9 +1310,9 @@
 
       // Merge the constants.
       uint32_t merged_id = 0;
-      SpvOp merge_op = inst->opcode();
+      spv::Op merge_op = inst->opcode();
       if (other_constants[0] == nullptr) {
-        merge_op = uses_float ? SpvOpFAdd : SpvOpIAdd;
+        merge_op = uses_float ? spv::Op::OpFAdd : spv::Op::OpIAdd;
       } else if (constants[0] == nullptr) {
         std::swap(const_input1, const_input2);
       }
@@ -1299,10 +1320,10 @@
           PerformOperation(const_mgr, merge_op, const_input1, const_input2);
       if (merged_id == 0) return false;
 
-      SpvOp op = inst->opcode();
+      spv::Op op = inst->opcode();
       if (constants[0] != nullptr && other_constants[0] != nullptr) {
         // Change the operation.
-        op = uses_float ? SpvOpFAdd : SpvOpIAdd;
+        op = uses_float ? spv::Op::OpFAdd : spv::Op::OpIAdd;
       }
 
       uint32_t op1 = 0;
@@ -1330,13 +1351,14 @@
   IRContext* context = inst->context();
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   Instruction* sub_inst = def_use_mgr->GetDef(sub);
-  if (sub_inst->opcode() != SpvOpFSub && sub_inst->opcode() != SpvOpISub)
+  if (sub_inst->opcode() != spv::Op::OpFSub &&
+      sub_inst->opcode() != spv::Op::OpISub)
     return false;
-  if (sub_inst->opcode() == SpvOpFSub &&
+  if (sub_inst->opcode() == spv::Op::OpFSub &&
       !sub_inst->IsFloatingPointFoldingAllowed())
     return false;
   if (addend != sub_inst->GetSingleWordInOperand(1)) return false;
-  inst->SetOpcode(SpvOpCopyObject);
+  inst->SetOpcode(spv::Op::OpCopyObject);
   inst->SetInOperands(
       {{SPV_OPERAND_TYPE_ID, {sub_inst->GetSingleWordInOperand(0)}}});
   context->UpdateDefUse(inst);
@@ -1352,7 +1374,8 @@
 FoldingRule MergeGenericAddSubArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     bool uses_float = HasFloatingPoint(type);
@@ -1380,7 +1403,8 @@
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
   Instruction* new_add_inst = ir_builder.AddBinaryOp(
       inst->type_id(), inst->opcode(), factor0_1, factor1_1);
-  inst->SetOpcode(inst->opcode() == SpvOpFAdd ? SpvOpFMul : SpvOpIMul);
+  inst->SetOpcode(inst->opcode() == spv::Op::OpFAdd ? spv::Op::OpFMul
+                                                    : spv::Op::OpIMul);
   inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {factor0_0}},
                        {SPV_OPERAND_TYPE_ID, {new_add_inst->result_id()}}});
   context->UpdateDefUse(inst);
@@ -1392,7 +1416,8 @@
 FoldingRule FactorAddMuls() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     bool uses_float = HasFloatingPoint(type);
@@ -1401,13 +1426,13 @@
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     uint32_t add_op0 = inst->GetSingleWordInOperand(0);
     Instruction* add_op0_inst = def_use_mgr->GetDef(add_op0);
-    if (add_op0_inst->opcode() != SpvOpFMul &&
-        add_op0_inst->opcode() != SpvOpIMul)
+    if (add_op0_inst->opcode() != spv::Op::OpFMul &&
+        add_op0_inst->opcode() != spv::Op::OpIMul)
       return false;
     uint32_t add_op1 = inst->GetSingleWordInOperand(1);
     Instruction* add_op1_inst = def_use_mgr->GetDef(add_op1);
-    if (add_op1_inst->opcode() != SpvOpFMul &&
-        add_op1_inst->opcode() != SpvOpIMul)
+    if (add_op1_inst->opcode() != spv::Op::OpFMul &&
+        add_op1_inst->opcode() != spv::Op::OpIMul)
       return false;
 
     // Only perform this optimization if both of the muls only have one use.
@@ -1415,7 +1440,7 @@
     if (def_use_mgr->NumUses(add_op0_inst) > 1) return false;
     if (def_use_mgr->NumUses(add_op1_inst) > 1) return false;
 
-    if (add_op0_inst->opcode() == SpvOpFMul &&
+    if (add_op0_inst->opcode() == spv::Op::OpFMul &&
         (!add_op0_inst->IsFloatingPointFoldingAllowed() ||
          !add_op1_inst->IsFloatingPointFoldingAllowed()))
       return false;
@@ -1454,7 +1479,7 @@
   operands.push_back({SPV_OPERAND_TYPE_ID, {y}});
   operands.push_back({SPV_OPERAND_TYPE_ID, {a}});
 
-  inst->SetOpcode(SpvOpExtInst);
+  inst->SetOpcode(spv::Op::OpExtInst);
   inst->SetInOperands(std::move(operands));
 }
 
@@ -1465,7 +1490,7 @@
 // a + (x * y) = Fma x y a
 bool MergeMulAddArithmetic(IRContext* context, Instruction* inst,
                            const std::vector<const analysis::Constant*>&) {
-  assert(inst->opcode() == SpvOpFAdd);
+  assert(inst->opcode() == spv::Op::OpFAdd);
 
   if (!inst->IsFloatingPointFoldingAllowed()) {
     return false;
@@ -1476,7 +1501,7 @@
     uint32_t op_id = inst->GetSingleWordInOperand(i);
     Instruction* op_inst = def_use_mgr->GetDef(op_id);
 
-    if (op_inst->opcode() != SpvOpFMul) {
+    if (op_inst->opcode() != spv::Op::OpFMul) {
       continue;
     }
 
@@ -1511,7 +1536,7 @@
       sub->context(), sub,
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
 
-  Instruction* neg = ir_builder.AddUnaryOp(sub->type_id(), SpvOpFNegate,
+  Instruction* neg = ir_builder.AddUnaryOp(sub->type_id(), spv::Op::OpFNegate,
                                            negate_addition ? a : x);
   uint32_t neg_op = neg->result_id();  // -a : -x
 
@@ -1522,7 +1547,7 @@
   operands.push_back({SPV_OPERAND_TYPE_ID, {y}});
   operands.push_back({SPV_OPERAND_TYPE_ID, {negate_addition ? neg_op : a}});
 
-  sub->SetOpcode(SpvOpExtInst);
+  sub->SetOpcode(spv::Op::OpExtInst);
   sub->SetInOperands(std::move(operands));
 }
 
@@ -1533,7 +1558,7 @@
 // a - (x * y) = Fma -x y a
 bool MergeMulSubArithmetic(IRContext* context, Instruction* sub,
                            const std::vector<const analysis::Constant*>&) {
-  assert(sub->opcode() == SpvOpFSub);
+  assert(sub->opcode() == spv::Op::OpFSub);
 
   if (!sub->IsFloatingPointFoldingAllowed()) {
     return false;
@@ -1544,7 +1569,7 @@
     uint32_t op_id = sub->GetSingleWordInOperand(i);
     Instruction* mul = def_use_mgr->GetDef(op_id);
 
-    if (mul->opcode() != SpvOpFMul) {
+    if (mul->opcode() != spv::Op::OpFMul) {
       continue;
     }
 
@@ -1564,7 +1589,8 @@
 FoldingRule IntMultipleBy1() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpIMul && "Wrong opcode.  Should be OpIMul.");
+    assert(inst->opcode() == spv::Op::OpIMul &&
+           "Wrong opcode.  Should be OpIMul.");
     for (uint32_t i = 0; i < 2; i++) {
       if (constants[i] == nullptr) {
         continue;
@@ -1576,7 +1602,7 @@
         bool is_one = (width == 32) ? int_constant->GetU32BitValue() == 1u
                                     : int_constant->GetU64BitValue() == 1ull;
         if (is_one) {
-          inst->SetOpcode(SpvOpCopyObject);
+          inst->SetOpcode(spv::Op::OpCopyObject);
           inst->SetInOperands(
               {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(1 - i)}}});
           return true;
@@ -1593,7 +1619,7 @@
 uint32_t GetNumOfElementsContributedByOperand(IRContext* context,
                                               const Instruction* inst,
                                               uint32_t index) {
-  assert(inst->opcode() == SpvOpCompositeConstruct);
+  assert(inst->opcode() == spv::Op::OpCompositeConstruct);
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -1624,7 +1650,7 @@
 // out-of-bounds. |inst| must be an |OpCompositeConstruct| instruction.
 std::vector<Operand> GetExtractOperandsForElementOfCompositeConstruct(
     IRContext* context, const Instruction* inst, uint32_t result_index) {
-  assert(inst->opcode() == SpvOpCompositeConstruct);
+  assert(inst->opcode() == spv::Op::OpCompositeConstruct);
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -1663,7 +1689,7 @@
     const std::vector<const analysis::Constant*>&) {
   // If the input to an OpCompositeExtract is an OpCompositeConstruct,
   // then we can simply use the appropriate element in the construction.
-  assert(inst->opcode() == SpvOpCompositeExtract &&
+  assert(inst->opcode() == spv::Op::OpCompositeExtract &&
          "Wrong opcode.  Should be OpCompositeExtract.");
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
 
@@ -1675,7 +1701,7 @@
   uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
   Instruction* cinst = def_use_mgr->GetDef(cid);
 
-  if (cinst->opcode() != SpvOpCompositeConstruct) {
+  if (cinst->opcode() != spv::Op::OpCompositeConstruct) {
     return false;
   }
 
@@ -1697,7 +1723,7 @@
   if (operands.size() == 1) {
     // If there were no extra indices, then we have the final object.  No need
     // to extract any more.
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
   }
 
   inst->SetInOperands(std::move(operands));
@@ -1735,8 +1761,8 @@
 bool HaveSameIndexesExceptForLast(Instruction* inst_1, Instruction* inst_2) {
   assert(inst_1->opcode() == inst_2->opcode() &&
          "Expecting the opcodes to be the same.");
-  assert((inst_1->opcode() == SpvOpCompositeInsert ||
-          inst_1->opcode() == SpvOpCompositeExtract) &&
+  assert((inst_1->opcode() == spv::Op::OpCompositeInsert ||
+          inst_1->opcode() == spv::Op::OpCompositeExtract) &&
          "Instructions must be OpCompositeInsert or OpCompositeExtract.");
 
   if (inst_1->NumInOperands() != inst_2->NumInOperands()) {
@@ -1744,7 +1770,7 @@
   }
 
   uint32_t first_index_position =
-      (inst_1->opcode() == SpvOpCompositeInsert ? 2 : 1);
+      (inst_1->opcode() == spv::Op::OpCompositeInsert ? 2 : 1);
   for (uint32_t i = first_index_position; i < inst_1->NumInOperands() - 1;
        i++) {
     if (inst_1->GetSingleWordInOperand(i) !=
@@ -1763,7 +1789,7 @@
 bool CompositeExtractFeedingConstruct(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>&) {
-  assert(inst->opcode() == SpvOpCompositeConstruct &&
+  assert(inst->opcode() == spv::Op::OpCompositeConstruct &&
          "Wrong opcode.  Should be OpCompositeConstruct.");
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   uint32_t original_id = 0;
@@ -1785,7 +1811,7 @@
       first_element_inst = element_inst;
     }
 
-    if (element_inst->opcode() != SpvOpCompositeExtract) {
+    if (element_inst->opcode() != spv::Op::OpCompositeExtract) {
       return false;
     }
 
@@ -1825,14 +1851,14 @@
 
   if (first_element_inst->NumInOperands() == 2) {
     // Simplify by using the original object.
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {original_id}}});
     return true;
   }
 
   // Copies the original id and all indexes except for the last to the new
   // extract instruction.
-  inst->SetOpcode(SpvOpCompositeExtract);
+  inst->SetOpcode(spv::Op::OpCompositeExtract);
   inst->SetInOperands(std::vector<Operand>(first_element_inst->begin() + 2,
                                            first_element_inst->end() - 1));
   return true;
@@ -1841,13 +1867,13 @@
 FoldingRule InsertFeedingExtract() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpCompositeExtract &&
+    assert(inst->opcode() == spv::Op::OpCompositeExtract &&
            "Wrong opcode.  Should be OpCompositeExtract.");
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
     Instruction* cinst = def_use_mgr->GetDef(cid);
 
-    if (cinst->opcode() != SpvOpCompositeInsert) {
+    if (cinst->opcode() != spv::Op::OpCompositeInsert) {
       return false;
     }
 
@@ -1867,7 +1893,7 @@
 
     // We are extracting the element that was inserted.
     if (i == inst->NumInOperands() && i + 1 == cinst->NumInOperands()) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID,
             {cinst->GetSingleWordInOperand(kInsertObjectIdInIdx)}}});
@@ -1916,14 +1942,14 @@
 FoldingRule VectorShuffleFeedingExtract() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpCompositeExtract &&
+    assert(inst->opcode() == spv::Op::OpCompositeExtract &&
            "Wrong opcode.  Should be OpCompositeExtract.");
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     analysis::TypeManager* type_mgr = context->get_type_mgr();
     uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
     Instruction* cinst = def_use_mgr->GetDef(cid);
 
-    if (cinst->opcode() != SpvOpVectorShuffle) {
+    if (cinst->opcode() != spv::Op::OpVectorShuffle) {
       return false;
     }
 
@@ -1944,7 +1970,7 @@
     // Extracting an undefined value so fold this extract into an undef.
     const uint32_t undef_literal_value = 0xffffffff;
     if (new_index == undef_literal_value) {
-      inst->SetOpcode(SpvOpUndef);
+      inst->SetOpcode(spv::Op::OpUndef);
       inst->SetInOperands({});
       return true;
     }
@@ -1972,7 +1998,7 @@
 FoldingRule FMixFeedingExtract() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpCompositeExtract &&
+    assert(inst->opcode() == spv::Op::OpCompositeExtract &&
            "Wrong opcode.  Should be OpCompositeExtract.");
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1981,7 +2007,7 @@
         inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
     Instruction* composite_inst = def_use_mgr->GetDef(composite_id);
 
-    if (composite_inst->opcode() != SpvOpExtInst) {
+    if (composite_inst->opcode() != spv::Op::OpExtInst) {
       return false;
     }
 
@@ -2001,7 +2027,7 @@
     a->SetInOperand(kExtractCompositeIdInIdx, {a_id});
     context->get_instruction_folder().FoldInstruction(a.get());
 
-    if (a->opcode() != SpvOpCopyObject) {
+    if (a->opcode() != spv::Op::OpCopyObject) {
       return false;
     }
 
@@ -2063,7 +2089,7 @@
   analysis::DefUseManager* def_use_mgr = inst->context()->get_def_use_mgr();
   std::map<uint32_t, uint32_t> values_inserted;
   Instruction* current_inst = inst;
-  while (current_inst->opcode() == SpvOpCompositeInsert) {
+  while (current_inst->opcode() == spv::Op::OpCompositeInsert) {
     if (current_inst->NumInOperands() > inst->NumInOperands()) {
       // This is the catch the case
       //   %2 = OpCompositeInsert %m2x2int %v2int_1_0 %m2x2int_undef 0
@@ -2105,7 +2131,7 @@
 // Returns the type of the element that immediately contains the element being
 // inserted by the OpCompositeInsert instruction |inst|.
 const analysis::Type* GetContainerType(Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeInsert);
+  assert(inst->opcode() == spv::Op::OpCompositeInsert);
   analysis::TypeManager* type_mgr = inst->context()->get_type_mgr();
   return GetElementType(inst->type_id(), inst->begin() + 4, inst->end() - 1,
                         type_mgr);
@@ -2137,7 +2163,7 @@
 // instruction is replaced with an OpCopyObject instead.
 void InsertConstructedObject(Instruction* inst, const Instruction* construct) {
   if (inst->NumInOperands() == 3) {
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {construct->result_id()}}});
   } else {
     inst->SetInOperand(kInsertObjectIdInIdx, {construct->result_id()});
@@ -2150,7 +2176,7 @@
 bool CompositeInsertToCompositeConstruct(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>&) {
-  assert(inst->opcode() == SpvOpCompositeInsert &&
+  assert(inst->opcode() == spv::Op::OpCompositeInsert &&
          "Wrong opcode.  Should be OpCompositeInsert.");
   if (inst->NumInOperands() < 3) return false;
 
@@ -2176,7 +2202,8 @@
   // itself, can be replaced by the value itself.
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpPhi && "Wrong opcode.  Should be OpPhi.");
+    assert(inst->opcode() == spv::Op::OpPhi &&
+           "Wrong opcode.  Should be OpPhi.");
 
     uint32_t incoming_value = 0;
 
@@ -2200,7 +2227,7 @@
     }
 
     // We have a single incoming value.  Simplify using that value.
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {incoming_value}}});
     return true;
   };
@@ -2209,7 +2236,7 @@
 FoldingRule BitCastScalarOrVector() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpBitcast && constants.size() == 1);
+    assert(inst->opcode() == spv::Op::OpBitcast && constants.size() == 1);
     if (constants[0] == nullptr) return false;
 
     const analysis::Type* type =
@@ -2229,7 +2256,7 @@
     auto new_feeder_id =
         const_mgr->GetDefiningInstruction(bitcasted_constant, inst->type_id())
             ->result_id();
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {new_feeder_id}}});
     return true;
   };
@@ -2240,7 +2267,7 @@
   // constant can be replaced by one of the values
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpSelect &&
+    assert(inst->opcode() == spv::Op::OpSelect &&
            "Wrong opcode.  Should be OpSelect.");
     assert(inst->NumInOperands() == 3);
     assert(constants.size() == 3);
@@ -2250,14 +2277,14 @@
 
     if (true_id == false_id) {
       // Both results are the same, condition doesn't matter
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {true_id}}});
       return true;
     } else if (constants[0]) {
       const analysis::Type* type = constants[0]->type();
       if (type->AsBool()) {
         // Scalar constant value, select the corresponding value.
-        inst->SetOpcode(SpvOpCopyObject);
+        inst->SetOpcode(spv::Op::OpCopyObject);
         if (constants[0]->AsNullConstant() ||
             !constants[0]->AsBoolConstant()->value()) {
           inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {false_id}}});
@@ -2269,7 +2296,7 @@
         assert(type->AsVector());
         if (constants[0]->AsNullConstant()) {
           // All values come from false id.
-          inst->SetOpcode(SpvOpCopyObject);
+          inst->SetOpcode(spv::Op::OpCopyObject);
           inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {false_id}}});
           return true;
         } else {
@@ -2296,7 +2323,7 @@
             }
           }
 
-          inst->SetOpcode(SpvOpVectorShuffle);
+          inst->SetOpcode(spv::Op::OpVectorShuffle);
           inst->SetInOperands(std::move(ops));
           return true;
         }
@@ -2356,7 +2383,8 @@
 FoldingRule RedundantFAdd() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFAdd && "Wrong opcode.  Should be OpFAdd.");
+    assert(inst->opcode() == spv::Op::OpFAdd &&
+           "Wrong opcode.  Should be OpFAdd.");
     assert(constants.size() == 2);
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2367,7 +2395,7 @@
     FloatConstantKind kind1 = getFloatConstantKind(constants[1]);
 
     if (kind0 == FloatConstantKind::Zero || kind1 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                             {inst->GetSingleWordInOperand(
                                 kind0 == FloatConstantKind::Zero ? 1 : 0)}}});
@@ -2381,7 +2409,8 @@
 FoldingRule RedundantFSub() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFSub && "Wrong opcode.  Should be OpFSub.");
+    assert(inst->opcode() == spv::Op::OpFSub &&
+           "Wrong opcode.  Should be OpFSub.");
     assert(constants.size() == 2);
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2392,14 +2421,14 @@
     FloatConstantKind kind1 = getFloatConstantKind(constants[1]);
 
     if (kind0 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpFNegate);
+      inst->SetOpcode(spv::Op::OpFNegate);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(1)}}});
       return true;
     }
 
     if (kind1 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
       return true;
@@ -2412,7 +2441,8 @@
 FoldingRule RedundantFMul() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFMul && "Wrong opcode.  Should be OpFMul.");
+    assert(inst->opcode() == spv::Op::OpFMul &&
+           "Wrong opcode.  Should be OpFMul.");
     assert(constants.size() == 2);
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2423,7 +2453,7 @@
     FloatConstantKind kind1 = getFloatConstantKind(constants[1]);
 
     if (kind0 == FloatConstantKind::Zero || kind1 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                             {inst->GetSingleWordInOperand(
                                 kind0 == FloatConstantKind::Zero ? 0 : 1)}}});
@@ -2431,7 +2461,7 @@
     }
 
     if (kind0 == FloatConstantKind::One || kind1 == FloatConstantKind::One) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                             {inst->GetSingleWordInOperand(
                                 kind0 == FloatConstantKind::One ? 1 : 0)}}});
@@ -2445,7 +2475,8 @@
 FoldingRule RedundantFDiv() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv && "Wrong opcode.  Should be OpFDiv.");
+    assert(inst->opcode() == spv::Op::OpFDiv &&
+           "Wrong opcode.  Should be OpFDiv.");
     assert(constants.size() == 2);
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2456,14 +2487,14 @@
     FloatConstantKind kind1 = getFloatConstantKind(constants[1]);
 
     if (kind0 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
       return true;
     }
 
     if (kind1 == FloatConstantKind::One) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
       return true;
@@ -2476,7 +2507,7 @@
 FoldingRule RedundantFMix() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpExtInst &&
+    assert(inst->opcode() == spv::Op::OpExtInst &&
            "Wrong opcode.  Should be OpExtInst.");
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2494,7 +2525,7 @@
       FloatConstantKind kind4 = getFloatConstantKind(constants[4]);
 
       if (kind4 == FloatConstantKind::Zero || kind4 == FloatConstantKind::One) {
-        inst->SetOpcode(SpvOpCopyObject);
+        inst->SetOpcode(spv::Op::OpCopyObject);
         inst->SetInOperands(
             {{SPV_OPERAND_TYPE_ID,
               {inst->GetSingleWordInOperand(kind4 == FloatConstantKind::Zero
@@ -2512,7 +2543,8 @@
 FoldingRule RedundantIAdd() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpIAdd && "Wrong opcode. Should be OpIAdd.");
+    assert(inst->opcode() == spv::Op::OpIAdd &&
+           "Wrong opcode. Should be OpIAdd.");
 
     uint32_t operand = std::numeric_limits<uint32_t>::max();
     const analysis::Type* operand_type = nullptr;
@@ -2528,9 +2560,9 @@
       const analysis::Type* inst_type =
           context->get_type_mgr()->GetType(inst->type_id());
       if (inst_type->IsSame(operand_type)) {
-        inst->SetOpcode(SpvOpCopyObject);
+        inst->SetOpcode(spv::Op::OpCopyObject);
       } else {
-        inst->SetOpcode(SpvOpBitcast);
+        inst->SetOpcode(spv::Op::OpBitcast);
       }
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {operand}}});
       return true;
@@ -2544,7 +2576,8 @@
 FoldingRule DotProductDoingExtract() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpDot && "Wrong opcode.  Should be OpDot.");
+    assert(inst->opcode() == spv::Op::OpDot &&
+           "Wrong opcode.  Should be OpDot.");
 
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
 
@@ -2570,7 +2603,7 @@
       std::vector<const analysis::Constant*> components;
       components = constants[i]->GetVectorComponents(const_mgr);
 
-      const uint32_t kNotFound = std::numeric_limits<uint32_t>::max();
+      constexpr uint32_t kNotFound = std::numeric_limits<uint32_t>::max();
 
       uint32_t component_with_one = kNotFound;
       bool all_others_zero = true;
@@ -2603,7 +2636,7 @@
       operands.push_back(
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {component_with_one}});
 
-      inst->SetOpcode(SpvOpCompositeExtract);
+      inst->SetOpcode(spv::Op::OpCompositeExtract);
       inst->SetInOperands(std::move(operands));
       return true;
     }
@@ -2618,20 +2651,22 @@
 FoldingRule StoringUndef() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpStore && "Wrong opcode.  Should be OpStore.");
+    assert(inst->opcode() == spv::Op::OpStore &&
+           "Wrong opcode.  Should be OpStore.");
 
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
 
     // If this is a volatile store, the store cannot be removed.
     if (inst->NumInOperands() == 3) {
-      if (inst->GetSingleWordInOperand(2) & SpvMemoryAccessVolatileMask) {
+      if (inst->GetSingleWordInOperand(2) &
+          uint32_t(spv::MemoryAccessMask::Volatile)) {
         return false;
       }
     }
 
     uint32_t object_id = inst->GetSingleWordInOperand(kStoreObjectInIdx);
     Instruction* object_inst = def_use_mgr->GetDef(object_id);
-    if (object_inst->opcode() == SpvOpUndef) {
+    if (object_inst->opcode() == spv::Op::OpUndef) {
       inst->ToNop();
       return true;
     }
@@ -2642,7 +2677,7 @@
 FoldingRule VectorShuffleFeedingShuffle() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpVectorShuffle &&
+    assert(inst->opcode() == spv::Op::OpVectorShuffle &&
            "Wrong opcode.  Should be OpVectorShuffle.");
 
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
@@ -2655,13 +2690,13 @@
     uint32_t op0_length = op0_type->element_count();
 
     bool feeder_is_op0 = true;
-    if (feeding_shuffle_inst->opcode() != SpvOpVectorShuffle) {
+    if (feeding_shuffle_inst->opcode() != spv::Op::OpVectorShuffle) {
       feeding_shuffle_inst =
           def_use_mgr->GetDef(inst->GetSingleWordInOperand(1));
       feeder_is_op0 = false;
     }
 
-    if (feeding_shuffle_inst->opcode() != SpvOpVectorShuffle) {
+    if (feeding_shuffle_inst->opcode() != spv::Op::OpVectorShuffle) {
       return false;
     }
 
@@ -2748,7 +2783,8 @@
 
       if (adjustment != 0) {
         for (uint32_t i = 2; i < new_operands.size(); i++) {
-          if (inst->GetSingleWordInOperand(i) >= op0_length) {
+          uint32_t operand = inst->GetSingleWordInOperand(i);
+          if (operand >= op0_length && operand != undef_literal) {
             new_operands[i].words[0] -= adjustment;
           }
         }
@@ -2771,7 +2807,7 @@
 FoldingRule RemoveRedundantOperands() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpEntryPoint &&
+    assert(inst->opcode() == spv::Op::OpEntryPoint &&
            "Wrong opcode.  Should be OpEntryPoint.");
     bool has_redundant_operand = false;
     std::unordered_set<uint32_t> seen_operands;
@@ -2804,46 +2840,52 @@
             const std::vector<const analysis::Constant*>& constants) {
     const auto opcode = inst->opcode();
     (void)opcode;
-    assert((opcode == SpvOpImageSampleImplicitLod ||
-            opcode == SpvOpImageSampleExplicitLod ||
-            opcode == SpvOpImageSampleDrefImplicitLod ||
-            opcode == SpvOpImageSampleDrefExplicitLod ||
-            opcode == SpvOpImageSampleProjImplicitLod ||
-            opcode == SpvOpImageSampleProjExplicitLod ||
-            opcode == SpvOpImageSampleProjDrefImplicitLod ||
-            opcode == SpvOpImageSampleProjDrefExplicitLod ||
-            opcode == SpvOpImageFetch || opcode == SpvOpImageGather ||
-            opcode == SpvOpImageDrefGather || opcode == SpvOpImageRead ||
-            opcode == SpvOpImageWrite ||
-            opcode == SpvOpImageSparseSampleImplicitLod ||
-            opcode == SpvOpImageSparseSampleExplicitLod ||
-            opcode == SpvOpImageSparseSampleDrefImplicitLod ||
-            opcode == SpvOpImageSparseSampleDrefExplicitLod ||
-            opcode == SpvOpImageSparseSampleProjImplicitLod ||
-            opcode == SpvOpImageSparseSampleProjExplicitLod ||
-            opcode == SpvOpImageSparseSampleProjDrefImplicitLod ||
-            opcode == SpvOpImageSparseSampleProjDrefExplicitLod ||
-            opcode == SpvOpImageSparseFetch ||
-            opcode == SpvOpImageSparseGather ||
-            opcode == SpvOpImageSparseDrefGather ||
-            opcode == SpvOpImageSparseRead) &&
+    assert((opcode == spv::Op::OpImageSampleImplicitLod ||
+            opcode == spv::Op::OpImageSampleExplicitLod ||
+            opcode == spv::Op::OpImageSampleDrefImplicitLod ||
+            opcode == spv::Op::OpImageSampleDrefExplicitLod ||
+            opcode == spv::Op::OpImageSampleProjImplicitLod ||
+            opcode == spv::Op::OpImageSampleProjExplicitLod ||
+            opcode == spv::Op::OpImageSampleProjDrefImplicitLod ||
+            opcode == spv::Op::OpImageSampleProjDrefExplicitLod ||
+            opcode == spv::Op::OpImageFetch ||
+            opcode == spv::Op::OpImageGather ||
+            opcode == spv::Op::OpImageDrefGather ||
+            opcode == spv::Op::OpImageRead || opcode == spv::Op::OpImageWrite ||
+            opcode == spv::Op::OpImageSparseSampleImplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleExplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleDrefImplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleDrefExplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleProjImplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleProjExplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleProjDrefImplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleProjDrefExplicitLod ||
+            opcode == spv::Op::OpImageSparseFetch ||
+            opcode == spv::Op::OpImageSparseGather ||
+            opcode == spv::Op::OpImageSparseDrefGather ||
+            opcode == spv::Op::OpImageSparseRead) &&
            "Wrong opcode.  Should be an image instruction.");
 
     int32_t operand_index = ImageOperandsMaskInOperandIndex(inst);
     if (operand_index >= 0) {
       auto image_operands = inst->GetSingleWordInOperand(operand_index);
-      if (image_operands & SpvImageOperandsOffsetMask) {
+      if (image_operands & uint32_t(spv::ImageOperandsMask::Offset)) {
         uint32_t offset_operand_index = operand_index + 1;
-        if (image_operands & SpvImageOperandsBiasMask) offset_operand_index++;
-        if (image_operands & SpvImageOperandsLodMask) offset_operand_index++;
-        if (image_operands & SpvImageOperandsGradMask)
+        if (image_operands & uint32_t(spv::ImageOperandsMask::Bias))
+          offset_operand_index++;
+        if (image_operands & uint32_t(spv::ImageOperandsMask::Lod))
+          offset_operand_index++;
+        if (image_operands & uint32_t(spv::ImageOperandsMask::Grad))
           offset_operand_index += 2;
-        assert(((image_operands & SpvImageOperandsConstOffsetMask) == 0) &&
+        assert(((image_operands &
+                 uint32_t(spv::ImageOperandsMask::ConstOffset)) == 0) &&
                "Offset and ConstOffset may not be used together");
         if (offset_operand_index < inst->NumOperands()) {
           if (constants[offset_operand_index]) {
-            image_operands = image_operands | SpvImageOperandsConstOffsetMask;
-            image_operands = image_operands & ~SpvImageOperandsOffsetMask;
+            image_operands =
+                image_operands | uint32_t(spv::ImageOperandsMask::ConstOffset);
+            image_operands =
+                image_operands & ~uint32_t(spv::ImageOperandsMask::Offset);
             inst->SetInOperand(operand_index, {image_operands});
             return true;
           }
@@ -2862,108 +2904,119 @@
   // Note that the order in which rules are added to the list matters. If a rule
   // applies to the instruction, the rest of the rules will not be attempted.
   // Take that into consideration.
-  rules_[SpvOpBitcast].push_back(BitCastScalarOrVector());
+  rules_[spv::Op::OpBitcast].push_back(BitCastScalarOrVector());
 
-  rules_[SpvOpCompositeConstruct].push_back(CompositeExtractFeedingConstruct);
+  rules_[spv::Op::OpCompositeConstruct].push_back(
+      CompositeExtractFeedingConstruct);
 
-  rules_[SpvOpCompositeExtract].push_back(InsertFeedingExtract());
-  rules_[SpvOpCompositeExtract].push_back(CompositeConstructFeedingExtract);
-  rules_[SpvOpCompositeExtract].push_back(VectorShuffleFeedingExtract());
-  rules_[SpvOpCompositeExtract].push_back(FMixFeedingExtract());
+  rules_[spv::Op::OpCompositeExtract].push_back(InsertFeedingExtract());
+  rules_[spv::Op::OpCompositeExtract].push_back(
+      CompositeConstructFeedingExtract);
+  rules_[spv::Op::OpCompositeExtract].push_back(VectorShuffleFeedingExtract());
+  rules_[spv::Op::OpCompositeExtract].push_back(FMixFeedingExtract());
 
-  rules_[SpvOpCompositeInsert].push_back(CompositeInsertToCompositeConstruct);
+  rules_[spv::Op::OpCompositeInsert].push_back(
+      CompositeInsertToCompositeConstruct);
 
-  rules_[SpvOpDot].push_back(DotProductDoingExtract());
+  rules_[spv::Op::OpDot].push_back(DotProductDoingExtract());
 
-  rules_[SpvOpEntryPoint].push_back(RemoveRedundantOperands());
+  rules_[spv::Op::OpEntryPoint].push_back(RemoveRedundantOperands());
 
-  rules_[SpvOpFAdd].push_back(RedundantFAdd());
-  rules_[SpvOpFAdd].push_back(MergeAddNegateArithmetic());
-  rules_[SpvOpFAdd].push_back(MergeAddAddArithmetic());
-  rules_[SpvOpFAdd].push_back(MergeAddSubArithmetic());
-  rules_[SpvOpFAdd].push_back(MergeGenericAddSubArithmetic());
-  rules_[SpvOpFAdd].push_back(FactorAddMuls());
-  rules_[SpvOpFAdd].push_back(MergeMulAddArithmetic);
+  rules_[spv::Op::OpFAdd].push_back(RedundantFAdd());
+  rules_[spv::Op::OpFAdd].push_back(MergeAddNegateArithmetic());
+  rules_[spv::Op::OpFAdd].push_back(MergeAddAddArithmetic());
+  rules_[spv::Op::OpFAdd].push_back(MergeAddSubArithmetic());
+  rules_[spv::Op::OpFAdd].push_back(MergeGenericAddSubArithmetic());
+  rules_[spv::Op::OpFAdd].push_back(FactorAddMuls());
+  rules_[spv::Op::OpFAdd].push_back(MergeMulAddArithmetic);
 
-  rules_[SpvOpFDiv].push_back(RedundantFDiv());
-  rules_[SpvOpFDiv].push_back(ReciprocalFDiv());
-  rules_[SpvOpFDiv].push_back(MergeDivDivArithmetic());
-  rules_[SpvOpFDiv].push_back(MergeDivMulArithmetic());
-  rules_[SpvOpFDiv].push_back(MergeDivNegateArithmetic());
+  rules_[spv::Op::OpFDiv].push_back(RedundantFDiv());
+  rules_[spv::Op::OpFDiv].push_back(ReciprocalFDiv());
+  rules_[spv::Op::OpFDiv].push_back(MergeDivDivArithmetic());
+  rules_[spv::Op::OpFDiv].push_back(MergeDivMulArithmetic());
+  rules_[spv::Op::OpFDiv].push_back(MergeDivNegateArithmetic());
 
-  rules_[SpvOpFMul].push_back(RedundantFMul());
-  rules_[SpvOpFMul].push_back(MergeMulMulArithmetic());
-  rules_[SpvOpFMul].push_back(MergeMulDivArithmetic());
-  rules_[SpvOpFMul].push_back(MergeMulNegateArithmetic());
+  rules_[spv::Op::OpFMul].push_back(RedundantFMul());
+  rules_[spv::Op::OpFMul].push_back(MergeMulMulArithmetic());
+  rules_[spv::Op::OpFMul].push_back(MergeMulDivArithmetic());
+  rules_[spv::Op::OpFMul].push_back(MergeMulNegateArithmetic());
 
-  rules_[SpvOpFNegate].push_back(MergeNegateArithmetic());
-  rules_[SpvOpFNegate].push_back(MergeNegateAddSubArithmetic());
-  rules_[SpvOpFNegate].push_back(MergeNegateMulDivArithmetic());
+  rules_[spv::Op::OpFNegate].push_back(MergeNegateArithmetic());
+  rules_[spv::Op::OpFNegate].push_back(MergeNegateAddSubArithmetic());
+  rules_[spv::Op::OpFNegate].push_back(MergeNegateMulDivArithmetic());
 
-  rules_[SpvOpFSub].push_back(RedundantFSub());
-  rules_[SpvOpFSub].push_back(MergeSubNegateArithmetic());
-  rules_[SpvOpFSub].push_back(MergeSubAddArithmetic());
-  rules_[SpvOpFSub].push_back(MergeSubSubArithmetic());
-  rules_[SpvOpFSub].push_back(MergeMulSubArithmetic);
+  rules_[spv::Op::OpFSub].push_back(RedundantFSub());
+  rules_[spv::Op::OpFSub].push_back(MergeSubNegateArithmetic());
+  rules_[spv::Op::OpFSub].push_back(MergeSubAddArithmetic());
+  rules_[spv::Op::OpFSub].push_back(MergeSubSubArithmetic());
+  rules_[spv::Op::OpFSub].push_back(MergeMulSubArithmetic);
 
-  rules_[SpvOpIAdd].push_back(RedundantIAdd());
-  rules_[SpvOpIAdd].push_back(MergeAddNegateArithmetic());
-  rules_[SpvOpIAdd].push_back(MergeAddAddArithmetic());
-  rules_[SpvOpIAdd].push_back(MergeAddSubArithmetic());
-  rules_[SpvOpIAdd].push_back(MergeGenericAddSubArithmetic());
-  rules_[SpvOpIAdd].push_back(FactorAddMuls());
+  rules_[spv::Op::OpIAdd].push_back(RedundantIAdd());
+  rules_[spv::Op::OpIAdd].push_back(MergeAddNegateArithmetic());
+  rules_[spv::Op::OpIAdd].push_back(MergeAddAddArithmetic());
+  rules_[spv::Op::OpIAdd].push_back(MergeAddSubArithmetic());
+  rules_[spv::Op::OpIAdd].push_back(MergeGenericAddSubArithmetic());
+  rules_[spv::Op::OpIAdd].push_back(FactorAddMuls());
 
-  rules_[SpvOpIMul].push_back(IntMultipleBy1());
-  rules_[SpvOpIMul].push_back(MergeMulMulArithmetic());
-  rules_[SpvOpIMul].push_back(MergeMulNegateArithmetic());
+  rules_[spv::Op::OpIMul].push_back(IntMultipleBy1());
+  rules_[spv::Op::OpIMul].push_back(MergeMulMulArithmetic());
+  rules_[spv::Op::OpIMul].push_back(MergeMulNegateArithmetic());
 
-  rules_[SpvOpISub].push_back(MergeSubNegateArithmetic());
-  rules_[SpvOpISub].push_back(MergeSubAddArithmetic());
-  rules_[SpvOpISub].push_back(MergeSubSubArithmetic());
+  rules_[spv::Op::OpISub].push_back(MergeSubNegateArithmetic());
+  rules_[spv::Op::OpISub].push_back(MergeSubAddArithmetic());
+  rules_[spv::Op::OpISub].push_back(MergeSubSubArithmetic());
 
-  rules_[SpvOpPhi].push_back(RedundantPhi());
+  rules_[spv::Op::OpPhi].push_back(RedundantPhi());
 
-  rules_[SpvOpSNegate].push_back(MergeNegateArithmetic());
-  rules_[SpvOpSNegate].push_back(MergeNegateMulDivArithmetic());
-  rules_[SpvOpSNegate].push_back(MergeNegateAddSubArithmetic());
+  rules_[spv::Op::OpSNegate].push_back(MergeNegateArithmetic());
+  rules_[spv::Op::OpSNegate].push_back(MergeNegateMulDivArithmetic());
+  rules_[spv::Op::OpSNegate].push_back(MergeNegateAddSubArithmetic());
 
-  rules_[SpvOpSelect].push_back(RedundantSelect());
+  rules_[spv::Op::OpSelect].push_back(RedundantSelect());
 
-  rules_[SpvOpStore].push_back(StoringUndef());
+  rules_[spv::Op::OpStore].push_back(StoringUndef());
 
-  rules_[SpvOpVectorShuffle].push_back(VectorShuffleFeedingShuffle());
+  rules_[spv::Op::OpVectorShuffle].push_back(VectorShuffleFeedingShuffle());
 
-  rules_[SpvOpImageSampleImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleDrefImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleDrefExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleProjImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleProjExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleProjDrefImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleProjDrefExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageFetch].push_back(UpdateImageOperands());
-  rules_[SpvOpImageGather].push_back(UpdateImageOperands());
-  rules_[SpvOpImageDrefGather].push_back(UpdateImageOperands());
-  rules_[SpvOpImageRead].push_back(UpdateImageOperands());
-  rules_[SpvOpImageWrite].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleDrefImplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleImplicitLod].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSampleExplicitLod].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSampleDrefImplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleDrefExplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleDrefExplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleProjImplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleProjImplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleProjExplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleProjExplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleProjDrefImplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleProjDrefImplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleProjDrefExplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleProjDrefExplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseFetch].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseGather].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseDrefGather].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseRead].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageFetch].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageGather].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageDrefGather].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageRead].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageWrite].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleImplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleExplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleDrefImplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleDrefExplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleProjImplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleProjExplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleProjDrefImplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleProjDrefExplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseFetch].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseGather].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseDrefGather].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseRead].push_back(UpdateImageOperands());
 
   FeatureManager* feature_manager = context_->get_feature_mgr();
   // Add rules for GLSLstd450
diff --git a/third_party/SPIRV-Tools/source/opt/folding_rules.h b/third_party/SPIRV-Tools/source/opt/folding_rules.h
index f1a8639..b51e0ce 100644
--- a/third_party/SPIRV-Tools/source/opt/folding_rules.h
+++ b/third_party/SPIRV-Tools/source/opt/folding_rules.h
@@ -64,7 +64,7 @@
   virtual ~FoldingRules() = default;
 
   const FoldingRuleSet& GetRulesForInstruction(Instruction* inst) const {
-    if (inst->opcode() != SpvOpExtInst) {
+    if (inst->opcode() != spv::Op::OpExtInst) {
       auto it = rules_.find(inst->opcode());
       if (it != rules_.end()) {
         return it->second;
@@ -86,8 +86,14 @@
   virtual void AddFoldingRules();
 
  protected:
+  struct hasher {
+    size_t operator()(const spv::Op& op) const noexcept {
+      return std::hash<uint32_t>()(uint32_t(op));
+    }
+  };
+
   // The folding rules for core instructions.
-  std::unordered_map<uint32_t, FoldingRuleSet> rules_;
+  std::unordered_map<spv::Op, FoldingRuleSet, hasher> rules_;
 
   // The folding rules for extended instructions.
   struct Key {
diff --git a/third_party/SPIRV-Tools/source/opt/freeze_spec_constant_value_pass.cpp b/third_party/SPIRV-Tools/source/opt/freeze_spec_constant_value_pass.cpp
index 10e98fd..3f89e56 100644
--- a/third_party/SPIRV-Tools/source/opt/freeze_spec_constant_value_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/freeze_spec_constant_value_pass.cpp
@@ -23,21 +23,21 @@
   auto ctx = context();
   ctx->module()->ForEachInst([&modified, ctx](Instruction* inst) {
     switch (inst->opcode()) {
-      case SpvOp::SpvOpSpecConstant:
-        inst->SetOpcode(SpvOp::SpvOpConstant);
+      case spv::Op::OpSpecConstant:
+        inst->SetOpcode(spv::Op::OpConstant);
         modified = true;
         break;
-      case SpvOp::SpvOpSpecConstantTrue:
-        inst->SetOpcode(SpvOp::SpvOpConstantTrue);
+      case spv::Op::OpSpecConstantTrue:
+        inst->SetOpcode(spv::Op::OpConstantTrue);
         modified = true;
         break;
-      case SpvOp::SpvOpSpecConstantFalse:
-        inst->SetOpcode(SpvOp::SpvOpConstantFalse);
+      case spv::Op::OpSpecConstantFalse:
+        inst->SetOpcode(spv::Op::OpConstantFalse);
         modified = true;
         break;
-      case SpvOp::SpvOpDecorate:
-        if (inst->GetSingleWordInOperand(1) ==
-            SpvDecoration::SpvDecorationSpecId) {
+      case spv::Op::OpDecorate:
+        if (spv::Decoration(inst->GetSingleWordInOperand(1)) ==
+            spv::Decoration::SpecId) {
           ctx->KillInst(inst);
           modified = true;
         }
diff --git a/third_party/SPIRV-Tools/source/opt/function.cpp b/third_party/SPIRV-Tools/source/opt/function.cpp
index 38c6695..6c7c949 100644
--- a/third_party/SPIRV-Tools/source/opt/function.cpp
+++ b/third_party/SPIRV-Tools/source/opt/function.cpp
@@ -264,11 +264,19 @@
   std::ostringstream str;
   ForEachInst([&str, options](const Instruction* inst) {
     str << inst->PrettyPrint(options);
-    if (inst->opcode() != SpvOpFunctionEnd) {
+    if (inst->opcode() != spv::Op::OpFunctionEnd) {
       str << std::endl;
     }
   });
   return str.str();
 }
+
+void Function::ReorderBasicBlocksInStructuredOrder() {
+  std::list<BasicBlock*> order;
+  IRContext* context = this->def_inst_->context();
+  context->cfg()->ComputeStructuredOrder(this, blocks_[0].get(), &order);
+  ReorderBasicBlocks(order.begin(), order.end());
+}
+
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/function.h b/third_party/SPIRV-Tools/source/opt/function.h
index 917bf58..8c0472c 100644
--- a/third_party/SPIRV-Tools/source/opt/function.h
+++ b/third_party/SPIRV-Tools/source/opt/function.h
@@ -19,6 +19,7 @@
 #include <functional>
 #include <memory>
 #include <string>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -180,7 +181,19 @@
   // Returns true is a function declaration and not a function definition.
   bool IsDeclaration() { return begin() == end(); }
 
+  // Reorders the basic blocks in the function to match the structured order.
+  void ReorderBasicBlocksInStructuredOrder();
+
  private:
+  // Reorders the basic blocks in the function to match the order given by the
+  // range |{begin,end}|.  The range must contain every basic block in the
+  // function, and no extras.
+  template <class It>
+  void ReorderBasicBlocks(It begin, It end);
+
+  template <class It>
+  bool ContainsAllBlocksInTheFunction(It begin, It end);
+
   // The OpFunction instruction that begins the definition of this function.
   std::unique_ptr<Instruction> def_inst_;
   // All parameters to this function.
@@ -240,7 +253,7 @@
   auto first_empty =
       std::remove_if(std::begin(blocks_), std::end(blocks_),
                      [](const std::unique_ptr<BasicBlock>& bb) -> bool {
-                       return bb->GetLabelInst()->opcode() == SpvOpNop;
+                       return bb->GetLabelInst()->opcode() == spv::Op::OpNop;
                      });
   blocks_.erase(first_empty, std::end(blocks_));
 }
@@ -262,6 +275,34 @@
   non_semantic_.emplace_back(std::move(non_semantic));
 }
 
+template <class It>
+void Function::ReorderBasicBlocks(It begin, It end) {
+  // Asserts to make sure every node in the function is in new_order.
+  assert(ContainsAllBlocksInTheFunction(begin, end));
+
+  // We have a pointer to all the elements in order, so we can release all
+  // pointers in |block_|, and then create the new unique pointers from |{begin,
+  // end}|.
+  std::for_each(blocks_.begin(), blocks_.end(),
+                [](std::unique_ptr<BasicBlock>& bb) { bb.release(); });
+  std::transform(begin, end, blocks_.begin(), [](BasicBlock* bb) {
+    return std::unique_ptr<BasicBlock>(bb);
+  });
+}
+
+template <class It>
+bool Function::ContainsAllBlocksInTheFunction(It begin, It end) {
+  std::unordered_multiset<BasicBlock*> range(begin, end);
+  if (range.size() != blocks_.size()) {
+    return false;
+  }
+
+  for (auto& bb : blocks_) {
+    if (range.count(bb.get()) == 0) return false;
+  }
+  return true;
+}
+
 }  // namespace opt
 }  // namespace spvtools
 
diff --git a/third_party/SPIRV-Tools/source/opt/graphics_robust_access_pass.cpp b/third_party/SPIRV-Tools/source/opt/graphics_robust_access_pass.cpp
index 4652d72..da2764f 100644
--- a/third_party/SPIRV-Tools/source/opt/graphics_robust_access_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/graphics_robust_access_pass.cpp
@@ -158,7 +158,6 @@
 #include "source/util/make_unique.h"
 #include "spirv-tools/libspirv.h"
 #include "spirv/unified1/GLSL.std.450.h"
-#include "spirv/unified1/spirv.h"
 #include "type_manager.h"
 #include "types.h"
 
@@ -194,14 +193,15 @@
 
 spv_result_t GraphicsRobustAccessPass::IsCompatibleModule() {
   auto* feature_mgr = context()->get_feature_mgr();
-  if (!feature_mgr->HasCapability(SpvCapabilityShader))
+  if (!feature_mgr->HasCapability(spv::Capability::Shader))
     return Fail() << "Can only process Shader modules";
-  if (feature_mgr->HasCapability(SpvCapabilityVariablePointers))
+  if (feature_mgr->HasCapability(spv::Capability::VariablePointers))
     return Fail() << "Can't process modules with VariablePointers capability";
-  if (feature_mgr->HasCapability(SpvCapabilityVariablePointersStorageBuffer))
+  if (feature_mgr->HasCapability(
+          spv::Capability::VariablePointersStorageBuffer))
     return Fail() << "Can't process modules with VariablePointersStorageBuffer "
                      "capability";
-  if (feature_mgr->HasCapability(SpvCapabilityRuntimeDescriptorArrayEXT)) {
+  if (feature_mgr->HasCapability(spv::Capability::RuntimeDescriptorArrayEXT)) {
     // These have a RuntimeArray outside of Block-decorated struct.  There
     // is no way to compute the array length from within SPIR-V.
     return Fail() << "Can't process modules with RuntimeDescriptorArrayEXT "
@@ -210,8 +210,9 @@
 
   {
     auto* inst = context()->module()->GetMemoryModel();
-    const auto addressing_model = inst->GetSingleWordOperand(0);
-    if (addressing_model != SpvAddressingModelLogical)
+    const auto addressing_model =
+        spv::AddressingModel(inst->GetSingleWordOperand(0));
+    if (addressing_model != spv::AddressingModel::Logical)
       return Fail() << "Addressing model must be Logical.  Found "
                     << inst->PrettyPrint();
   }
@@ -237,11 +238,11 @@
   for (auto& block : *function) {
     for (auto& inst : block) {
       switch (inst.opcode()) {
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain:
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain:
           access_chains.push_back(&inst);
           break;
-        case SpvOpImageTexelPointer:
+        case spv::Op::OpImageTexelPointer:
           image_texel_pointers.push_back(&inst);
           break;
         default:
@@ -268,7 +269,7 @@
   auto* def_use_mgr = context()->get_def_use_mgr();
   auto* type_mgr = context()->get_type_mgr();
   const bool have_int64_cap =
-      context()->get_feature_mgr()->HasCapability(SpvCapabilityInt64);
+      context()->get_feature_mgr()->HasCapability(spv::Capability::Int64);
 
   // Replaces one of the OpAccessChain index operands with a new value.
   // Updates def-use analysis.
@@ -451,7 +452,7 @@
       // It doesn't matter if 1 is signed or unsigned.
       auto* one = GetValueForType(1, wider_type);
       auto* count_minus_1 = InsertInst(
-          &inst, SpvOpISub, type_mgr->GetId(wider_type), TakeNextId(),
+          &inst, spv::Op::OpISub, type_mgr->GetId(wider_type), TakeNextId(),
           {{SPV_OPERAND_TYPE_ID, {count_inst->result_id()}},
            {SPV_OPERAND_TYPE_ID, {one->result_id()}}});
       auto* zero = GetValueForType(0, wider_type);
@@ -486,15 +487,15 @@
     Instruction* index_inst = GetDef(index_id);
 
     switch (pointee_type->opcode()) {
-      case SpvOpTypeMatrix:  // Use column count
-      case SpvOpTypeVector:  // Use component count
+      case spv::Op::OpTypeMatrix:  // Use column count
+      case spv::Op::OpTypeVector:  // Use component count
       {
         const uint32_t count = pointee_type->GetSingleWordOperand(2);
         clamp_to_literal_count(idx, count);
         pointee_type = GetDef(pointee_type->GetSingleWordOperand(1));
       } break;
 
-      case SpvOpTypeArray: {
+      case spv::Op::OpTypeArray: {
         // The array length can be a spec constant, so go through the general
         // case.
         Instruction* array_len = GetDef(pointee_type->GetSingleWordOperand(2));
@@ -502,11 +503,11 @@
         pointee_type = GetDef(pointee_type->GetSingleWordOperand(1));
       } break;
 
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // SPIR-V requires the index to be an OpConstant.
         // We need to know the index literal value so we can compute the next
         // pointee type.
-        if (index_inst->opcode() != SpvOpConstant ||
+        if (index_inst->opcode() != spv::Op::OpConstant ||
             !constant_mgr->GetConstantFromInst(index_inst)
                  ->type()
                  ->AsInteger()) {
@@ -537,7 +538,7 @@
         // No need to clamp this index.  We just checked that it's valid.
       } break;
 
-      case SpvOpTypeRuntimeArray: {
+      case spv::Op::OpTypeRuntimeArray: {
         auto* array_len = MakeRuntimeArrayLengthInst(&inst, idx);
         if (!array_len) {  // We've already signaled an error.
           return;
@@ -571,7 +572,7 @@
       module_status_.glsl_insts_id = TakeNextId();
       std::vector<uint32_t> words = spvtools::utils::MakeVector(glsl);
       auto import_inst = MakeUnique<Instruction>(
-          context(), SpvOpExtInstImport, 0, module_status_.glsl_insts_id,
+          context(), spv::Op::OpExtInstImport, 0, module_status_.glsl_insts_id,
           std::initializer_list<Operand>{
               Operand{SPV_OPERAND_TYPE_LITERAL_STRING, std::move(words)}});
       Instruction* inst = import_inst.get();
@@ -609,8 +610,8 @@
   auto type_id = context()->get_type_mgr()->GetId(unsigned_type);
   auto conversion_id = TakeNextId();
   auto* conversion = InsertInst(
-      before_inst, (sign_extend ? SpvOpSConvert : SpvOpUConvert), type_id,
-      conversion_id, {{SPV_OPERAND_TYPE_ID, {value->result_id()}}});
+      before_inst, (sign_extend ? spv::Op::OpSConvert : spv::Op::OpUConvert),
+      type_id, conversion_id, {{SPV_OPERAND_TYPE_ID, {value->result_id()}}});
   return conversion;
 }
 
@@ -628,7 +629,7 @@
   (void)xwidth;
   (void)ywidth;
   auto* smin_inst = InsertInst(
-      where, SpvOpExtInst, x->type_id(), smin_id,
+      where, spv::Op::OpExtInst, x->type_id(), smin_id,
       {
           {SPV_OPERAND_TYPE_ID, {glsl_insts_id}},
           {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, {GLSLstd450UMin}},
@@ -655,7 +656,7 @@
   (void)minwidth;
   (void)maxwidth;
   auto* clamp_inst = InsertInst(
-      where, SpvOpExtInst, x->type_id(), clamp_id,
+      where, spv::Op::OpExtInst, x->type_id(), clamp_id,
       {
           {SPV_OPERAND_TYPE_ID, {glsl_insts_id}},
           {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, {GLSLstd450SClamp}},
@@ -689,13 +690,13 @@
   Instruction* pointer_to_containing_struct = nullptr;
   while (steps_remaining > 0) {
     switch (current_access_chain->opcode()) {
-      case SpvOpCopyObject:
+      case spv::Op::OpCopyObject:
         // Whoops. Walk right through this one.
         current_access_chain =
             GetDef(current_access_chain->GetSingleWordInOperand(0));
         break;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain: {
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain: {
         const int first_index_operand = 3;
         // How many indices in this access chain contribute to getting us
         // to an element in the runtime array?
@@ -793,7 +794,8 @@
   analysis::Integer uint_type_for_query(32, false);
   auto* uint_type = type_mgr->GetRegisteredType(&uint_type_for_query);
   auto* array_len = InsertInst(
-      access_chain, SpvOpArrayLength, type_mgr->GetId(uint_type), array_len_id,
+      access_chain, spv::Op::OpArrayLength, type_mgr->GetId(uint_type),
+      array_len_id,
       {{SPV_OPERAND_TYPE_ID, {pointer_to_containing_struct->result_id()}},
        {SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index_of_runtime_array}}});
   return array_len;
@@ -839,11 +841,11 @@
 
   // Declare the ImageQuery capability if the module doesn't already have it.
   auto* feature_mgr = context()->get_feature_mgr();
-  if (!feature_mgr->HasCapability(SpvCapabilityImageQuery)) {
+  if (!feature_mgr->HasCapability(spv::Capability::ImageQuery)) {
     auto cap = MakeUnique<Instruction>(
-        context(), SpvOpCapability, 0, 0,
+        context(), spv::Op::OpCapability, 0, 0,
         std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityImageQuery}}});
+            {SPV_OPERAND_TYPE_CAPABILITY, {spv::Capability::ImageQuery}}});
     def_use_mgr->AnalyzeInstDefUse(cap.get());
     context()->AddCapability(std::move(cap));
     feature_mgr->Analyze(context()->module());
@@ -890,21 +892,21 @@
     const int arrayness_bonus = arrayed ? 1 : 0;
     int num_coords = 0;
     switch (dim) {
-      case SpvDimBuffer:
+      case spv::Dim::Buffer:
       case SpvDim1D:
         num_coords = 1;
         break;
-      case SpvDimCube:
+      case spv::Dim::Cube:
         // For cube, we need bounds for x, y, but not face.
-      case SpvDimRect:
+      case spv::Dim::Rect:
       case SpvDim2D:
         num_coords = 2;
         break;
       case SpvDim3D:
         num_coords = 3;
         break;
-      case SpvDimSubpassData:
-      case SpvDimMax:
+      case spv::Dim::SubpassData:
+      case spv::Dim::Max:
         return Fail() << "Invalid image dimension for OpImageTexelPointer: "
                       << int(dim);
         break;
@@ -941,12 +943,12 @@
 
   const uint32_t image_id = TakeNextId();
   auto* image =
-      InsertInst(image_texel_pointer, SpvOpLoad, image_type_id, image_id,
+      InsertInst(image_texel_pointer, spv::Op::OpLoad, image_type_id, image_id,
                  {{SPV_OPERAND_TYPE_ID, {image_ptr->result_id()}}});
 
   const uint32_t query_size_id = TakeNextId();
   auto* query_size =
-      InsertInst(image_texel_pointer, SpvOpImageQuerySize,
+      InsertInst(image_texel_pointer, spv::Op::OpImageQuerySize,
                  type_mgr->GetTypeInstruction(query_size_type), query_size_id,
                  {{SPV_OPERAND_TYPE_ID, {image->result_id()}}});
 
@@ -962,7 +964,7 @@
   // in the face index ranging from 0 through 5. The inclusive upper bound
   // on the third coordinate therefore is multiplied by 6.
   auto* query_size_including_faces = query_size;
-  if (arrayed && (dim == SpvDimCube)) {
+  if (arrayed && (dim == spv::Dim::Cube)) {
     // Multiply the last coordinate by 6.
     auto* component_6 = constant_mgr->GetConstant(coord_component_type, {6});
     const uint32_t component_6_id =
@@ -974,7 +976,7 @@
         constant_mgr->GetDefiningInstruction(multiplicand);
     const auto query_size_including_faces_id = TakeNextId();
     query_size_including_faces = InsertInst(
-        image_texel_pointer, SpvOpIMul,
+        image_texel_pointer, spv::Op::OpIMul,
         type_mgr->GetTypeInstruction(query_size_type),
         query_size_including_faces_id,
         {{SPV_OPERAND_TYPE_ID, {query_size_including_faces->result_id()}},
@@ -998,7 +1000,7 @@
 
   const uint32_t query_max_including_faces_id = TakeNextId();
   auto* query_max_including_faces = InsertInst(
-      image_texel_pointer, SpvOpISub,
+      image_texel_pointer, spv::Op::OpISub,
       type_mgr->GetTypeInstruction(query_size_type),
       query_max_including_faces_id,
       {{SPV_OPERAND_TYPE_ID, {query_size_including_faces->result_id()}},
@@ -1016,12 +1018,12 @@
     // Get the sample count via OpImageQuerySamples
     const auto query_samples_id = TakeNextId();
     auto* query_samples = InsertInst(
-        image_texel_pointer, SpvOpImageQuerySamples,
+        image_texel_pointer, spv::Op::OpImageQuerySamples,
         constant_mgr->GetDefiningInstruction(component_0)->type_id(),
         query_samples_id, {{SPV_OPERAND_TYPE_ID, {image->result_id()}}});
 
     const auto max_samples_id = TakeNextId();
-    auto* max_samples = InsertInst(image_texel_pointer, SpvOpImageQuerySamples,
+    auto* max_samples = InsertInst(image_texel_pointer, spv::Op::OpImageQuerySamples,
                                    query_samples->type_id(), max_samples_id,
                                    {{SPV_OPERAND_TYPE_ID, {query_samples_id}},
                                     {SPV_OPERAND_TYPE_ID, {component_1_id}}});
@@ -1043,7 +1045,7 @@
 }
 
 opt::Instruction* GraphicsRobustAccessPass::InsertInst(
-    opt::Instruction* where_inst, SpvOp opcode, uint32_t type_id,
+    opt::Instruction* where_inst, spv::Op opcode, uint32_t type_id,
     uint32_t result_id, const Instruction::OperandList& operands) {
   module_status_.modified = true;
   auto* result = where_inst->InsertBefore(
diff --git a/third_party/SPIRV-Tools/source/opt/graphics_robust_access_pass.h b/third_party/SPIRV-Tools/source/opt/graphics_robust_access_pass.h
index 8f4c9dc..a7ffe11 100644
--- a/third_party/SPIRV-Tools/source/opt/graphics_robust_access_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/graphics_robust_access_pass.h
@@ -133,7 +133,7 @@
   // Returns a new instruction inserted before |where_inst|, and created from
   // the remaining arguments. Registers the definitions and uses of the new
   // instruction and also records its block.
-  opt::Instruction* InsertInst(opt::Instruction* where_inst, SpvOp opcode,
+  opt::Instruction* InsertInst(opt::Instruction* where_inst, spv::Op opcode,
                                uint32_t type_id, uint32_t result_id,
                                const Instruction::OperandList& operands);
 
diff --git a/third_party/SPIRV-Tools/source/opt/if_conversion.cpp b/third_party/SPIRV-Tools/source/opt/if_conversion.cpp
index 1232796..5912cf1 100644
--- a/third_party/SPIRV-Tools/source/opt/if_conversion.cpp
+++ b/third_party/SPIRV-Tools/source/opt/if_conversion.cpp
@@ -23,7 +23,7 @@
 namespace opt {
 
 Pass::Status IfConversion::Process() {
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
     return Status::SuccessWithoutChange;
   }
 
@@ -40,7 +40,7 @@
 
       // Get an insertion point.
       auto iter = block.begin();
-      while (iter != block.end() && iter->opcode() == SpvOpPhi) {
+      while (iter != block.end() && iter->opcode() == spv::Op::OpPhi) {
         ++iter;
       }
 
@@ -171,23 +171,26 @@
   *common = dominators->CommonDominator(inc0, inc1);
   if (!*common || cfg()->IsPseudoEntryBlock(*common)) return false;
   Instruction* branch = (*common)->terminator();
-  if (branch->opcode() != SpvOpBranchConditional) return false;
+  if (branch->opcode() != spv::Op::OpBranchConditional) return false;
   auto merge = (*common)->GetMergeInst();
-  if (!merge || merge->opcode() != SpvOpSelectionMerge) return false;
-  if (merge->GetSingleWordInOperand(1) == SpvSelectionControlDontFlattenMask)
+  if (!merge || merge->opcode() != spv::Op::OpSelectionMerge) return false;
+  if (spv::SelectionControlMask(merge->GetSingleWordInOperand(1)) ==
+      spv::SelectionControlMask::DontFlatten) {
     return false;
+  }
   if ((*common)->MergeBlockIdIfAny() != block->id()) return false;
 
   return true;
 }
 
 bool IfConversion::CheckPhiUsers(Instruction* phi, BasicBlock* block) {
-  return get_def_use_mgr()->WhileEachUser(phi, [block,
-                                                this](Instruction* user) {
-    if (user->opcode() == SpvOpPhi && context()->get_instr_block(user) == block)
-      return false;
-    return true;
-  });
+  return get_def_use_mgr()->WhileEachUser(
+      phi, [block, this](Instruction* user) {
+        if (user->opcode() == spv::Op::OpPhi &&
+            context()->get_instr_block(user) == block)
+          return false;
+        return true;
+      });
 }
 
 uint32_t IfConversion::SplatCondition(analysis::Vector* vec_data_ty,
@@ -207,9 +210,9 @@
 
 bool IfConversion::CheckType(uint32_t id) {
   Instruction* type = get_def_use_mgr()->GetDef(id);
-  SpvOp op = type->opcode();
-  if (spvOpcodeIsScalarType(op) || op == SpvOpTypePointer ||
-      op == SpvOpTypeVector)
+  spv::Op op = type->opcode();
+  if (spvOpcodeIsScalarType(op) || op == spv::Op::OpTypePointer ||
+      op == spv::Op::OpTypeVector)
     return true;
   return false;
 }
@@ -255,7 +258,7 @@
       });
 
   Instruction* insertion_pos = target_block->terminator();
-  if ((insertion_pos)->PreviousNode()->opcode() == SpvOpSelectionMerge) {
+  if ((insertion_pos)->PreviousNode()->opcode() == spv::Op::OpSelectionMerge) {
     insertion_pos = insertion_pos->PreviousNode();
   }
   inst->RemoveFromList();
diff --git a/third_party/SPIRV-Tools/source/opt/inline_opaque_pass.cpp b/third_party/SPIRV-Tools/source/opt/inline_opaque_pass.cpp
index fe9c679..90a4c22 100644
--- a/third_party/SPIRV-Tools/source/opt/inline_opaque_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/inline_opaque_pass.cpp
@@ -21,26 +21,24 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-const uint32_t kTypePointerTypeIdInIdx = 1;
-
-}  // anonymous namespace
+constexpr uint32_t kTypePointerTypeIdInIdx = 1;
+}  // namespace
 
 bool InlineOpaquePass::IsOpaqueType(uint32_t typeId) {
   const Instruction* typeInst = get_def_use_mgr()->GetDef(typeId);
   switch (typeInst->opcode()) {
-    case SpvOpTypeSampler:
-    case SpvOpTypeImage:
-    case SpvOpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampledImage:
       return true;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       return IsOpaqueType(
           typeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx));
     default:
       break;
   }
   // TODO(greg-lunarg): Handle arrays containing opaque type
-  if (typeInst->opcode() != SpvOpTypeStruct) return false;
+  if (typeInst->opcode() != spv::Op::OpTypeStruct) return false;
   // Return true if any member is opaque
   return !typeInst->WhileEachInId([this](const uint32_t* tid) {
     if (IsOpaqueType(*tid)) return false;
diff --git a/third_party/SPIRV-Tools/source/opt/inline_pass.cpp b/third_party/SPIRV-Tools/source/opt/inline_pass.cpp
index 6e73f1c..3f160b2 100644
--- a/third_party/SPIRV-Tools/source/opt/inline_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/inline_pass.cpp
@@ -23,24 +23,24 @@
 #include "source/opt/reflect.h"
 #include "source/util/make_unique.h"
 
-// Indices of operands in SPIR-V instructions
-
-static const int kSpvFunctionCallFunctionId = 2;
-static const int kSpvFunctionCallArgumentId = 3;
-static const int kSpvReturnValueId = 0;
-
 namespace spvtools {
 namespace opt {
+namespace {
+// Indices of operands in SPIR-V instructions
+constexpr int kSpvFunctionCallFunctionId = 2;
+constexpr int kSpvFunctionCallArgumentId = 3;
+constexpr int kSpvReturnValueId = 0;
+}  // namespace
 
 uint32_t InlinePass::AddPointerToType(uint32_t type_id,
-                                      SpvStorageClass storage_class) {
+                                      spv::StorageClass storage_class) {
   uint32_t resultId = context()->TakeNextId();
   if (resultId == 0) {
     return resultId;
   }
 
   std::unique_ptr<Instruction> type_inst(
-      new Instruction(context(), SpvOpTypePointer, 0, resultId,
+      new Instruction(context(), spv::Op::OpTypePointer, 0, resultId,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
                         {uint32_t(storage_class)}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {type_id}}}));
@@ -48,8 +48,8 @@
   analysis::Type* pointeeTy;
   std::unique_ptr<analysis::Pointer> pointerTy;
   std::tie(pointeeTy, pointerTy) =
-      context()->get_type_mgr()->GetTypeAndPointerType(type_id,
-                                                       SpvStorageClassFunction);
+      context()->get_type_mgr()->GetTypeAndPointerType(
+          type_id, spv::StorageClass::Function);
   context()->get_type_mgr()->RegisterType(resultId, *pointerTy);
   return resultId;
 }
@@ -57,7 +57,7 @@
 void InlinePass::AddBranch(uint32_t label_id,
                            std::unique_ptr<BasicBlock>* block_ptr) {
   std::unique_ptr<Instruction> newBranch(
-      new Instruction(context(), SpvOpBranch, 0, 0,
+      new Instruction(context(), spv::Op::OpBranch, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {label_id}}}));
   (*block_ptr)->AddInstruction(std::move(newBranch));
 }
@@ -66,7 +66,7 @@
                                uint32_t false_id,
                                std::unique_ptr<BasicBlock>* block_ptr) {
   std::unique_ptr<Instruction> newBranch(
-      new Instruction(context(), SpvOpBranchConditional, 0, 0,
+      new Instruction(context(), spv::Op::OpBranchConditional, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {cond_id}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {true_id}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {false_id}}}));
@@ -76,7 +76,7 @@
 void InlinePass::AddLoopMerge(uint32_t merge_id, uint32_t continue_id,
                               std::unique_ptr<BasicBlock>* block_ptr) {
   std::unique_ptr<Instruction> newLoopMerge(new Instruction(
-      context(), SpvOpLoopMerge, 0, 0,
+      context(), spv::Op::OpLoopMerge, 0, 0,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {merge_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {continue_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LOOP_CONTROL, {0}}}));
@@ -88,7 +88,7 @@
                           const Instruction* line_inst,
                           const DebugScope& dbg_scope) {
   std::unique_ptr<Instruction> newStore(
-      new Instruction(context(), SpvOpStore, 0, 0,
+      new Instruction(context(), spv::Op::OpStore, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {val_id}}}));
   if (line_inst != nullptr) {
@@ -103,7 +103,7 @@
                          const Instruction* line_inst,
                          const DebugScope& dbg_scope) {
   std::unique_ptr<Instruction> newLoad(
-      new Instruction(context(), SpvOpLoad, type_id, resultId,
+      new Instruction(context(), spv::Op::OpLoad, type_id, resultId,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}}}));
   if (line_inst != nullptr) {
     newLoad->AddDebugLine(line_inst);
@@ -114,27 +114,27 @@
 
 std::unique_ptr<Instruction> InlinePass::NewLabel(uint32_t label_id) {
   std::unique_ptr<Instruction> newLabel(
-      new Instruction(context(), SpvOpLabel, 0, label_id, {}));
+      new Instruction(context(), spv::Op::OpLabel, 0, label_id, {}));
   return newLabel;
 }
 
 uint32_t InlinePass::GetFalseId() {
   if (false_id_ != 0) return false_id_;
-  false_id_ = get_module()->GetGlobalValue(SpvOpConstantFalse);
+  false_id_ = get_module()->GetGlobalValue(spv::Op::OpConstantFalse);
   if (false_id_ != 0) return false_id_;
-  uint32_t boolId = get_module()->GetGlobalValue(SpvOpTypeBool);
+  uint32_t boolId = get_module()->GetGlobalValue(spv::Op::OpTypeBool);
   if (boolId == 0) {
     boolId = context()->TakeNextId();
     if (boolId == 0) {
       return 0;
     }
-    get_module()->AddGlobalValue(SpvOpTypeBool, boolId, 0);
+    get_module()->AddGlobalValue(spv::Op::OpTypeBool, boolId, 0);
   }
   false_id_ = context()->TakeNextId();
   if (false_id_ == 0) {
     return 0;
   }
-  get_module()->AddGlobalValue(SpvOpConstantFalse, false_id_, boolId);
+  get_module()->AddGlobalValue(spv::Op::OpConstantFalse, false_id_, boolId);
   return false_id_;
 }
 
@@ -157,10 +157,10 @@
     analysis::DebugInlinedAtContext* inlined_at_ctx) {
   auto callee_block_itr = calleeFn->begin();
   auto callee_var_itr = callee_block_itr->begin();
-  while (callee_var_itr->opcode() == SpvOp::SpvOpVariable ||
+  while (callee_var_itr->opcode() == spv::Op::OpVariable ||
          callee_var_itr->GetCommonDebugOpcode() ==
              CommonDebugInfoDebugDeclare) {
-    if (callee_var_itr->opcode() != SpvOp::SpvOpVariable) {
+    if (callee_var_itr->opcode() != spv::Op::OpVariable) {
       ++callee_var_itr;
       continue;
     }
@@ -191,10 +191,11 @@
          "Cannot create a return variable of type void.");
   // Find or create ptr to callee return type.
   uint32_t returnVarTypeId =
-      type_mgr->FindPointerToType(calleeTypeId, SpvStorageClassFunction);
+      type_mgr->FindPointerToType(calleeTypeId, spv::StorageClass::Function);
 
   if (returnVarTypeId == 0) {
-    returnVarTypeId = AddPointerToType(calleeTypeId, SpvStorageClassFunction);
+    returnVarTypeId =
+        AddPointerToType(calleeTypeId, spv::StorageClass::Function);
     if (returnVarTypeId == 0) {
       return 0;
     }
@@ -206,17 +207,18 @@
     return 0;
   }
 
-  std::unique_ptr<Instruction> var_inst(
-      new Instruction(context(), SpvOpVariable, returnVarTypeId, returnVarId,
-                      {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
-                        {SpvStorageClassFunction}}}));
+  std::unique_ptr<Instruction> var_inst(new Instruction(
+      context(), spv::Op::OpVariable, returnVarTypeId, returnVarId,
+      {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
+        {(uint32_t)spv::StorageClass::Function}}}));
   new_vars->push_back(std::move(var_inst));
   get_decoration_mgr()->CloneDecorations(calleeFn->result_id(), returnVarId);
   return returnVarId;
 }
 
 bool InlinePass::IsSameBlockOp(const Instruction* inst) const {
-  return inst->opcode() == SpvOpSampledImage || inst->opcode() == SpvOpImage;
+  return inst->opcode() == spv::Op::OpSampledImage ||
+         inst->opcode() == spv::Op::OpImage;
 }
 
 bool InlinePass::CloneSameBlockOps(
@@ -299,9 +301,9 @@
     std::unique_ptr<BasicBlock>* new_blk_ptr,
     UptrVectorIterator<BasicBlock> callee_first_block_itr) {
   auto callee_itr = callee_first_block_itr->begin();
-  while (callee_itr->opcode() == SpvOp::SpvOpVariable ||
+  while (callee_itr->opcode() == spv::Op::OpVariable ||
          callee_itr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) {
-    if (callee_itr->opcode() == SpvOp::SpvOpVariable &&
+    if (callee_itr->opcode() == spv::Op::OpVariable &&
         callee_itr->NumInOperands() == 2) {
       assert(callee2caller.count(callee_itr->result_id()) &&
              "Expected the variable to have already been mapped.");
@@ -330,7 +332,8 @@
     BasicBlock* new_blk_ptr, const Instruction* inst, uint32_t dbg_inlined_at) {
   // If we have return, it must be at the end of the callee. We will handle
   // it at the end.
-  if (inst->opcode() == SpvOpReturnValue || inst->opcode() == SpvOpReturn)
+  if (inst->opcode() == spv::Op::OpReturnValue ||
+      inst->opcode() == spv::Op::OpReturn)
     return true;
 
   // Copy callee instruction and remap all input Ids.
@@ -366,7 +369,7 @@
     analysis::DebugInlinedAtContext* inlined_at_ctx, Function* calleeFn,
     const Instruction* inst, uint32_t returnVarId) {
   // Store return value to return variable.
-  if (inst->opcode() == SpvOpReturnValue) {
+  if (inst->opcode() == spv::Op::OpReturnValue) {
     assert(returnVarId != 0);
     uint32_t valId = inst->GetInOperand(kSpvReturnValueId).words[0];
     const auto mapItr = callee2caller.find(valId);
@@ -388,7 +391,8 @@
   }
   if (returnLabelId == 0) return new_blk_ptr;
 
-  if (inst->opcode() == SpvOpReturn || inst->opcode() == SpvOpReturnValue)
+  if (inst->opcode() == spv::Op::OpReturn ||
+      inst->opcode() == spv::Op::OpReturnValue)
     AddBranch(returnLabelId, &new_blk_ptr);
   new_blocks->push_back(std::move(new_blk_ptr));
   return MakeUnique<BasicBlock>(NewLabel(returnLabelId));
@@ -499,7 +503,7 @@
   // Insert a modified copy of the loop merge into the first block.
   auto loop_merge_itr = last->tail();
   --loop_merge_itr;
-  assert(loop_merge_itr->opcode() == SpvOpLoopMerge);
+  assert(loop_merge_itr->opcode() == spv::Op::OpLoopMerge);
   std::unique_ptr<Instruction> cp_inst(loop_merge_itr->Clone(context()));
   first->tail().InsertBefore(std::move(cp_inst));
 
@@ -696,7 +700,7 @@
 }
 
 bool InlinePass::IsInlinableFunctionCall(const Instruction* inst) {
-  if (inst->opcode() != SpvOp::SpvOpFunctionCall) return false;
+  if (inst->opcode() != spv::Op::OpFunctionCall) return false;
   const uint32_t calleeFnId =
       inst->GetSingleWordOperand(kSpvFunctionCallFunctionId);
   const auto ci = inlinable_.find(calleeFnId);
@@ -738,7 +742,7 @@
 bool InlinePass::HasNoReturnInLoop(Function* func) {
   // If control not structured, do not do loop/return analysis
   // TODO: Analyze returns in non-structured control flow
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return false;
   const auto structured_analysis = context()->GetStructuredCFGAnalysis();
   // Search for returns in structured construct.
@@ -776,7 +780,7 @@
   if (func->cbegin() == func->cend()) return false;
 
   // Do not inline functions with DontInline flag.
-  if (func->control_mask() & SpvFunctionControlDontInlineMask) {
+  if (func->control_mask() & uint32_t(spv::FunctionControlMask::DontInline)) {
     return false;
   }
 
@@ -794,22 +798,25 @@
     return false;
   }
 
-  // Do not inline functions with an OpKill if they are called from a continue
-  // construct. If it is inlined into a continue construct it will generate
-  // invalid code.
+  // Do not inline functions with an abort instruction if they are called from a
+  // continue construct. If it is inlined into a continue construct the backedge
+  // will no longer post-dominate the continue target, which is invalid.  An
+  // `OpUnreachable` is acceptable because it will not change post-dominance if
+  // it is statically unreachable.
   bool func_is_called_from_continue =
       funcs_called_from_continue_.count(func->result_id()) != 0;
 
-  if (func_is_called_from_continue && ContainsKillOrTerminateInvocation(func)) {
+  if (func_is_called_from_continue && ContainsAbortOtherThanUnreachable(func)) {
     return false;
   }
 
   return true;
 }
 
-bool InlinePass::ContainsKillOrTerminateInvocation(Function* func) const {
+bool InlinePass::ContainsAbortOtherThanUnreachable(Function* func) const {
   return !func->WhileEachInst([](Instruction* inst) {
-    return !spvOpcodeTerminatesExecution(inst->opcode());
+    return inst->opcode() == spv::Op::OpUnreachable ||
+           !spvOpcodeIsAbort(inst->opcode());
   });
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/inline_pass.h b/third_party/SPIRV-Tools/source/opt/inline_pass.h
index f204395..1c9d60e 100644
--- a/third_party/SPIRV-Tools/source/opt/inline_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/inline_pass.h
@@ -44,7 +44,7 @@
 
   // Add pointer to type to module and return resultId.  Returns 0 if the type
   // could not be created.
-  uint32_t AddPointerToType(uint32_t type_id, SpvStorageClass storage_class);
+  uint32_t AddPointerToType(uint32_t type_id, spv::StorageClass storage_class);
 
   // Add unconditional branch to labelId to end of block block_ptr.
   void AddBranch(uint32_t labelId, std::unique_ptr<BasicBlock>* block_ptr);
@@ -139,9 +139,9 @@
   // Return true if |func| is a function that can be inlined.
   bool IsInlinableFunction(Function* func);
 
-  // Returns true if |func| contains an OpKill or OpTerminateInvocation
-  // instruction.
-  bool ContainsKillOrTerminateInvocation(Function* func) const;
+  // Returns true if |func| contains an abort instruction that is not an
+  // `OpUnreachable` instruction.
+  bool ContainsAbortOtherThanUnreachable(Function* func) const;
 
   // Update phis in succeeding blocks to point to new last block
   void UpdateSucceedingPhis(
diff --git a/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp b/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp
index c2c5d6c..ca36dd6 100644
--- a/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp
@@ -16,31 +16,29 @@
 
 #include "inst_bindless_check_pass.h"
 
-namespace {
-
-// Input Operand Indices
-static const int kSpvImageSampleImageIdInIdx = 0;
-static const int kSpvSampledImageImageIdInIdx = 0;
-static const int kSpvSampledImageSamplerIdInIdx = 1;
-static const int kSpvImageSampledImageIdInIdx = 0;
-static const int kSpvCopyObjectOperandIdInIdx = 0;
-static const int kSpvLoadPtrIdInIdx = 0;
-static const int kSpvAccessChainBaseIdInIdx = 0;
-static const int kSpvAccessChainIndex0IdInIdx = 1;
-static const int kSpvTypeArrayTypeIdInIdx = 0;
-static const int kSpvTypeArrayLengthIdInIdx = 1;
-static const int kSpvConstantValueInIdx = 0;
-static const int kSpvVariableStorageClassInIdx = 0;
-static const int kSpvTypePtrTypeIdInIdx = 1;
-static const int kSpvTypeImageDim = 1;
-static const int kSpvTypeImageDepth = 2;
-static const int kSpvTypeImageArrayed = 3;
-static const int kSpvTypeImageMS = 4;
-static const int kSpvTypeImageSampled = 5;
-}  // anonymous namespace
-
 namespace spvtools {
 namespace opt {
+namespace {
+// Input Operand Indices
+constexpr int kSpvImageSampleImageIdInIdx = 0;
+constexpr int kSpvSampledImageImageIdInIdx = 0;
+constexpr int kSpvSampledImageSamplerIdInIdx = 1;
+constexpr int kSpvImageSampledImageIdInIdx = 0;
+constexpr int kSpvCopyObjectOperandIdInIdx = 0;
+constexpr int kSpvLoadPtrIdInIdx = 0;
+constexpr int kSpvAccessChainBaseIdInIdx = 0;
+constexpr int kSpvAccessChainIndex0IdInIdx = 1;
+constexpr int kSpvTypeArrayTypeIdInIdx = 0;
+constexpr int kSpvTypeArrayLengthIdInIdx = 1;
+constexpr int kSpvConstantValueInIdx = 0;
+constexpr int kSpvVariableStorageClassInIdx = 0;
+constexpr int kSpvTypePtrTypeIdInIdx = 1;
+constexpr int kSpvTypeImageDim = 1;
+constexpr int kSpvTypeImageDepth = 2;
+constexpr int kSpvTypeImageArrayed = 3;
+constexpr int kSpvTypeImageMS = 4;
+constexpr int kSpvTypeImageSampled = 5;
+}  // namespace
 
 uint32_t InstBindlessCheckPass::GenDebugReadLength(
     uint32_t var_id, InstructionBuilder* builder) {
@@ -79,25 +77,25 @@
     uint32_t old_image_id, InstructionBuilder* builder) {
   Instruction* new_image_inst;
   Instruction* old_image_inst = get_def_use_mgr()->GetDef(old_image_id);
-  if (old_image_inst->opcode() == SpvOpLoad) {
+  if (old_image_inst->opcode() == spv::Op::OpLoad) {
     new_image_inst = builder->AddLoad(
         old_image_inst->type_id(),
         old_image_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx));
-  } else if (old_image_inst->opcode() == SpvOp::SpvOpSampledImage) {
+  } else if (old_image_inst->opcode() == spv::Op::OpSampledImage) {
     uint32_t clone_id = CloneOriginalImage(
         old_image_inst->GetSingleWordInOperand(kSpvSampledImageImageIdInIdx),
         builder);
     new_image_inst = builder->AddBinaryOp(
-        old_image_inst->type_id(), SpvOpSampledImage, clone_id,
+        old_image_inst->type_id(), spv::Op::OpSampledImage, clone_id,
         old_image_inst->GetSingleWordInOperand(kSpvSampledImageSamplerIdInIdx));
-  } else if (old_image_inst->opcode() == SpvOp::SpvOpImage) {
+  } else if (old_image_inst->opcode() == spv::Op::OpImage) {
     uint32_t clone_id = CloneOriginalImage(
         old_image_inst->GetSingleWordInOperand(kSpvImageSampledImageIdInIdx),
         builder);
-    new_image_inst =
-        builder->AddUnaryOp(old_image_inst->type_id(), SpvOpImage, clone_id);
+    new_image_inst = builder->AddUnaryOp(old_image_inst->type_id(),
+                                         spv::Op::OpImage, clone_id);
   } else {
-    assert(old_image_inst->opcode() == SpvOp::SpvOpCopyObject &&
+    assert(old_image_inst->opcode() == spv::Op::OpCopyObject &&
            "expecting OpCopyObject");
     uint32_t clone_id = CloneOriginalImage(
         old_image_inst->GetSingleWordInOperand(kSpvCopyObjectOperandIdInIdx),
@@ -143,38 +141,38 @@
 
 uint32_t InstBindlessCheckPass::GetImageId(Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOp::SpvOpImageSampleImplicitLod:
-    case SpvOp::SpvOpImageSampleExplicitLod:
-    case SpvOp::SpvOpImageSampleDrefImplicitLod:
-    case SpvOp::SpvOpImageSampleDrefExplicitLod:
-    case SpvOp::SpvOpImageSampleProjImplicitLod:
-    case SpvOp::SpvOpImageSampleProjExplicitLod:
-    case SpvOp::SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOp::SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOp::SpvOpImageGather:
-    case SpvOp::SpvOpImageDrefGather:
-    case SpvOp::SpvOpImageQueryLod:
-    case SpvOp::SpvOpImageSparseSampleImplicitLod:
-    case SpvOp::SpvOpImageSparseSampleExplicitLod:
-    case SpvOp::SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOp::SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOp::SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOp::SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOp::SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOp::SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOp::SpvOpImageSparseGather:
-    case SpvOp::SpvOpImageSparseDrefGather:
-    case SpvOp::SpvOpImageFetch:
-    case SpvOp::SpvOpImageRead:
-    case SpvOp::SpvOpImageQueryFormat:
-    case SpvOp::SpvOpImageQueryOrder:
-    case SpvOp::SpvOpImageQuerySizeLod:
-    case SpvOp::SpvOpImageQuerySize:
-    case SpvOp::SpvOpImageQueryLevels:
-    case SpvOp::SpvOpImageQuerySamples:
-    case SpvOp::SpvOpImageSparseFetch:
-    case SpvOp::SpvOpImageSparseRead:
-    case SpvOp::SpvOpImageWrite:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageQueryLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageQueryFormat:
+    case spv::Op::OpImageQueryOrder:
+    case spv::Op::OpImageQuerySizeLod:
+    case spv::Op::OpImageQuerySize:
+    case spv::Op::OpImageQueryLevels:
+    case spv::Op::OpImageQuerySamples:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseRead:
+    case spv::Op::OpImageWrite:
       return inst->GetSingleWordInOperand(kSpvImageSampleImageIdInIdx);
     default:
       break;
@@ -190,56 +188,58 @@
 bool InstBindlessCheckPass::AnalyzeDescriptorReference(Instruction* ref_inst,
                                                        RefAnalysis* ref) {
   ref->ref_inst = ref_inst;
-  if (ref_inst->opcode() == SpvOpLoad || ref_inst->opcode() == SpvOpStore) {
+  if (ref_inst->opcode() == spv::Op::OpLoad ||
+      ref_inst->opcode() == spv::Op::OpStore) {
     ref->desc_load_id = 0;
     ref->ptr_id = ref_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx);
     Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref->ptr_id);
-    if (ptr_inst->opcode() != SpvOp::SpvOpAccessChain) return false;
+    if (ptr_inst->opcode() != spv::Op::OpAccessChain) return false;
     ref->var_id = ptr_inst->GetSingleWordInOperand(kSpvAccessChainBaseIdInIdx);
     Instruction* var_inst = get_def_use_mgr()->GetDef(ref->var_id);
-    if (var_inst->opcode() != SpvOp::SpvOpVariable) return false;
-    uint32_t storage_class =
-        var_inst->GetSingleWordInOperand(kSpvVariableStorageClassInIdx);
+    if (var_inst->opcode() != spv::Op::OpVariable) return false;
+    spv::StorageClass storage_class = spv::StorageClass(
+        var_inst->GetSingleWordInOperand(kSpvVariableStorageClassInIdx));
     switch (storage_class) {
-      case SpvStorageClassUniform:
-      case SpvStorageClassStorageBuffer:
+      case spv::StorageClass::Uniform:
+      case spv::StorageClass::StorageBuffer:
         break;
       default:
         return false;
         break;
     }
     // Check for deprecated storage block form
-    if (storage_class == SpvStorageClassUniform) {
+    if (storage_class == spv::StorageClass::Uniform) {
       uint32_t var_ty_id = var_inst->type_id();
       Instruction* var_ty_inst = get_def_use_mgr()->GetDef(var_ty_id);
       uint32_t ptr_ty_id =
           var_ty_inst->GetSingleWordInOperand(kSpvTypePtrTypeIdInIdx);
       Instruction* ptr_ty_inst = get_def_use_mgr()->GetDef(ptr_ty_id);
-      SpvOp ptr_ty_op = ptr_ty_inst->opcode();
+      spv::Op ptr_ty_op = ptr_ty_inst->opcode();
       uint32_t block_ty_id =
-          (ptr_ty_op == SpvOpTypeArray || ptr_ty_op == SpvOpTypeRuntimeArray)
+          (ptr_ty_op == spv::Op::OpTypeArray ||
+           ptr_ty_op == spv::Op::OpTypeRuntimeArray)
               ? ptr_ty_inst->GetSingleWordInOperand(kSpvTypeArrayTypeIdInIdx)
               : ptr_ty_id;
       assert(get_def_use_mgr()->GetDef(block_ty_id)->opcode() ==
-                 SpvOpTypeStruct &&
+                 spv::Op::OpTypeStruct &&
              "unexpected block type");
       bool block_found = get_decoration_mgr()->FindDecoration(
-          block_ty_id, SpvDecorationBlock,
+          block_ty_id, uint32_t(spv::Decoration::Block),
           [](const Instruction&) { return true; });
       if (!block_found) {
         // If block decoration not found, verify deprecated form of SSBO
         bool buffer_block_found = get_decoration_mgr()->FindDecoration(
-            block_ty_id, SpvDecorationBufferBlock,
+            block_ty_id, uint32_t(spv::Decoration::BufferBlock),
             [](const Instruction&) { return true; });
         USE_ASSERT(buffer_block_found && "block decoration not found");
-        storage_class = SpvStorageClassStorageBuffer;
+        storage_class = spv::StorageClass::StorageBuffer;
       }
     }
-    ref->strg_class = storage_class;
+    ref->strg_class = uint32_t(storage_class);
     Instruction* desc_type_inst = GetPointeeTypeInst(var_inst);
     switch (desc_type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
         // A load through a descriptor array will have at least 3 operands. We
         // do not want to instrument loads of descriptors here which are part of
         // an image-based reference.
@@ -261,29 +261,29 @@
   Instruction* desc_load_inst;
   for (;;) {
     desc_load_inst = get_def_use_mgr()->GetDef(desc_load_id);
-    if (desc_load_inst->opcode() == SpvOp::SpvOpSampledImage)
+    if (desc_load_inst->opcode() == spv::Op::OpSampledImage)
       desc_load_id =
           desc_load_inst->GetSingleWordInOperand(kSpvSampledImageImageIdInIdx);
-    else if (desc_load_inst->opcode() == SpvOp::SpvOpImage)
+    else if (desc_load_inst->opcode() == spv::Op::OpImage)
       desc_load_id =
           desc_load_inst->GetSingleWordInOperand(kSpvImageSampledImageIdInIdx);
-    else if (desc_load_inst->opcode() == SpvOp::SpvOpCopyObject)
+    else if (desc_load_inst->opcode() == spv::Op::OpCopyObject)
       desc_load_id =
           desc_load_inst->GetSingleWordInOperand(kSpvCopyObjectOperandIdInIdx);
     else
       break;
   }
-  if (desc_load_inst->opcode() != SpvOp::SpvOpLoad) {
+  if (desc_load_inst->opcode() != spv::Op::OpLoad) {
     // TODO(greg-lunarg): Handle additional possibilities?
     return false;
   }
   ref->desc_load_id = desc_load_id;
   ref->ptr_id = desc_load_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx);
   Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref->ptr_id);
-  if (ptr_inst->opcode() == SpvOp::SpvOpVariable) {
+  if (ptr_inst->opcode() == spv::Op::OpVariable) {
     ref->desc_idx_id = 0;
     ref->var_id = ref->ptr_id;
-  } else if (ptr_inst->opcode() == SpvOp::SpvOpAccessChain) {
+  } else if (ptr_inst->opcode() == spv::Op::OpAccessChain) {
     if (ptr_inst->NumInOperands() != 2) {
       assert(false && "unexpected bindless index number");
       return false;
@@ -292,7 +292,7 @@
         ptr_inst->GetSingleWordInOperand(kSpvAccessChainIndex0IdInIdx);
     ref->var_id = ptr_inst->GetSingleWordInOperand(kSpvAccessChainBaseIdInIdx);
     Instruction* var_inst = get_def_use_mgr()->GetDef(ref->var_id);
-    if (var_inst->opcode() != SpvOpVariable) {
+    if (var_inst->opcode() != spv::Op::OpVariable) {
       assert(false && "unexpected bindless base");
       return false;
     }
@@ -369,13 +369,13 @@
   uint32_t buff_ty_id;
   uint32_t ac_in_idx = 1;
   switch (desc_ty_inst->opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       buff_ty_id = desc_ty_inst->GetSingleWordInOperand(0);
       ++ac_in_idx;
       break;
     default:
-      assert(desc_ty_inst->opcode() == SpvOpTypeStruct &&
+      assert(desc_ty_inst->opcode() == spv::Op::OpTypeStruct &&
              "unexpected descriptor type");
       buff_ty_id = desc_ty_inst->result_id();
       break;
@@ -393,19 +393,20 @@
     Instruction* curr_ty_inst = get_def_use_mgr()->GetDef(curr_ty_id);
     uint32_t curr_offset_id = 0;
     switch (curr_ty_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray: {
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray: {
         // Get array stride and multiply by current index
-        uint32_t arr_stride = FindStride(curr_ty_id, SpvDecorationArrayStride);
+        uint32_t arr_stride =
+            FindStride(curr_ty_id, uint32_t(spv::Decoration::ArrayStride));
         uint32_t arr_stride_id = builder->GetUintConstantId(arr_stride);
         uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
         Instruction* curr_offset_inst = builder->AddBinaryOp(
-            GetUintId(), SpvOpIMul, arr_stride_id, curr_idx_32b_id);
+            GetUintId(), spv::Op::OpIMul, arr_stride_id, curr_idx_32b_id);
         curr_offset_id = curr_offset_inst->result_id();
         // Get element type for next step
         curr_ty_id = curr_ty_inst->GetSingleWordInOperand(0);
       } break;
-      case SpvOpTypeMatrix: {
+      case spv::Op::OpTypeMatrix: {
         assert(matrix_stride != 0 && "missing matrix stride");
         matrix_stride_id = builder->GetUintConstantId(matrix_stride);
         uint32_t vec_ty_id = curr_ty_inst->GetSingleWordInOperand(0);
@@ -423,40 +424,40 @@
         }
         uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
         Instruction* curr_offset_inst = builder->AddBinaryOp(
-            GetUintId(), SpvOpIMul, col_stride_id, curr_idx_32b_id);
+            GetUintId(), spv::Op::OpIMul, col_stride_id, curr_idx_32b_id);
         curr_offset_id = curr_offset_inst->result_id();
         // Get element type for next step
         curr_ty_id = vec_ty_id;
         in_matrix = true;
       } break;
-      case SpvOpTypeVector: {
+      case spv::Op::OpTypeVector: {
         // If inside a row major matrix type, multiply index by matrix stride,
         // else multiply by component size
         uint32_t comp_ty_id = curr_ty_inst->GetSingleWordInOperand(0u);
         uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
         if (in_matrix && !col_major) {
           Instruction* curr_offset_inst = builder->AddBinaryOp(
-              GetUintId(), SpvOpIMul, matrix_stride_id, curr_idx_32b_id);
+              GetUintId(), spv::Op::OpIMul, matrix_stride_id, curr_idx_32b_id);
           curr_offset_id = curr_offset_inst->result_id();
         } else {
           uint32_t comp_ty_sz = ByteSize(comp_ty_id, 0u, false, false);
           uint32_t comp_ty_sz_id = builder->GetUintConstantId(comp_ty_sz);
           Instruction* curr_offset_inst = builder->AddBinaryOp(
-              GetUintId(), SpvOpIMul, comp_ty_sz_id, curr_idx_32b_id);
+              GetUintId(), spv::Op::OpIMul, comp_ty_sz_id, curr_idx_32b_id);
           curr_offset_id = curr_offset_inst->result_id();
         }
         // Get element type for next step
         curr_ty_id = comp_ty_id;
       } break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // Get buffer byte offset for the referenced member
         Instruction* curr_idx_inst = get_def_use_mgr()->GetDef(curr_idx_id);
-        assert(curr_idx_inst->opcode() == SpvOpConstant &&
+        assert(curr_idx_inst->opcode() == spv::Op::OpConstant &&
                "unexpected struct index");
         uint32_t member_idx = curr_idx_inst->GetSingleWordInOperand(0);
         uint32_t member_offset = 0xdeadbeef;
         bool found = get_decoration_mgr()->FindDecoration(
-            curr_ty_id, SpvDecorationOffset,
+            curr_ty_id, uint32_t(spv::Decoration::Offset),
             [&member_idx, &member_offset](const Instruction& deco_inst) {
               if (deco_inst.GetSingleWordInOperand(1u) != member_idx)
                 return false;
@@ -470,7 +471,7 @@
         // enclosing struct type at the member index. If none found, reset
         // stride to 0.
         found = get_decoration_mgr()->FindDecoration(
-            curr_ty_id, SpvDecorationMatrixStride,
+            curr_ty_id, uint32_t(spv::Decoration::MatrixStride),
             [&member_idx, &matrix_stride](const Instruction& deco_inst) {
               if (deco_inst.GetSingleWordInOperand(1u) != member_idx)
                 return false;
@@ -480,7 +481,7 @@
         if (!found) matrix_stride = 0;
         // Look for column major decoration
         found = get_decoration_mgr()->FindDecoration(
-            curr_ty_id, SpvDecorationColMajor,
+            curr_ty_id, uint32_t(spv::Decoration::ColMajor),
             [&member_idx, &col_major](const Instruction& deco_inst) {
               if (deco_inst.GetSingleWordInOperand(1u) != member_idx)
                 return false;
@@ -496,8 +497,8 @@
     if (sum_id == 0)
       sum_id = curr_offset_id;
     else {
-      Instruction* sum_inst =
-          builder->AddBinaryOp(GetUintId(), SpvOpIAdd, sum_id, curr_offset_id);
+      Instruction* sum_inst = builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd,
+                                                   sum_id, curr_offset_id);
       sum_id = sum_inst->result_id();
     }
     ++ac_in_idx;
@@ -507,7 +508,7 @@
   uint32_t last = bsize - 1;
   uint32_t last_id = builder->GetUintConstantId(last);
   Instruction* sum_inst =
-      builder->AddBinaryOp(GetUintId(), SpvOpIAdd, sum_id, last_id);
+      builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, sum_id, last_id);
   return sum_inst->result_id();
 }
 
@@ -527,8 +528,9 @@
   std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
   std::unique_ptr<Instruction> valid_label(NewLabel(valid_blk_id));
   std::unique_ptr<Instruction> invalid_label(NewLabel(invalid_blk_id));
-  (void)builder.AddConditionalBranch(check_id, valid_blk_id, invalid_blk_id,
-                                     merge_blk_id, SpvSelectionControlMaskNone);
+  (void)builder.AddConditionalBranch(
+      check_id, valid_blk_id, invalid_blk_id, merge_blk_id,
+      uint32_t(spv::SelectionControlMask::MaskNone));
   // Gen valid bounds branch
   std::unique_ptr<BasicBlock> new_blk_ptr(
       new BasicBlock(std::move(valid_label)));
@@ -593,24 +595,24 @@
   RefAnalysis ref;
   if (!AnalyzeDescriptorReference(&*ref_inst_itr, &ref)) return;
   Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref.ptr_id);
-  if (ptr_inst->opcode() != SpvOp::SpvOpAccessChain) return;
+  if (ptr_inst->opcode() != spv::Op::OpAccessChain) return;
   // If index and bound both compile-time constants and index < bound,
   // return without changing
   Instruction* var_inst = get_def_use_mgr()->GetDef(ref.var_id);
   Instruction* desc_type_inst = GetPointeeTypeInst(var_inst);
   uint32_t length_id = 0;
-  if (desc_type_inst->opcode() == SpvOpTypeArray) {
+  if (desc_type_inst->opcode() == spv::Op::OpTypeArray) {
     length_id =
         desc_type_inst->GetSingleWordInOperand(kSpvTypeArrayLengthIdInIdx);
     Instruction* index_inst = get_def_use_mgr()->GetDef(ref.desc_idx_id);
     Instruction* length_inst = get_def_use_mgr()->GetDef(length_id);
-    if (index_inst->opcode() == SpvOpConstant &&
-        length_inst->opcode() == SpvOpConstant &&
+    if (index_inst->opcode() == spv::Op::OpConstant &&
+        length_inst->opcode() == spv::Op::OpConstant &&
         index_inst->GetSingleWordInOperand(kSpvConstantValueInIdx) <
             length_inst->GetSingleWordInOperand(kSpvConstantValueInIdx))
       return;
   } else if (!desc_idx_enabled_ ||
-             desc_type_inst->opcode() != SpvOpTypeRuntimeArray) {
+             desc_type_inst->opcode() != spv::Op::OpTypeRuntimeArray) {
     return;
   }
   // Move original block's preceding instructions into first new block
@@ -624,7 +626,7 @@
   // If length id not yet set, descriptor array is runtime size so
   // generate load of length from stage's debug input buffer.
   if (length_id == 0) {
-    assert(desc_type_inst->opcode() == SpvOpTypeRuntimeArray &&
+    assert(desc_type_inst->opcode() == spv::Op::OpTypeRuntimeArray &&
            "unexpected bindless type");
     length_id = GenDebugReadLength(ref.var_id, &builder);
   }
@@ -633,7 +635,7 @@
   // for the referenced value.
   uint32_t desc_idx_32b_id = Gen32BitCvtCode(ref.desc_idx_id, &builder);
   uint32_t length_32b_id = Gen32BitCvtCode(length_id, &builder);
-  Instruction* ult_inst = builder.AddBinaryOp(GetBoolId(), SpvOpULessThan,
+  Instruction* ult_inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpULessThan,
                                               desc_idx_32b_id, length_32b_id);
   ref.desc_idx_id = desc_idx_32b_id;
   GenCheckCode(ult_inst->result_id(), error_id, 0u, length_id, stage_idx, &ref,
@@ -661,9 +663,10 @@
     // TODO(greg-lunarg): Do bounds check for aggregate loads and stores
     Instruction* ref_ptr_inst = get_def_use_mgr()->GetDef(ref.ptr_id);
     Instruction* pte_type_inst = GetPointeeTypeInst(ref_ptr_inst);
-    uint32_t pte_type_op = pte_type_inst->opcode();
-    if (pte_type_op == SpvOpTypeArray || pte_type_op == SpvOpTypeRuntimeArray ||
-        pte_type_op == SpvOpTypeStruct)
+    spv::Op pte_type_op = pte_type_inst->opcode();
+    if (pte_type_op == spv::Op::OpTypeArray ||
+        pte_type_op == spv::Op::OpTypeRuntimeArray ||
+        pte_type_op == spv::Op::OpTypeStruct)
       init_check = true;
   }
   // If initialization check and not enabled, return
@@ -687,11 +690,13 @@
   // being full reference and false branch being debug output and zero
   // for the referenced value.
   Instruction* ult_inst =
-      builder.AddBinaryOp(GetBoolId(), SpvOpULessThan, ref_id, init_id);
-  uint32_t error = init_check ? kInstErrorBindlessUninit
-                              : (ref.strg_class == SpvStorageClassUniform
-                                     ? kInstErrorBuffOOBUniform
-                                     : kInstErrorBuffOOBStorage);
+      builder.AddBinaryOp(GetBoolId(), spv::Op::OpULessThan, ref_id, init_id);
+  uint32_t error =
+      init_check
+          ? kInstErrorBindlessUninit
+          : (spv::StorageClass(ref.strg_class) == spv::StorageClass::Uniform
+                 ? kInstErrorBuffOOBUniform
+                 : kInstErrorBuffOOBStorage);
   uint32_t error_id = builder.GetUintConstantId(error);
   GenCheckCode(ult_inst->result_id(), error_id, init_check ? 0 : ref_id,
                init_check ? builder.GetUintConstantId(0u) : init_id, stage_idx,
@@ -708,11 +713,11 @@
     std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
   // Only process OpImageRead and OpImageWrite with no optional operands
   Instruction* ref_inst = &*ref_inst_itr;
-  SpvOp op = ref_inst->opcode();
+  spv::Op op = ref_inst->opcode();
   uint32_t num_in_oprnds = ref_inst->NumInOperands();
-  if (!((op == SpvOpImageRead && num_in_oprnds == 2) ||
-        (op == SpvOpImageFetch && num_in_oprnds == 2) ||
-        (op == SpvOpImageWrite && num_in_oprnds == 3)))
+  if (!((op == spv::Op::OpImageRead && num_in_oprnds == 2) ||
+        (op == spv::Op::OpImageFetch && num_in_oprnds == 2) ||
+        (op == spv::Op::OpImageWrite && num_in_oprnds == 3)))
     return;
   // Pull components from descriptor reference
   RefAnalysis ref;
@@ -721,17 +726,20 @@
   Instruction* image_inst = get_def_use_mgr()->GetDef(ref.image_id);
   uint32_t image_ty_id = image_inst->type_id();
   Instruction* image_ty_inst = get_def_use_mgr()->GetDef(image_ty_id);
-  if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDim) != SpvDimBuffer)
+  if (spv::Dim(image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDim)) !=
+      spv::Dim::Buffer) {
     return;
+  }
   if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDepth) != 0) return;
   if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageArrayed) != 0) return;
   if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageMS) != 0) return;
   // Enable ImageQuery Capability if not yet enabled
-  if (!get_feature_mgr()->HasCapability(SpvCapabilityImageQuery)) {
-    std::unique_ptr<Instruction> cap_image_query_inst(new Instruction(
-        context(), SpvOpCapability, 0, 0,
-        std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityImageQuery}}}));
+  if (!get_feature_mgr()->HasCapability(spv::Capability::ImageQuery)) {
+    std::unique_ptr<Instruction> cap_image_query_inst(
+        new Instruction(context(), spv::Op::OpCapability, 0, 0,
+                        std::initializer_list<Operand>{
+                            {SPV_OPERAND_TYPE_CAPABILITY,
+                             {uint32_t(spv::Capability::ImageQuery)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*cap_image_query_inst);
     context()->AddCapability(std::move(cap_image_query_inst));
   }
@@ -750,13 +758,13 @@
   if (ref.desc_idx_id == 0) ref.desc_idx_id = builder.GetUintConstantId(0u);
   // Get texel buffer size.
   Instruction* size_inst =
-      builder.AddUnaryOp(GetUintId(), SpvOpImageQuerySize, ref.image_id);
+      builder.AddUnaryOp(GetUintId(), spv::Op::OpImageQuerySize, ref.image_id);
   uint32_t size_id = size_inst->result_id();
   // Generate runtime initialization/bounds test code with true branch
   // being full reference and false branch being debug output and zero
   // for the referenced value.
   Instruction* ult_inst =
-      builder.AddBinaryOp(GetBoolId(), SpvOpULessThan, coord_id, size_id);
+      builder.AddBinaryOp(GetBoolId(), spv::Op::OpULessThan, coord_id, size_id);
   uint32_t error =
       (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageSampled) == 2)
           ? kInstErrorBuffOOBStorageTexel
@@ -778,13 +786,16 @@
   // init check is enabled.
   if (desc_idx_enabled_ || buffer_bounds_enabled_ || texel_buffer_enabled_)
     for (auto& anno : get_module()->annotations())
-      if (anno.opcode() == SpvOpDecorate) {
-        if (anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet)
+      if (anno.opcode() == spv::Op::OpDecorate) {
+        if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+            spv::Decoration::DescriptorSet) {
           var2desc_set_[anno.GetSingleWordInOperand(0u)] =
               anno.GetSingleWordInOperand(2u);
-        else if (anno.GetSingleWordInOperand(1u) == SpvDecorationBinding)
+        } else if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+                   spv::Decoration::Binding) {
           var2binding_[anno.GetSingleWordInOperand(0u)] =
               anno.GetSingleWordInOperand(2u);
+        }
       }
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.cpp b/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.cpp
index e2336d3..be361e6 100644
--- a/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.cpp
@@ -22,9 +22,9 @@
 uint32_t InstBuffAddrCheckPass::CloneOriginalReference(
     Instruction* ref_inst, InstructionBuilder* builder) {
   // Clone original ref with new result id (if load)
-  assert(
-      (ref_inst->opcode() == SpvOpLoad || ref_inst->opcode() == SpvOpStore) &&
-      "unexpected ref");
+  assert((ref_inst->opcode() == spv::Op::OpLoad ||
+          ref_inst->opcode() == spv::Op::OpStore) &&
+         "unexpected ref");
   std::unique_ptr<Instruction> new_ref_inst(ref_inst->Clone(context()));
   uint32_t ref_result_id = ref_inst->result_id();
   uint32_t new_ref_id = 0;
@@ -41,16 +41,17 @@
 }
 
 bool InstBuffAddrCheckPass::IsPhysicalBuffAddrReference(Instruction* ref_inst) {
-  if (ref_inst->opcode() != SpvOpLoad && ref_inst->opcode() != SpvOpStore)
+  if (ref_inst->opcode() != spv::Op::OpLoad &&
+      ref_inst->opcode() != spv::Op::OpStore)
     return false;
   uint32_t ptr_id = ref_inst->GetSingleWordInOperand(0);
   analysis::DefUseManager* du_mgr = get_def_use_mgr();
   Instruction* ptr_inst = du_mgr->GetDef(ptr_id);
-  if (ptr_inst->opcode() != SpvOpAccessChain) return false;
+  if (ptr_inst->opcode() != spv::Op::OpAccessChain) return false;
   uint32_t ptr_ty_id = ptr_inst->type_id();
   Instruction* ptr_ty_inst = du_mgr->GetDef(ptr_ty_id);
-  if (ptr_ty_inst->GetSingleWordInOperand(0) !=
-      SpvStorageClassPhysicalStorageBufferEXT)
+  if (spv::StorageClass(ptr_ty_inst->GetSingleWordInOperand(0)) !=
+      spv::StorageClass::PhysicalStorageBufferEXT)
     return false;
   return true;
 }
@@ -72,8 +73,9 @@
   std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
   std::unique_ptr<Instruction> valid_label(NewLabel(valid_blk_id));
   std::unique_ptr<Instruction> invalid_label(NewLabel(invalid_blk_id));
-  (void)builder.AddConditionalBranch(check_id, valid_blk_id, invalid_blk_id,
-                                     merge_blk_id, SpvSelectionControlMaskNone);
+  (void)builder.AddConditionalBranch(
+      check_id, valid_blk_id, invalid_blk_id, merge_blk_id,
+      uint32_t(spv::SelectionControlMask::MaskNone));
   // Gen valid branch
   std::unique_ptr<BasicBlock> new_blk_ptr(
       new BasicBlock(std::move(valid_label)));
@@ -86,12 +88,12 @@
   builder.SetInsertPoint(&*new_blk_ptr);
   // Convert uptr from uint64 to 2 uint32
   Instruction* lo_uptr_inst =
-      builder.AddUnaryOp(GetUintId(), SpvOpUConvert, ref_uptr_id);
+      builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, ref_uptr_id);
   Instruction* rshift_uptr_inst =
-      builder.AddBinaryOp(GetUint64Id(), SpvOpShiftRightLogical, ref_uptr_id,
-                          builder.GetUintConstantId(32));
-  Instruction* hi_uptr_inst = builder.AddUnaryOp(GetUintId(), SpvOpUConvert,
-                                                 rshift_uptr_inst->result_id());
+      builder.AddBinaryOp(GetUint64Id(), spv::Op::OpShiftRightLogical,
+                          ref_uptr_id, builder.GetUintConstantId(32));
+  Instruction* hi_uptr_inst = builder.AddUnaryOp(
+      GetUintId(), spv::Op::OpUConvert, rshift_uptr_inst->result_id());
   GenDebugStreamWrite(
       uid2offset_[ref_inst->unique_id()], stage_idx,
       {error_id, lo_uptr_inst->result_id(), hi_uptr_inst->result_id()},
@@ -105,8 +107,8 @@
     analysis::Type* ref_type = type_mgr->GetType(ref_type_id);
     if (ref_type->AsPointer() != nullptr) {
       uint32_t null_u64_id = GetNullId(GetUint64Id());
-      Instruction* null_ptr_inst =
-          builder.AddUnaryOp(ref_type_id, SpvOpConvertUToPtr, null_u64_id);
+      Instruction* null_ptr_inst = builder.AddUnaryOp(
+          ref_type_id, spv::Op::OpConvertUToPtr, null_u64_id);
       null_id = null_ptr_inst->result_id();
     } else {
       null_id = GetNullId(ref_type_id);
@@ -133,16 +135,16 @@
 uint32_t InstBuffAddrCheckPass::GetTypeAlignment(uint32_t type_id) {
   Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
   switch (type_inst->opcode()) {
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeVector:
       return GetTypeLength(type_id);
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       return GetTypeAlignment(type_inst->GetSingleWordInOperand(0));
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       return GetTypeAlignment(type_inst->GetSingleWordInOperand(0));
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       uint32_t max = 0;
       type_inst->ForEachInId([&max, this](const uint32_t* iid) {
         uint32_t alignment = GetTypeAlignment(*iid);
@@ -150,9 +152,9 @@
       });
       return max;
     }
-    case SpvOpTypePointer:
-      assert(type_inst->GetSingleWordInOperand(0) ==
-                 SpvStorageClassPhysicalStorageBufferEXT &&
+    case spv::Op::OpTypePointer:
+      assert(spv::StorageClass(type_inst->GetSingleWordInOperand(0)) ==
+                 spv::StorageClass::PhysicalStorageBufferEXT &&
              "unexpected pointer type");
       return 8u;
     default:
@@ -164,29 +166,29 @@
 uint32_t InstBuffAddrCheckPass::GetTypeLength(uint32_t type_id) {
   Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
   switch (type_inst->opcode()) {
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
       return type_inst->GetSingleWordInOperand(0) / 8u;
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       uint32_t raw_cnt = type_inst->GetSingleWordInOperand(1);
       uint32_t adj_cnt = (raw_cnt == 3u) ? 4u : raw_cnt;
       return adj_cnt * GetTypeLength(type_inst->GetSingleWordInOperand(0));
     }
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       return type_inst->GetSingleWordInOperand(1) *
              GetTypeLength(type_inst->GetSingleWordInOperand(0));
-    case SpvOpTypePointer:
-      assert(type_inst->GetSingleWordInOperand(0) ==
-                 SpvStorageClassPhysicalStorageBufferEXT &&
+    case spv::Op::OpTypePointer:
+      assert(spv::StorageClass(type_inst->GetSingleWordInOperand(0)) ==
+                 spv::StorageClass::PhysicalStorageBufferEXT &&
              "unexpected pointer type");
       return 8u;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       uint32_t const_id = type_inst->GetSingleWordInOperand(1);
       Instruction* const_inst = get_def_use_mgr()->GetDef(const_id);
       uint32_t cnt = const_inst->GetSingleWordInOperand(0);
       return cnt * GetTypeLength(type_inst->GetSingleWordInOperand(0));
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       uint32_t len = 0;
       type_inst->ForEachInId([&len, this](const uint32_t* iid) {
         // Align struct length
@@ -200,7 +202,7 @@
       });
       return len;
     }
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
     default:
       assert(false && "unexpected type");
       return 0;
@@ -213,7 +215,7 @@
   uint32_t pid = TakeNextId();
   param_vec->push_back(pid);
   std::unique_ptr<Instruction> param_inst(new Instruction(
-      get_module()->context(), SpvOpFunctionParameter, type_id, pid, {}));
+      get_module()->context(), spv::Op::OpFunctionParameter, type_id, pid, {}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
   (*input_func)->AddParameter(std::move(param_inst));
 }
@@ -231,10 +233,10 @@
     analysis::Function func_ty(type_mgr->GetType(GetBoolId()), param_types);
     analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
     std::unique_ptr<Instruction> func_inst(
-        new Instruction(get_module()->context(), SpvOpFunction, GetBoolId(),
-                        search_test_func_id_,
+        new Instruction(get_module()->context(), spv::Op::OpFunction,
+                        GetBoolId(), search_test_func_id_,
                         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                          {SpvFunctionControlMaskNone}},
+                          {uint32_t(spv::FunctionControlMask::MaskNone)}},
                          {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
                           {type_mgr->GetTypeInstruction(reg_func_ty)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
@@ -256,7 +258,7 @@
     // Branch to search loop header
     std::unique_ptr<Instruction> hdr_blk_label(NewLabel(hdr_blk_id));
     (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpBranch, 0, 0,
+        context(), spv::Op::OpBranch, 0, 0,
         std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {hdr_blk_id}}}));
     input_func->AddBasicBlock(std::move(first_blk_ptr));
     // Linear search loop header block
@@ -273,12 +275,12 @@
     uint32_t idx_phi_id = TakeNextId();
     uint32_t idx_inc_id = TakeNextId();
     std::unique_ptr<Instruction> idx_inc_inst(new Instruction(
-        context(), SpvOpIAdd, GetUintId(), idx_inc_id,
+        context(), spv::Op::OpIAdd, GetUintId(), idx_inc_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {idx_phi_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
           {builder.GetUintConstantId(1u)}}}));
     std::unique_ptr<Instruction> idx_phi_inst(new Instruction(
-        context(), SpvOpPhi, GetUintId(), idx_phi_id,
+        context(), spv::Op::OpPhi, GetUintId(), idx_phi_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
           {builder.GetUintConstantId(1u)}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {first_blk_id}},
@@ -292,14 +294,15 @@
     std::unique_ptr<Instruction> bound_test_blk_label(
         NewLabel(bound_test_blk_id));
     (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpLoopMerge, 0, 0,
+        context(), spv::Op::OpLoopMerge, 0, 0,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {bound_test_blk_id}},
             {SPV_OPERAND_TYPE_ID, {cont_blk_id}},
-            {SPV_OPERAND_TYPE_LITERAL_INTEGER, {SpvLoopControlMaskNone}}}));
+            {SPV_OPERAND_TYPE_LITERAL_INTEGER,
+             {uint32_t(spv::LoopControlMask::MaskNone)}}}));
     // Branch to continue/work block
     (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpBranch, 0, 0,
+        context(), spv::Op::OpBranch, 0, 0,
         std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_blk_id}}}));
     input_func->AddBasicBlock(std::move(hdr_blk_ptr));
     // Continue/Work Block. Read next buffer pointer and break if greater
@@ -313,19 +316,19 @@
     uint32_t ibuf_id = GetInputBufferId();
     uint32_t ibuf_ptr_id = GetInputBufferPtrId();
     Instruction* uptr_ac_inst = builder.AddTernaryOp(
-        ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
+        ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
         builder.GetUintConstantId(kDebugInputDataOffset), idx_inc_id);
     uint32_t ibuf_type_id = GetInputBufferTypeId();
-    Instruction* uptr_load_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, uptr_ac_inst->result_id());
+    Instruction* uptr_load_inst = builder.AddUnaryOp(
+        ibuf_type_id, spv::Op::OpLoad, uptr_ac_inst->result_id());
     // If loaded address greater than ref_ptr arg, break, else branch back to
     // loop header
     Instruction* uptr_test_inst =
-        builder.AddBinaryOp(GetBoolId(), SpvOpUGreaterThan,
+        builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThan,
                             uptr_load_inst->result_id(), param_vec[0]);
-    (void)builder.AddConditionalBranch(uptr_test_inst->result_id(),
-                                       bound_test_blk_id, hdr_blk_id,
-                                       kInvalidId, SpvSelectionControlMaskNone);
+    (void)builder.AddConditionalBranch(
+        uptr_test_inst->result_id(), bound_test_blk_id, hdr_blk_id, kInvalidId,
+        uint32_t(spv::SelectionControlMask::MaskNone));
     input_func->AddBasicBlock(std::move(cont_blk_ptr));
     // Bounds test block. Read length of selected buffer and test that
     // all len arg bytes are in buffer.
@@ -333,66 +336,70 @@
         MakeUnique<BasicBlock>(std::move(bound_test_blk_label));
     builder.SetInsertPoint(&*bound_test_blk_ptr);
     // Decrement index to point to previous/candidate buffer address
-    Instruction* cand_idx_inst = builder.AddBinaryOp(
-        GetUintId(), SpvOpISub, idx_inc_id, builder.GetUintConstantId(1u));
+    Instruction* cand_idx_inst =
+        builder.AddBinaryOp(GetUintId(), spv::Op::OpISub, idx_inc_id,
+                            builder.GetUintConstantId(1u));
     // Load candidate buffer address
     Instruction* cand_ac_inst =
-        builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
+        builder.AddTernaryOp(ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
                              builder.GetUintConstantId(kDebugInputDataOffset),
                              cand_idx_inst->result_id());
-    Instruction* cand_load_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, cand_ac_inst->result_id());
+    Instruction* cand_load_inst = builder.AddUnaryOp(
+        ibuf_type_id, spv::Op::OpLoad, cand_ac_inst->result_id());
     // Compute offset of ref_ptr from candidate buffer address
-    Instruction* offset_inst = builder.AddBinaryOp(
-        ibuf_type_id, SpvOpISub, param_vec[0], cand_load_inst->result_id());
+    Instruction* offset_inst =
+        builder.AddBinaryOp(ibuf_type_id, spv::Op::OpISub, param_vec[0],
+                            cand_load_inst->result_id());
     // Convert ref length to uint64
     Instruction* ref_len_64_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpUConvert, param_vec[1]);
+        builder.AddUnaryOp(ibuf_type_id, spv::Op::OpUConvert, param_vec[1]);
     // Add ref length to ref offset to compute end of reference
-    Instruction* ref_end_inst =
-        builder.AddBinaryOp(ibuf_type_id, SpvOpIAdd, offset_inst->result_id(),
-                            ref_len_64_inst->result_id());
+    Instruction* ref_end_inst = builder.AddBinaryOp(
+        ibuf_type_id, spv::Op::OpIAdd, offset_inst->result_id(),
+        ref_len_64_inst->result_id());
     // Load starting index of lengths in input buffer and convert to uint32
     Instruction* len_start_ac_inst =
-        builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
+        builder.AddTernaryOp(ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
                              builder.GetUintConstantId(kDebugInputDataOffset),
                              builder.GetUintConstantId(0u));
     Instruction* len_start_load_inst = builder.AddUnaryOp(
-        ibuf_type_id, SpvOpLoad, len_start_ac_inst->result_id());
+        ibuf_type_id, spv::Op::OpLoad, len_start_ac_inst->result_id());
     Instruction* len_start_32_inst = builder.AddUnaryOp(
-        GetUintId(), SpvOpUConvert, len_start_load_inst->result_id());
+        GetUintId(), spv::Op::OpUConvert, len_start_load_inst->result_id());
     // Decrement search index to get candidate buffer length index
-    Instruction* cand_len_idx_inst =
-        builder.AddBinaryOp(GetUintId(), SpvOpISub, cand_idx_inst->result_id(),
-                            builder.GetUintConstantId(1u));
+    Instruction* cand_len_idx_inst = builder.AddBinaryOp(
+        GetUintId(), spv::Op::OpISub, cand_idx_inst->result_id(),
+        builder.GetUintConstantId(1u));
     // Add candidate length index to start index
     Instruction* len_idx_inst = builder.AddBinaryOp(
-        GetUintId(), SpvOpIAdd, cand_len_idx_inst->result_id(),
+        GetUintId(), spv::Op::OpIAdd, cand_len_idx_inst->result_id(),
         len_start_32_inst->result_id());
     // Load candidate buffer length
     Instruction* len_ac_inst =
-        builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
+        builder.AddTernaryOp(ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
                              builder.GetUintConstantId(kDebugInputDataOffset),
                              len_idx_inst->result_id());
-    Instruction* len_load_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, len_ac_inst->result_id());
+    Instruction* len_load_inst = builder.AddUnaryOp(
+        ibuf_type_id, spv::Op::OpLoad, len_ac_inst->result_id());
     // Test if reference end within candidate buffer length
     Instruction* len_test_inst = builder.AddBinaryOp(
-        GetBoolId(), SpvOpULessThanEqual, ref_end_inst->result_id(),
+        GetBoolId(), spv::Op::OpULessThanEqual, ref_end_inst->result_id(),
         len_load_inst->result_id());
     // Return test result
     (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpReturnValue, 0, 0,
+        context(), spv::Op::OpReturnValue, 0, 0,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {len_test_inst->result_id()}}}));
     // Close block
     input_func->AddBasicBlock(std::move(bound_test_blk_ptr));
     // Close function and add function to module
-    std::unique_ptr<Instruction> func_end_inst(
-        new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
+    std::unique_ptr<Instruction> func_end_inst(new Instruction(
+        get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
     input_func->SetFunctionEnd(std::move(func_end_inst));
     context()->AddFunction(std::move(input_func));
+    context()->AddDebug2Inst(
+        NewGlobalName(search_test_func_id_, "search_and_test"));
   }
   return search_test_func_id_;
 }
@@ -401,18 +408,18 @@
                                                  InstructionBuilder* builder,
                                                  uint32_t* ref_uptr_id) {
   // Enable Int64 if necessary
-  if (!get_feature_mgr()->HasCapability(SpvCapabilityInt64)) {
+  if (!get_feature_mgr()->HasCapability(spv::Capability::Int64)) {
     std::unique_ptr<Instruction> cap_int64_inst(new Instruction(
-        context(), SpvOpCapability, 0, 0,
-        std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityInt64}}}));
+        context(), spv::Op::OpCapability, 0, 0,
+        std::initializer_list<Operand>{{SPV_OPERAND_TYPE_CAPABILITY,
+                                        {uint32_t(spv::Capability::Int64)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*cap_int64_inst);
     context()->AddCapability(std::move(cap_int64_inst));
   }
   // Convert reference pointer to uint64
   uint32_t ref_ptr_id = ref_inst->GetSingleWordInOperand(0);
   Instruction* ref_uptr_inst =
-      builder->AddUnaryOp(GetUint64Id(), SpvOpConvertPtrToU, ref_ptr_id);
+      builder->AddUnaryOp(GetUint64Id(), spv::Op::OpConvertPtrToU, ref_ptr_id);
   *ref_uptr_id = ref_uptr_inst->result_id();
   // Compute reference length in bytes
   analysis::DefUseManager* du_mgr = get_def_use_mgr();
@@ -425,7 +432,7 @@
   const std::vector<uint32_t> args = {GetSearchAndTestFuncId(), *ref_uptr_id,
                                       ref_len_id};
   Instruction* call_inst =
-      builder->AddNaryOp(GetBoolId(), SpvOpFunctionCall, args);
+      builder->AddNaryOp(GetBoolId(), spv::Op::OpFunctionCall, args);
   uint32_t retval = call_inst->result_id();
   return retval;
 }
@@ -483,7 +490,7 @@
 
 Pass::Status InstBuffAddrCheckPass::Process() {
   if (!get_feature_mgr()->HasCapability(
-          SpvCapabilityPhysicalStorageBufferAddressesEXT))
+          spv::Capability::PhysicalStorageBufferAddressesEXT))
     return Status::SuccessWithoutChange;
   InitInstBuffAddrCheck();
   return ProcessImpl();
diff --git a/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.h b/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.h
index a823223..fb43c39 100644
--- a/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.h
@@ -39,7 +39,7 @@
   // See optimizer.hpp for pass user documentation.
   Status Process() override;
 
-  const char* name() const override { return "inst-bindless-check-pass"; }
+  const char* name() const override { return "inst-buff-addr-check-pass"; }
 
  private:
   // Return byte alignment of type |type_id|. Must be int, float, vector,
diff --git a/third_party/SPIRV-Tools/source/opt/inst_debug_printf_pass.cpp b/third_party/SPIRV-Tools/source/opt/inst_debug_printf_pass.cpp
index 4218138..151b94c 100644
--- a/third_party/SPIRV-Tools/source/opt/inst_debug_printf_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/inst_debug_printf_pass.cpp
@@ -35,7 +35,7 @@
       uint32_t c_ty_id = type_mgr->GetId(c_ty);
       for (uint32_t c = 0; c < v_ty->element_count(); ++c) {
         Instruction* c_inst = builder->AddIdLiteralOp(
-            c_ty_id, SpvOpCompositeExtract, val_inst->result_id(), c);
+            c_ty_id, spv::Op::OpCompositeExtract, val_inst->result_id(), c);
         GenOutputValues(c_inst, val_ids, builder);
       }
       return;
@@ -44,8 +44,9 @@
       // Select between uint32 zero or one
       uint32_t zero_id = builder->GetUintConstantId(0);
       uint32_t one_id = builder->GetUintConstantId(1);
-      Instruction* sel_inst = builder->AddTernaryOp(
-          GetUintId(), SpvOpSelect, val_inst->result_id(), one_id, zero_id);
+      Instruction* sel_inst =
+          builder->AddTernaryOp(GetUintId(), spv::Op::OpSelect,
+                                val_inst->result_id(), one_id, zero_id);
       val_ids->push_back(sel_inst->result_id());
       return;
     }
@@ -55,21 +56,21 @@
         case 16: {
           // Convert float16 to float32 and recurse
           Instruction* f32_inst = builder->AddUnaryOp(
-              GetFloatId(), SpvOpFConvert, val_inst->result_id());
+              GetFloatId(), spv::Op::OpFConvert, val_inst->result_id());
           GenOutputValues(f32_inst, val_ids, builder);
           return;
         }
         case 64: {
           // Bitcast float64 to uint64 and recurse
           Instruction* ui64_inst = builder->AddUnaryOp(
-              GetUint64Id(), SpvOpBitcast, val_inst->result_id());
+              GetUint64Id(), spv::Op::OpBitcast, val_inst->result_id());
           GenOutputValues(ui64_inst, val_ids, builder);
           return;
         }
         case 32: {
           // Bitcase float32 to uint32
-          Instruction* bc_inst = builder->AddUnaryOp(GetUintId(), SpvOpBitcast,
-                                                     val_inst->result_id());
+          Instruction* bc_inst = builder->AddUnaryOp(
+              GetUintId(), spv::Op::OpBitcast, val_inst->result_id());
           val_ids->push_back(bc_inst->result_id());
           return;
         }
@@ -85,17 +86,17 @@
           Instruction* ui64_inst = val_inst;
           if (i_ty->IsSigned()) {
             // Bitcast sint64 to uint64
-            ui64_inst = builder->AddUnaryOp(GetUint64Id(), SpvOpBitcast,
+            ui64_inst = builder->AddUnaryOp(GetUint64Id(), spv::Op::OpBitcast,
                                             val_inst->result_id());
           }
           // Break uint64 into 2x uint32
           Instruction* lo_ui64_inst = builder->AddUnaryOp(
-              GetUintId(), SpvOpUConvert, ui64_inst->result_id());
+              GetUintId(), spv::Op::OpUConvert, ui64_inst->result_id());
           Instruction* rshift_ui64_inst = builder->AddBinaryOp(
-              GetUint64Id(), SpvOpShiftRightLogical, ui64_inst->result_id(),
-              builder->GetUintConstantId(32));
+              GetUint64Id(), spv::Op::OpShiftRightLogical,
+              ui64_inst->result_id(), builder->GetUintConstantId(32));
           Instruction* hi_ui64_inst = builder->AddUnaryOp(
-              GetUintId(), SpvOpUConvert, rshift_ui64_inst->result_id());
+              GetUintId(), spv::Op::OpUConvert, rshift_ui64_inst->result_id());
           val_ids->push_back(lo_ui64_inst->result_id());
           val_ids->push_back(hi_ui64_inst->result_id());
           return;
@@ -104,12 +105,12 @@
           Instruction* ui8_inst = val_inst;
           if (i_ty->IsSigned()) {
             // Bitcast sint8 to uint8
-            ui8_inst = builder->AddUnaryOp(GetUint8Id(), SpvOpBitcast,
+            ui8_inst = builder->AddUnaryOp(GetUint8Id(), spv::Op::OpBitcast,
                                            val_inst->result_id());
           }
           // Convert uint8 to uint32
           Instruction* ui32_inst = builder->AddUnaryOp(
-              GetUintId(), SpvOpUConvert, ui8_inst->result_id());
+              GetUintId(), spv::Op::OpUConvert, ui8_inst->result_id());
           val_ids->push_back(ui32_inst->result_id());
           return;
         }
@@ -117,7 +118,7 @@
           Instruction* ui32_inst = val_inst;
           if (i_ty->IsSigned()) {
             // Bitcast sint32 to uint32
-            ui32_inst = builder->AddUnaryOp(GetUintId(), SpvOpBitcast,
+            ui32_inst = builder->AddUnaryOp(GetUintId(), spv::Op::OpBitcast,
                                             val_inst->result_id());
           }
           // uint32 needs no further processing
@@ -158,7 +159,7 @@
           return;
         }
         Instruction* opnd_inst = get_def_use_mgr()->GetDef(*iid);
-        if (opnd_inst->opcode() == SpvOpString) {
+        if (opnd_inst->opcode() == spv::Op::OpString) {
           uint32_t string_id_id = builder.GetUintConstantId(*iid);
           val_ids.push_back(string_id_id);
         } else {
@@ -176,7 +177,7 @@
     std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
   // If not DebugPrintf OpExtInst, return.
   Instruction* printf_inst = &*ref_inst_itr;
-  if (printf_inst->opcode() != SpvOpExtInst) return;
+  if (printf_inst->opcode() != spv::Op::OpExtInst) return;
   if (printf_inst->GetSingleWordInOperand(0) != ext_inst_printf_id_) return;
   if (printf_inst->GetSingleWordInOperand(1) !=
       NonSemanticDebugPrintfDebugPrintf)
diff --git a/third_party/SPIRV-Tools/source/opt/instruction.cpp b/third_party/SPIRV-Tools/source/opt/instruction.cpp
index 6a8daea..ab3ca0f 100644
--- a/third_party/SPIRV-Tools/source/opt/instruction.cpp
+++ b/third_party/SPIRV-Tools/source/opt/instruction.cpp
@@ -24,38 +24,37 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
 // Indices used to get particular operands out of instructions using InOperand.
-const uint32_t kTypeImageDimIndex = 1;
-const uint32_t kLoadBaseIndex = 0;
-const uint32_t kPointerTypeStorageClassIndex = 0;
-const uint32_t kVariableStorageClassIndex = 0;
-const uint32_t kTypeImageSampledIndex = 5;
+constexpr uint32_t kTypeImageDimIndex = 1;
+constexpr uint32_t kLoadBaseIndex = 0;
+constexpr uint32_t kPointerTypeStorageClassIndex = 0;
+constexpr uint32_t kVariableStorageClassIndex = 0;
+constexpr uint32_t kTypeImageSampledIndex = 5;
 
 // Constants for OpenCL.DebugInfo.100 / NonSemantic.Shader.DebugInfo.100
 // extension instructions.
-const uint32_t kExtInstSetIdInIdx = 0;
-const uint32_t kExtInstInstructionInIdx = 1;
-const uint32_t kDebugScopeNumWords = 7;
-const uint32_t kDebugScopeNumWordsWithoutInlinedAt = 6;
-const uint32_t kDebugNoScopeNumWords = 5;
+constexpr uint32_t kExtInstSetIdInIdx = 0;
+constexpr uint32_t kExtInstInstructionInIdx = 1;
+constexpr uint32_t kDebugScopeNumWords = 7;
+constexpr uint32_t kDebugScopeNumWordsWithoutInlinedAt = 6;
+constexpr uint32_t kDebugNoScopeNumWords = 5;
 
 // Number of operands of an OpBranchConditional instruction
 // with weights.
-const uint32_t kOpBranchConditionalWithWeightsNumOperands = 5;
+constexpr uint32_t kOpBranchConditionalWithWeightsNumOperands = 5;
 }  // namespace
 
 Instruction::Instruction(IRContext* c)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
-      opcode_(SpvOpNop),
+      opcode_(spv::Op::OpNop),
       has_type_id_(false),
       has_result_id_(false),
       unique_id_(c->TakeNextUniqueId()),
       dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
-Instruction::Instruction(IRContext* c, SpvOp op)
+Instruction::Instruction(IRContext* c, spv::Op op)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
       opcode_(op),
@@ -68,7 +67,7 @@
                          std::vector<Instruction>&& dbg_line)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
-      opcode_(static_cast<SpvOp>(inst.opcode)),
+      opcode_(static_cast<spv::Op>(inst.opcode)),
       has_type_id_(inst.type_id != 0),
       has_result_id_(inst.result_id != 0),
       unique_id_(c->TakeNextUniqueId()),
@@ -88,7 +87,7 @@
                          const DebugScope& dbg_scope)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
-      opcode_(static_cast<SpvOp>(inst.opcode)),
+      opcode_(static_cast<spv::Op>(inst.opcode)),
       has_type_id_(inst.type_id != 0),
       has_result_id_(inst.result_id != 0),
       unique_id_(c->TakeNextUniqueId()),
@@ -101,7 +100,7 @@
   }
 }
 
-Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
+Instruction::Instruction(IRContext* c, spv::Op op, uint32_t ty_id,
                          uint32_t res_id, const OperandList& in_operands)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
@@ -179,7 +178,7 @@
 }
 
 bool Instruction::HasBranchWeights() const {
-  if (opcode_ == SpvOpBranchConditional &&
+  if (opcode_ == spv::Op::OpBranchConditional &&
       NumOperands() == kOpBranchConditionalWithWeightsNumOperands) {
     return true;
   }
@@ -208,13 +207,13 @@
       return false;
     }
 
-    if (address_def->opcode() == SpvOpVariable) {
+    if (address_def->opcode() == spv::Op::OpVariable) {
       if (address_def->IsReadOnlyPointer()) {
         return true;
       }
     }
 
-    if (address_def->opcode() == SpvOpLoad) {
+    if (address_def->opcode() == spv::Op::OpLoad) {
       const analysis::Type* address_type =
           context()->get_type_mgr()->GetType(address_def->type_id());
       if (address_type->AsSampledImage() != nullptr) {
@@ -235,12 +234,12 @@
   bool done = false;
   while (!done) {
     switch (base_inst->opcode()) {
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
-      case SpvOpPtrAccessChain:
-      case SpvOpInBoundsPtrAccessChain:
-      case SpvOpImageTexelPointer:
-      case SpvOpCopyObject:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
+      case spv::Op::OpPtrAccessChain:
+      case spv::Op::OpInBoundsPtrAccessChain:
+      case spv::Op::OpImageTexelPointer:
+      case spv::Op::OpCopyObject:
         // All of these instructions have the base pointer use a base pointer
         // in in-operand 0.
         base = base_inst->GetSingleWordInOperand(0);
@@ -255,20 +254,20 @@
 }
 
 bool Instruction::IsReadOnlyPointer() const {
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return IsReadOnlyPointerShaders();
   else
     return IsReadOnlyPointerKernel();
 }
 
 bool Instruction::IsVulkanStorageImage() const {
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class != SpvStorageClassUniformConstant) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class != spv::StorageClass::UniformConstant) {
     return false;
   }
 
@@ -276,17 +275,18 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeImage) {
+  if (base_type->opcode() != spv::Op::OpTypeImage) {
     return false;
   }
 
-  if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) == SpvDimBuffer) {
+  if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) ==
+      spv::Dim::Buffer) {
     return false;
   }
 
@@ -296,13 +296,13 @@
 }
 
 bool Instruction::IsVulkanSampledImage() const {
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class != SpvStorageClassUniformConstant) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class != spv::StorageClass::UniformConstant) {
     return false;
   }
 
@@ -310,17 +310,18 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeImage) {
+  if (base_type->opcode() != spv::Op::OpTypeImage) {
     return false;
   }
 
-  if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) == SpvDimBuffer) {
+  if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) ==
+      spv::Dim::Buffer) {
     return false;
   }
 
@@ -330,13 +331,13 @@
 }
 
 bool Instruction::IsVulkanStorageTexelBuffer() const {
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class != SpvStorageClassUniformConstant) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class != spv::StorageClass::UniformConstant) {
     return false;
   }
 
@@ -344,17 +345,18 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeImage) {
+  if (base_type->opcode() != spv::Op::OpTypeImage) {
     return false;
   }
 
-  if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) != SpvDimBuffer) {
+  if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) !=
+      spv::Dim::Buffer) {
     return false;
   }
 
@@ -366,7 +368,7 @@
 bool Instruction::IsVulkanStorageBuffer() const {
   // Is there a difference between a "Storage buffer" and a "dynamic storage
   // buffer" in SPIR-V and do we care about the difference?
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
@@ -374,28 +376,28 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeStruct) {
+  if (base_type->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class == SpvStorageClassUniform) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class == spv::StorageClass::Uniform) {
     bool is_buffer_block = false;
     context()->get_decoration_mgr()->ForEachDecoration(
-        base_type->result_id(), SpvDecorationBufferBlock,
+        base_type->result_id(), uint32_t(spv::Decoration::BufferBlock),
         [&is_buffer_block](const Instruction&) { is_buffer_block = true; });
     return is_buffer_block;
-  } else if (storage_class == SpvStorageClassStorageBuffer) {
+  } else if (storage_class == spv::StorageClass::StorageBuffer) {
     bool is_block = false;
     context()->get_decoration_mgr()->ForEachDecoration(
-        base_type->result_id(), SpvDecorationBlock,
+        base_type->result_id(), uint32_t(spv::Decoration::Block),
         [&is_block](const Instruction&) { is_block = true; });
     return is_block;
   }
@@ -403,13 +405,14 @@
 }
 
 bool Instruction::IsVulkanStorageBufferVariable() const {
-  if (opcode() != SpvOpVariable) {
+  if (opcode() != spv::Op::OpVariable) {
     return false;
   }
 
-  uint32_t storage_class = GetSingleWordInOperand(kVariableStorageClassIndex);
-  if (storage_class == SpvStorageClassStorageBuffer ||
-      storage_class == SpvStorageClassUniform) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kVariableStorageClassIndex));
+  if (storage_class == spv::StorageClass::StorageBuffer ||
+      storage_class == spv::StorageClass::Uniform) {
     Instruction* var_type = context()->get_def_use_mgr()->GetDef(type_id());
     return var_type != nullptr && var_type->IsVulkanStorageBuffer();
   }
@@ -418,13 +421,13 @@
 }
 
 bool Instruction::IsVulkanUniformBuffer() const {
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class != SpvStorageClassUniform) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class != spv::StorageClass::Uniform) {
     return false;
   }
 
@@ -432,19 +435,19 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeStruct) {
+  if (base_type->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
   bool is_block = false;
   context()->get_decoration_mgr()->ForEachDecoration(
-      base_type->result_id(), SpvDecorationBlock,
+      base_type->result_id(), uint32_t(spv::Decoration::Block),
       [&is_block](const Instruction&) { is_block = true; });
   return is_block;
 }
@@ -455,27 +458,27 @@
   }
 
   Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
-  if (type_def->opcode() != SpvOpTypePointer) {
+  if (type_def->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex);
+  spv::StorageClass storage_class = spv::StorageClass(
+      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex));
 
   switch (storage_class) {
-    case SpvStorageClassUniformConstant:
+    case spv::StorageClass::UniformConstant:
       if (!type_def->IsVulkanStorageImage() &&
           !type_def->IsVulkanStorageTexelBuffer()) {
         return true;
       }
       break;
-    case SpvStorageClassUniform:
+    case spv::StorageClass::Uniform:
       if (!type_def->IsVulkanStorageBuffer()) {
         return true;
       }
       break;
-    case SpvStorageClassPushConstant:
-    case SpvStorageClassInput:
+    case spv::StorageClass::PushConstant:
+    case spv::StorageClass::Input:
       return true;
     default:
       break;
@@ -483,7 +486,7 @@
 
   bool is_nonwritable = false;
   context()->get_decoration_mgr()->ForEachDecoration(
-      result_id(), SpvDecorationNonWritable,
+      result_id(), uint32_t(spv::Decoration::NonWritable),
       [&is_nonwritable](const Instruction&) { is_nonwritable = true; });
   return is_nonwritable;
 }
@@ -494,34 +497,14 @@
   }
 
   Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
-  if (type_def->opcode() != SpvOpTypePointer) {
+  if (type_def->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex);
+  spv::StorageClass storage_class = spv::StorageClass(
+      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex));
 
-  return storage_class == SpvStorageClassUniformConstant;
-}
-
-uint32_t Instruction::GetTypeComponent(uint32_t element) const {
-  uint32_t subtype = 0;
-  switch (opcode()) {
-    case SpvOpTypeStruct:
-      subtype = GetSingleWordInOperand(element);
-      break;
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-      // These types all have uniform subtypes.
-      subtype = GetSingleWordInOperand(0u);
-      break;
-    default:
-      break;
-  }
-
-  return subtype;
+  return storage_class == spv::StorageClass::UniformConstant;
 }
 
 void Instruction::UpdateLexicalScope(uint32_t scope) {
@@ -584,13 +567,13 @@
 bool Instruction::IsLineInst() const { return IsLine() || IsNoLine(); }
 
 bool Instruction::IsLine() const {
-  if (opcode() == SpvOpLine) return true;
+  if (opcode() == spv::Op::OpLine) return true;
   NonSemanticShaderDebugInfo100Instructions ext_opt = GetShader100DebugOpcode();
   return ext_opt == NonSemanticShaderDebugInfo100DebugLine;
 }
 
 bool Instruction::IsNoLine() const {
-  if (opcode() == SpvOpNoLine) return true;
+  if (opcode() == spv::Op::OpNoLine) return true;
   NonSemanticShaderDebugInfo100Instructions ext_opt = GetShader100DebugOpcode();
   return ext_opt == NonSemanticShaderDebugInfo100DebugNoLine;
 }
@@ -617,33 +600,35 @@
   }
 
   Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
-  if (type->opcode() != SpvOpTypePointer) {
+  if (type->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
   auto feature_mgr = context()->get_feature_mgr();
-  if (feature_mgr->HasCapability(SpvCapabilityAddresses)) {
+  if (feature_mgr->HasCapability(spv::Capability::Addresses)) {
     // TODO: The rules here could be more restrictive.
     return true;
   }
 
-  if (opcode() == SpvOpVariable || opcode() == SpvOpFunctionParameter) {
+  if (opcode() == spv::Op::OpVariable ||
+      opcode() == spv::Op::OpFunctionParameter) {
     return true;
   }
 
   // With variable pointers, there are more valid base pointer objects.
   // Variable pointers implicitly declares Variable pointers storage buffer.
-  SpvStorageClass storage_class =
-      static_cast<SpvStorageClass>(type->GetSingleWordInOperand(0));
-  if ((feature_mgr->HasCapability(SpvCapabilityVariablePointersStorageBuffer) &&
-       storage_class == SpvStorageClassStorageBuffer) ||
-      (feature_mgr->HasCapability(SpvCapabilityVariablePointers) &&
-       storage_class == SpvStorageClassWorkgroup)) {
+  spv::StorageClass storage_class =
+      static_cast<spv::StorageClass>(type->GetSingleWordInOperand(0));
+  if ((feature_mgr->HasCapability(
+           spv::Capability::VariablePointersStorageBuffer) &&
+       storage_class == spv::StorageClass::StorageBuffer) ||
+      (feature_mgr->HasCapability(spv::Capability::VariablePointers) &&
+       storage_class == spv::StorageClass::Workgroup)) {
     switch (opcode()) {
-      case SpvOpPhi:
-      case SpvOpSelect:
-      case SpvOpFunctionCall:
-      case SpvOpConstantNull:
+      case spv::Op::OpPhi:
+      case spv::Op::OpSelect:
+      case spv::Op::OpFunctionCall:
+      case spv::Op::OpConstantNull:
         return true;
       default:
         break;
@@ -661,7 +646,7 @@
 }
 
 OpenCLDebugInfo100Instructions Instruction::GetOpenCL100DebugOpcode() const {
-  if (opcode() != SpvOpExtInst) {
+  if (opcode() != spv::Op::OpExtInst) {
     return OpenCLDebugInfo100InstructionsMax;
   }
 
@@ -680,7 +665,7 @@
 
 NonSemanticShaderDebugInfo100Instructions Instruction::GetShader100DebugOpcode()
     const {
-  if (opcode() != SpvOpExtInst) {
+  if (opcode() != spv::Op::OpExtInst) {
     return NonSemanticShaderDebugInfo100InstructionsMax;
   }
 
@@ -702,7 +687,7 @@
 }
 
 CommonDebugInfoInstructions Instruction::GetCommonDebugOpcode() const {
-  if (opcode() != SpvOpExtInst) {
+  if (opcode() != spv::Op::OpExtInst) {
     return CommonDebugInfoInstructionsMax;
   }
 
@@ -732,25 +717,25 @@
   }
 
   Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
-  return (type->opcode() == SpvOpTypeImage ||
-          type->opcode() == SpvOpTypeSampledImage);
+  return (type->opcode() == spv::Op::OpTypeImage ||
+          type->opcode() == spv::Op::OpTypeSampledImage);
 }
 
 bool Instruction::IsOpaqueType() const {
-  if (opcode() == SpvOpTypeStruct) {
+  if (opcode() == spv::Op::OpTypeStruct) {
     bool is_opaque = false;
     ForEachInOperand([&is_opaque, this](const uint32_t* op_id) {
       Instruction* type_inst = context()->get_def_use_mgr()->GetDef(*op_id);
       is_opaque |= type_inst->IsOpaqueType();
     });
     return is_opaque;
-  } else if (opcode() == SpvOpTypeArray) {
+  } else if (opcode() == spv::Op::OpTypeArray) {
     uint32_t sub_type_id = GetSingleWordInOperand(0);
     Instruction* sub_type_inst =
         context()->get_def_use_mgr()->GetDef(sub_type_id);
     return sub_type_inst->IsOpaqueType();
   } else {
-    return opcode() == SpvOpTypeRuntimeArray ||
+    return opcode() == spv::Op::OpTypeRuntimeArray ||
            spvOpcodeIsBaseOpaqueType(opcode());
   }
 }
@@ -785,22 +770,23 @@
 bool Instruction::IsFloatingPointFoldingAllowed() const {
   // TODO: Add the rules for kernels.  For now it will be pessimistic.
   // For now, do not support capabilities introduced by SPV_KHR_float_controls.
-  if (!context_->get_feature_mgr()->HasCapability(SpvCapabilityShader) ||
-      context_->get_feature_mgr()->HasCapability(SpvCapabilityDenormPreserve) ||
+  if (!context_->get_feature_mgr()->HasCapability(spv::Capability::Shader) ||
       context_->get_feature_mgr()->HasCapability(
-          SpvCapabilityDenormFlushToZero) ||
+          spv::Capability::DenormPreserve) ||
       context_->get_feature_mgr()->HasCapability(
-          SpvCapabilitySignedZeroInfNanPreserve) ||
+          spv::Capability::DenormFlushToZero) ||
       context_->get_feature_mgr()->HasCapability(
-          SpvCapabilityRoundingModeRTZ) ||
+          spv::Capability::SignedZeroInfNanPreserve) ||
       context_->get_feature_mgr()->HasCapability(
-          SpvCapabilityRoundingModeRTE)) {
+          spv::Capability::RoundingModeRTZ) ||
+      context_->get_feature_mgr()->HasCapability(
+          spv::Capability::RoundingModeRTE)) {
     return false;
   }
 
   bool is_nocontract = false;
   context_->get_decoration_mgr()->WhileEachDecoration(
-      result_id(), SpvDecorationNoContraction,
+      result_id(), uint32_t(spv::Decoration::NoContraction),
       [&is_nocontract](const Instruction&) {
         is_nocontract = true;
         return false;
@@ -836,101 +822,101 @@
 
 bool Instruction::IsOpcodeCodeMotionSafe() const {
   switch (opcode_) {
-    case SpvOpNop:
-    case SpvOpUndef:
-    case SpvOpLoad:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpArrayLength:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpSizeOf:
+    case spv::Op::OpNop:
+    case spv::Op::OpUndef:
+    case spv::Op::OpLoad:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpArrayLength:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpSizeOf:
       return true;
     default:
       return false;
@@ -942,7 +928,7 @@
     return true;
   }
 
-  if (opcode() == SpvOpExtInst) {
+  if (opcode() == spv::Op::OpExtInst) {
     uint32_t instSetId =
         context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
 
@@ -1017,16 +1003,16 @@
   }
 
   switch (opcode()) {
-    case SpvOpDPdx:
-    case SpvOpDPdy:
-    case SpvOpFwidth:
-    case SpvOpDPdxFine:
-    case SpvOpDPdyFine:
-    case SpvOpFwidthFine:
-    case SpvOpDPdxCoarse:
-    case SpvOpDPdyCoarse:
-    case SpvOpFwidthCoarse:
-    case SpvOpImageQueryLod:
+    case spv::Op::OpDPdx:
+    case spv::Op::OpDPdy:
+    case spv::Op::OpFwidth:
+    case spv::Op::OpDPdxFine:
+    case spv::Op::OpDPdyFine:
+    case spv::Op::OpFwidthFine:
+    case spv::Op::OpDPdxCoarse:
+    case spv::Op::OpDPdyCoarse:
+    case spv::Op::OpFwidthCoarse:
+    case spv::Op::OpImageQueryLod:
       return true;
     default:
       return false;
@@ -1035,7 +1021,7 @@
 
 bool Instruction::IsNonSemanticInstruction() const {
   if (!HasResultId()) return false;
-  if (opcode() != SpvOpExtInst) return false;
+  if (opcode() != spv::Op::OpExtInst) return false;
 
   auto import_inst =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(0));
@@ -1055,7 +1041,7 @@
     num_words = kDebugScopeNumWordsWithoutInlinedAt;
   }
   std::vector<uint32_t> operands = {
-      (num_words << 16) | static_cast<uint16_t>(SpvOpExtInst),
+      (num_words << 16) | static_cast<uint16_t>(spv::Op::OpExtInst),
       type_id,
       result_id,
       ext_set,
diff --git a/third_party/SPIRV-Tools/source/opt/instruction.h b/third_party/SPIRV-Tools/source/opt/instruction.h
index 2163d99..22736bf 100644
--- a/third_party/SPIRV-Tools/source/opt/instruction.h
+++ b/third_party/SPIRV-Tools/source/opt/instruction.h
@@ -36,8 +36,8 @@
 #include "source/util/string_utils.h"
 #include "spirv-tools/libspirv.h"
 
-const uint32_t kNoDebugScope = 0;
-const uint32_t kNoInlinedAt = 0;
+constexpr uint32_t kNoDebugScope = 0;
+constexpr uint32_t kNoInlinedAt = 0;
 
 namespace spvtools {
 namespace opt {
@@ -190,7 +190,7 @@
   Instruction()
       : utils::IntrusiveNodeBase<Instruction>(),
         context_(nullptr),
-        opcode_(SpvOpNop),
+        opcode_(spv::Op::OpNop),
         has_type_id_(false),
         has_result_id_(false),
         unique_id_(0),
@@ -200,7 +200,7 @@
   Instruction(IRContext*);
   // Creates an instruction with the given opcode |op| and no additional logical
   // operands.
-  Instruction(IRContext*, SpvOp);
+  Instruction(IRContext*, spv::Op);
   // Creates an instruction using the given spv_parsed_instruction_t |inst|. All
   // the data inside |inst| will be copied and owned in this instance. And keep
   // record of line-related debug instructions |dbg_line| ahead of this
@@ -213,7 +213,7 @@
 
   // Creates an instruction with the given opcode |op|, type id: |ty_id|,
   // result id: |res_id| and input operands: |in_operands|.
-  Instruction(IRContext* c, SpvOp op, uint32_t ty_id, uint32_t res_id,
+  Instruction(IRContext* c, spv::Op op, uint32_t ty_id, uint32_t res_id,
               const OperandList& in_operands);
 
   // TODO: I will want to remove these, but will first have to remove the use of
@@ -235,12 +235,12 @@
 
   IRContext* context() const { return context_; }
 
-  SpvOp opcode() const { return opcode_; }
+  spv::Op opcode() const { return opcode_; }
   // Sets the opcode of this instruction to a specific opcode. Note this may
   // invalidate the instruction.
   // TODO(qining): Remove this function when instruction building and insertion
   // is well implemented.
-  void SetOpcode(SpvOp op) { opcode_ = op; }
+  void SetOpcode(spv::Op op) { opcode_ = op; }
   uint32_t type_id() const {
     return has_type_id_ ? GetSingleWordOperand(0) : 0;
   }
@@ -504,10 +504,6 @@
   // Returns true if this instruction exits this function or aborts execution.
   bool IsReturnOrAbort() const { return spvOpcodeIsReturnOrAbort(opcode()); }
 
-  // Returns the id for the |element|'th subtype. If the |this| is not a
-  // composite type, this function returns 0.
-  uint32_t GetTypeComponent(uint32_t element) const;
-
   // Returns true if this instruction is a basic block terminator.
   bool IsBlockTerminator() const {
     return spvOpcodeIsBlockTerminator(opcode());
@@ -629,7 +625,7 @@
   bool IsValidBaseImage() const;
 
   IRContext* context_;  // IR Context
-  SpvOp opcode_;        // Opcode
+  spv::Op opcode_;      // Opcode
   bool has_type_id_;    // True if the instruction has a type id
   bool has_result_id_;  // True if the instruction has a result id
   uint32_t unique_id_;  // Unique instruction id
@@ -736,12 +732,12 @@
 }
 
 inline bool Instruction::IsNop() const {
-  return opcode_ == SpvOpNop && !has_type_id_ && !has_result_id_ &&
+  return opcode_ == spv::Op::OpNop && !has_type_id_ && !has_result_id_ &&
          operands_.empty();
 }
 
 inline void Instruction::ToNop() {
-  opcode_ = SpvOpNop;
+  opcode_ = spv::Op::OpNop;
   has_type_id_ = false;
   has_result_id_ = false;
   operands_.clear();
@@ -883,12 +879,12 @@
 
 inline bool Instruction::HasLabels() const {
   switch (opcode_) {
-    case SpvOpSelectionMerge:
-    case SpvOpBranch:
-    case SpvOpLoopMerge:
-    case SpvOpBranchConditional:
-    case SpvOpSwitch:
-    case SpvOpPhi:
+    case spv::Op::OpSelectionMerge:
+    case spv::Op::OpBranch:
+    case spv::Op::OpLoopMerge:
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch:
+    case spv::Op::OpPhi:
       return true;
       break;
     default:
diff --git a/third_party/SPIRV-Tools/source/opt/instrument_pass.cpp b/third_party/SPIRV-Tools/source/opt/instrument_pass.cpp
index ed34fb0..441d943 100644
--- a/third_party/SPIRV-Tools/source/opt/instrument_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/instrument_pass.cpp
@@ -19,20 +19,15 @@
 #include "source/cfa.h"
 #include "source/spirv_constant.h"
 
-namespace {
-
-// Common Parameter Positions
-static const int kInstCommonParamInstIdx = 0;
-static const int kInstCommonParamCnt = 1;
-
-// Indices of operands in SPIR-V instructions
-static const int kEntryPointExecutionModelInIdx = 0;
-static const int kEntryPointFunctionIdInIdx = 1;
-
-}  // anonymous namespace
-
 namespace spvtools {
 namespace opt {
+namespace {
+// Common Parameter Positions
+constexpr int kInstCommonParamInstIdx = 0;
+constexpr int kInstCommonParamCnt = 1;
+// Indices of operands in SPIR-V instructions
+constexpr int kEntryPointFunctionIdInIdx = 1;
+}  // namespace
 
 void InstrumentPass::MovePreludeCode(
     BasicBlock::iterator ref_inst_itr,
@@ -83,11 +78,56 @@
 
 std::unique_ptr<Instruction> InstrumentPass::NewLabel(uint32_t label_id) {
   std::unique_ptr<Instruction> newLabel(
-      new Instruction(context(), SpvOpLabel, 0, label_id, {}));
+      new Instruction(context(), spv::Op::OpLabel, 0, label_id, {}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*newLabel);
   return newLabel;
 }
 
+std::unique_ptr<Instruction> InstrumentPass::NewName(
+    uint32_t id, const std::string& name_str) {
+  std::unique_ptr<Instruction> new_name(new Instruction(
+      context(), spv::Op::OpName, 0, 0,
+      std::initializer_list<Operand>{
+          {SPV_OPERAND_TYPE_ID, {id}},
+          {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}));
+
+  return new_name;
+}
+
+std::unique_ptr<Instruction> InstrumentPass::NewGlobalName(
+    uint32_t id, const std::string& name_str) {
+  std::string prefixed_name;
+  switch (validation_id_) {
+    case kInstValidationIdBindless:
+      prefixed_name = "inst_bindless_";
+      break;
+    case kInstValidationIdBuffAddr:
+      prefixed_name = "inst_buff_addr_";
+      break;
+    case kInstValidationIdDebugPrintf:
+      prefixed_name = "inst_printf_";
+      break;
+    default:
+      assert(false);  // add new instrumentation pass here
+      prefixed_name = "inst_pass_";
+      break;
+  }
+  prefixed_name += name_str;
+  return NewName(id, prefixed_name);
+}
+
+std::unique_ptr<Instruction> InstrumentPass::NewMemberName(
+    uint32_t id, uint32_t member_index, const std::string& name_str) {
+  std::unique_ptr<Instruction> new_name(new Instruction(
+      context(), spv::Op::OpMemberName, 0, 0,
+      std::initializer_list<Operand>{
+          {SPV_OPERAND_TYPE_ID, {id}},
+          {SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index}},
+          {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}));
+
+  return new_name;
+}
+
 uint32_t InstrumentPass::Gen32BitCvtCode(uint32_t val_id,
                                          InstructionBuilder* builder) {
   // Convert integer value to 32-bit if necessary
@@ -100,10 +140,10 @@
   analysis::Type* val_32b_reg_ty = type_mgr->GetRegisteredType(&val_32b_ty);
   uint32_t val_32b_reg_ty_id = type_mgr->GetId(val_32b_reg_ty);
   if (is_signed)
-    return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpSConvert, val_id)
+    return builder->AddUnaryOp(val_32b_reg_ty_id, spv::Op::OpSConvert, val_id)
         ->result_id();
   else
-    return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpUConvert, val_id)
+    return builder->AddUnaryOp(val_32b_reg_ty_id, spv::Op::OpUConvert, val_id)
         ->result_id();
 }
 
@@ -116,7 +156,7 @@
   uint32_t val_ty_id = get_def_use_mgr()->GetDef(val_32b_id)->type_id();
   analysis::Integer* val_ty = type_mgr->GetType(val_ty_id)->AsInteger();
   if (!val_ty->IsSigned()) return val_32b_id;
-  return builder->AddUnaryOp(GetUintId(), SpvOpBitcast, val_32b_id)
+  return builder->AddUnaryOp(GetUintId(), spv::Op::OpBitcast, val_32b_id)
       ->result_id();
 }
 
@@ -128,15 +168,16 @@
   uint32_t val_id = GenUintCastCode(field_value_id, builder);
   // Store value
   Instruction* data_idx_inst =
-      builder->AddBinaryOp(GetUintId(), SpvOpIAdd, base_offset_id,
+      builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, base_offset_id,
                            builder->GetUintConstantId(field_offset));
   uint32_t buf_id = GetOutputBufferId();
   uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
   Instruction* achain_inst =
-      builder->AddTernaryOp(buf_uint_ptr_id, SpvOpAccessChain, buf_id,
+      builder->AddTernaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id,
                             builder->GetUintConstantId(kDebugOutputDataOffset),
                             data_idx_inst->result_id());
-  (void)builder->AddBinaryOp(0, SpvOpStore, achain_inst->result_id(), val_id);
+  (void)builder->AddBinaryOp(0, spv::Op::OpStore, achain_inst->result_id(),
+                             val_id);
 }
 
 void InstrumentPass::GenCommonStreamWriteCode(uint32_t record_sz,
@@ -162,7 +203,7 @@
     uint32_t base_offset_id, uint32_t uint_frag_coord_id, uint32_t element,
     InstructionBuilder* builder) {
   Instruction* element_val_inst = builder->AddIdLiteralOp(
-      GetUintId(), SpvOpCompositeExtract, uint_frag_coord_id, element);
+      GetUintId(), spv::Op::OpCompositeExtract, uint_frag_coord_id, element);
   GenDebugOutputFieldCode(base_offset_id, kInstFragOutFragCoordX + element,
                           element_val_inst->result_id(), builder);
 }
@@ -171,7 +212,8 @@
                                     InstructionBuilder* builder) {
   Instruction* var_inst = get_def_use_mgr()->GetDef(var_id);
   uint32_t type_id = GetPointeeTypeId(var_inst);
-  Instruction* load_inst = builder->AddUnaryOp(type_id, SpvOpLoad, var_id);
+  Instruction* load_inst =
+      builder->AddUnaryOp(type_id, spv::Op::OpLoad, var_id);
   return load_inst->result_id();
 }
 
@@ -188,29 +230,31 @@
                                              uint32_t base_offset_id,
                                              InstructionBuilder* builder) {
   // TODO(greg-lunarg): Add support for all stages
-  switch (stage_idx) {
-    case SpvExecutionModelVertex: {
+  switch (spv::ExecutionModel(stage_idx)) {
+    case spv::ExecutionModel::Vertex: {
       // Load and store VertexId and InstanceId
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInVertexIndex),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::VertexIndex)),
           kInstVertOutVertexIndex, base_offset_id, builder);
-      GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInInstanceIndex),
-          kInstVertOutInstanceIndex, base_offset_id, builder);
+      GenBuiltinOutputCode(context()->GetBuiltinInputVarId(
+                               uint32_t(spv::BuiltIn::InstanceIndex)),
+                           kInstVertOutInstanceIndex, base_offset_id, builder);
     } break;
-    case SpvExecutionModelGLCompute:
-    case SpvExecutionModelTaskNV:
-    case SpvExecutionModelMeshNV: {
+    case spv::ExecutionModel::GLCompute:
+    case spv::ExecutionModel::TaskNV:
+    case spv::ExecutionModel::MeshNV:
+    case spv::ExecutionModel::TaskEXT:
+    case spv::ExecutionModel::MeshEXT: {
       // Load and store GlobalInvocationId.
-      uint32_t load_id = GenVarLoad(
-          context()->GetBuiltinInputVarId(SpvBuiltInGlobalInvocationId),
-          builder);
+      uint32_t load_id = GenVarLoad(context()->GetBuiltinInputVarId(uint32_t(
+                                        spv::BuiltIn::GlobalInvocationId)),
+                                    builder);
       Instruction* x_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, load_id, 0);
+          GetUintId(), spv::Op::OpCompositeExtract, load_id, 0);
       Instruction* y_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, load_id, 1);
+          GetUintId(), spv::Op::OpCompositeExtract, load_id, 1);
       Instruction* z_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, load_id, 2);
+          GetUintId(), spv::Op::OpCompositeExtract, load_id, 2);
       GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdX,
                               x_inst->result_id(), builder);
       GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdY,
@@ -218,69 +262,71 @@
       GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdZ,
                               z_inst->result_id(), builder);
     } break;
-    case SpvExecutionModelGeometry: {
+    case spv::ExecutionModel::Geometry: {
       // Load and store PrimitiveId and InvocationId.
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
           kInstGeomOutPrimitiveId, base_offset_id, builder);
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInInvocationId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::InvocationId)),
           kInstGeomOutInvocationId, base_offset_id, builder);
     } break;
-    case SpvExecutionModelTessellationControl: {
+    case spv::ExecutionModel::TessellationControl: {
       // Load and store InvocationId and PrimitiveId
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInInvocationId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::InvocationId)),
           kInstTessCtlOutInvocationId, base_offset_id, builder);
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
           kInstTessCtlOutPrimitiveId, base_offset_id, builder);
     } break;
-    case SpvExecutionModelTessellationEvaluation: {
+    case spv::ExecutionModel::TessellationEvaluation: {
       // Load and store PrimitiveId and TessCoord.uv
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
           kInstTessEvalOutPrimitiveId, base_offset_id, builder);
       uint32_t load_id = GenVarLoad(
-          context()->GetBuiltinInputVarId(SpvBuiltInTessCoord), builder);
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::TessCoord)),
+          builder);
       Instruction* uvec3_cast_inst =
-          builder->AddUnaryOp(GetVec3UintId(), SpvOpBitcast, load_id);
+          builder->AddUnaryOp(GetVec3UintId(), spv::Op::OpBitcast, load_id);
       uint32_t uvec3_cast_id = uvec3_cast_inst->result_id();
       Instruction* u_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 0);
+          GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 0);
       Instruction* v_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 1);
+          GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 1);
       GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordU,
                               u_inst->result_id(), builder);
       GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordV,
                               v_inst->result_id(), builder);
     } break;
-    case SpvExecutionModelFragment: {
+    case spv::ExecutionModel::Fragment: {
       // Load FragCoord and convert to Uint
       Instruction* frag_coord_inst = builder->AddUnaryOp(
-          GetVec4FloatId(), SpvOpLoad,
-          context()->GetBuiltinInputVarId(SpvBuiltInFragCoord));
+          GetVec4FloatId(), spv::Op::OpLoad,
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::FragCoord)));
       Instruction* uint_frag_coord_inst = builder->AddUnaryOp(
-          GetVec4UintId(), SpvOpBitcast, frag_coord_inst->result_id());
+          GetVec4UintId(), spv::Op::OpBitcast, frag_coord_inst->result_id());
       for (uint32_t u = 0; u < 2u; ++u)
         GenFragCoordEltDebugOutputCode(
             base_offset_id, uint_frag_coord_inst->result_id(), u, builder);
     } break;
-    case SpvExecutionModelRayGenerationNV:
-    case SpvExecutionModelIntersectionNV:
-    case SpvExecutionModelAnyHitNV:
-    case SpvExecutionModelClosestHitNV:
-    case SpvExecutionModelMissNV:
-    case SpvExecutionModelCallableNV: {
+    case spv::ExecutionModel::RayGenerationNV:
+    case spv::ExecutionModel::IntersectionNV:
+    case spv::ExecutionModel::AnyHitNV:
+    case spv::ExecutionModel::ClosestHitNV:
+    case spv::ExecutionModel::MissNV:
+    case spv::ExecutionModel::CallableNV: {
       // Load and store LaunchIdNV.
       uint32_t launch_id = GenVarLoad(
-          context()->GetBuiltinInputVarId(SpvBuiltInLaunchIdNV), builder);
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::LaunchIdNV)),
+          builder);
       Instruction* x_launch_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, launch_id, 0);
+          GetUintId(), spv::Op::OpCompositeExtract, launch_id, 0);
       Instruction* y_launch_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, launch_id, 1);
+          GetUintId(), spv::Op::OpCompositeExtract, launch_id, 1);
       Instruction* z_launch_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, launch_id, 2);
+          GetUintId(), spv::Op::OpCompositeExtract, launch_id, 2);
       GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdX,
                               x_launch_inst->result_id(), builder);
       GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdY,
@@ -302,7 +348,7 @@
   std::vector<uint32_t> args = {output_func_id,
                                 builder->GetUintConstantId(instruction_idx)};
   (void)args.insert(args.end(), validation_ids.begin(), validation_ids.end());
-  (void)builder->AddNaryOp(GetVoidId(), SpvOpFunctionCall, args);
+  (void)builder->AddNaryOp(GetVoidId(), spv::Op::OpFunctionCall, args);
 }
 
 bool InstrumentPass::AllConstant(const std::vector<uint32_t>& ids) {
@@ -338,13 +384,15 @@
     builder.SetInsertPoint(insert_before);
   }
   uint32_t res_id =
-      builder.AddNaryOp(GetUintId(), SpvOpFunctionCall, args)->result_id();
+      builder.AddNaryOp(GetUintId(), spv::Op::OpFunctionCall, args)
+          ->result_id();
   if (insert_in_first_block) call2id_[args] = res_id;
   return res_id;
 }
 
 bool InstrumentPass::IsSameBlockOp(const Instruction* inst) const {
-  return inst->opcode() == SpvOpSampledImage || inst->opcode() == SpvOpImage;
+  return inst->opcode() == spv::Op::OpSampledImage ||
+         inst->opcode() == spv::Op::OpImage;
 }
 
 void InstrumentPass::CloneSameBlockOps(
@@ -410,7 +458,7 @@
 uint32_t InstrumentPass::GetOutputBufferPtrId() {
   if (output_buffer_ptr_id_ == 0) {
     output_buffer_ptr_id_ = context()->get_type_mgr()->FindPointerToType(
-        GetUintId(), SpvStorageClassStorageBuffer);
+        GetUintId(), spv::StorageClass::StorageBuffer);
   }
   return output_buffer_ptr_id_;
 }
@@ -423,7 +471,7 @@
 uint32_t InstrumentPass::GetInputBufferPtrId() {
   if (input_buffer_ptr_id_ == 0) {
     input_buffer_ptr_id_ = context()->get_type_mgr()->FindPointerToType(
-        GetInputBufferTypeId(), SpvStorageClassStorageBuffer);
+        GetInputBufferTypeId(), spv::StorageClass::StorageBuffer);
   }
   return input_buffer_ptr_id_;
 }
@@ -472,8 +520,8 @@
     // invalidated after this pass.
     assert(context()->get_def_use_mgr()->NumUses(uint_arr_ty_id) == 0 &&
            "used RuntimeArray type returned");
-    deco_mgr->AddDecorationVal(uint_arr_ty_id, SpvDecorationArrayStride,
-                               width / 8u);
+    deco_mgr->AddDecorationVal(
+        uint_arr_ty_id, uint32_t(spv::Decoration::ArrayStride), width / 8u);
   }
   return *rarr_ty;
 }
@@ -501,7 +549,7 @@
     analysis::Type* reg_uint_rarr_ty = GetUintRuntimeArrayType(32);
     analysis::Integer uint_ty(32, false);
     analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
-    analysis::Struct buf_ty({reg_uint_ty, reg_uint_rarr_ty});
+    analysis::Struct buf_ty({reg_uint_ty, reg_uint_ty, reg_uint_rarr_ty});
     analysis::Type* reg_buf_ty = type_mgr->GetRegisteredType(&buf_ty);
     uint32_t obufTyId = type_mgr->GetTypeInstruction(reg_buf_ty);
     // By the Vulkan spec, a pre-existing struct containing a RuntimeArray
@@ -512,22 +560,30 @@
     // invalidated after this pass.
     assert(context()->get_def_use_mgr()->NumUses(obufTyId) == 0 &&
            "used struct type returned");
-    deco_mgr->AddDecoration(obufTyId, SpvDecorationBlock);
+    deco_mgr->AddDecoration(obufTyId, uint32_t(spv::Decoration::Block));
+    deco_mgr->AddMemberDecoration(obufTyId, kDebugOutputFlagsOffset,
+                                  uint32_t(spv::Decoration::Offset), 0);
     deco_mgr->AddMemberDecoration(obufTyId, kDebugOutputSizeOffset,
-                                  SpvDecorationOffset, 0);
+                                  uint32_t(spv::Decoration::Offset), 4);
     deco_mgr->AddMemberDecoration(obufTyId, kDebugOutputDataOffset,
-                                  SpvDecorationOffset, 4);
+                                  uint32_t(spv::Decoration::Offset), 8);
     uint32_t obufTyPtrId_ =
-        type_mgr->FindPointerToType(obufTyId, SpvStorageClassStorageBuffer);
+        type_mgr->FindPointerToType(obufTyId, spv::StorageClass::StorageBuffer);
     output_buffer_id_ = TakeNextId();
     std::unique_ptr<Instruction> newVarOp(new Instruction(
-        context(), SpvOpVariable, obufTyPtrId_, output_buffer_id_,
+        context(), spv::Op::OpVariable, obufTyPtrId_, output_buffer_id_,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-          {SpvStorageClassStorageBuffer}}}));
+          {uint32_t(spv::StorageClass::StorageBuffer)}}}));
     context()->AddGlobalValue(std::move(newVarOp));
-    deco_mgr->AddDecorationVal(output_buffer_id_, SpvDecorationDescriptorSet,
-                               desc_set_);
-    deco_mgr->AddDecorationVal(output_buffer_id_, SpvDecorationBinding,
+    context()->AddDebug2Inst(NewGlobalName(obufTyId, "OutputBuffer"));
+    context()->AddDebug2Inst(NewMemberName(obufTyId, 0, "flags"));
+    context()->AddDebug2Inst(NewMemberName(obufTyId, 1, "written_count"));
+    context()->AddDebug2Inst(NewMemberName(obufTyId, 2, "data"));
+    context()->AddDebug2Inst(NewGlobalName(output_buffer_id_, "output_buffer"));
+    deco_mgr->AddDecorationVal(
+        output_buffer_id_, uint32_t(spv::Decoration::DescriptorSet), desc_set_);
+    deco_mgr->AddDecorationVal(output_buffer_id_,
+                               uint32_t(spv::Decoration::Binding),
                                GetOutputBufferBinding());
     AddStorageBufferExt();
     if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
@@ -559,19 +615,24 @@
     // invalidated after this pass.
     assert(context()->get_def_use_mgr()->NumUses(ibufTyId) == 0 &&
            "used struct type returned");
-    deco_mgr->AddDecoration(ibufTyId, SpvDecorationBlock);
-    deco_mgr->AddMemberDecoration(ibufTyId, 0, SpvDecorationOffset, 0);
+    deco_mgr->AddDecoration(ibufTyId, uint32_t(spv::Decoration::Block));
+    deco_mgr->AddMemberDecoration(ibufTyId, 0,
+                                  uint32_t(spv::Decoration::Offset), 0);
     uint32_t ibufTyPtrId_ =
-        type_mgr->FindPointerToType(ibufTyId, SpvStorageClassStorageBuffer);
+        type_mgr->FindPointerToType(ibufTyId, spv::StorageClass::StorageBuffer);
     input_buffer_id_ = TakeNextId();
     std::unique_ptr<Instruction> newVarOp(new Instruction(
-        context(), SpvOpVariable, ibufTyPtrId_, input_buffer_id_,
+        context(), spv::Op::OpVariable, ibufTyPtrId_, input_buffer_id_,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-          {SpvStorageClassStorageBuffer}}}));
+          {uint32_t(spv::StorageClass::StorageBuffer)}}}));
     context()->AddGlobalValue(std::move(newVarOp));
-    deco_mgr->AddDecorationVal(input_buffer_id_, SpvDecorationDescriptorSet,
-                               desc_set_);
-    deco_mgr->AddDecorationVal(input_buffer_id_, SpvDecorationBinding,
+    context()->AddDebug2Inst(NewGlobalName(ibufTyId, "InputBuffer"));
+    context()->AddDebug2Inst(NewMemberName(ibufTyId, 0, "data"));
+    context()->AddDebug2Inst(NewGlobalName(input_buffer_id_, "input_buffer"));
+    deco_mgr->AddDecorationVal(
+        input_buffer_id_, uint32_t(spv::Decoration::DescriptorSet), desc_set_);
+    deco_mgr->AddDecorationVal(input_buffer_id_,
+                               uint32_t(spv::Decoration::Binding),
                                GetInputBufferBinding());
     AddStorageBufferExt();
     if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
@@ -692,10 +753,10 @@
     analysis::Function func_ty(type_mgr->GetType(GetVoidId()), param_types);
     analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
     std::unique_ptr<Instruction> func_inst(
-        new Instruction(get_module()->context(), SpvOpFunction, GetVoidId(),
-                        param2output_func_id_[param_cnt],
+        new Instruction(get_module()->context(), spv::Op::OpFunction,
+                        GetVoidId(), param2output_func_id_[param_cnt],
                         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                          {SpvFunctionControlMaskNone}},
+                          {uint32_t(spv::FunctionControlMask::MaskNone)}},
                          {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
                           {type_mgr->GetTypeInstruction(reg_func_ty)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
@@ -707,7 +768,7 @@
       uint32_t pid = TakeNextId();
       param_vec.push_back(pid);
       std::unique_ptr<Instruction> param_inst(
-          new Instruction(get_module()->context(), SpvOpFunctionParameter,
+          new Instruction(get_module()->context(), spv::Op::OpFunctionParameter,
                           GetUintId(), pid, {}));
       get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
       output_func->AddParameter(std::move(param_inst));
@@ -726,37 +787,39 @@
     uint32_t buf_id = GetOutputBufferId();
     uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
     Instruction* obuf_curr_sz_ac_inst =
-        builder.AddBinaryOp(buf_uint_ptr_id, SpvOpAccessChain, buf_id,
+        builder.AddBinaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id,
                             builder.GetUintConstantId(kDebugOutputSizeOffset));
     // Fetch the current debug buffer written size atomically, adding the
     // size of the record to be written.
     uint32_t obuf_record_sz_id = builder.GetUintConstantId(obuf_record_sz);
-    uint32_t mask_none_id = builder.GetUintConstantId(SpvMemoryAccessMaskNone);
-    uint32_t scope_invok_id = builder.GetUintConstantId(SpvScopeInvocation);
+    uint32_t mask_none_id =
+        builder.GetUintConstantId(uint32_t(spv::MemoryAccessMask::MaskNone));
+    uint32_t scope_invok_id =
+        builder.GetUintConstantId(uint32_t(spv::Scope::Invocation));
     Instruction* obuf_curr_sz_inst = builder.AddQuadOp(
-        GetUintId(), SpvOpAtomicIAdd, obuf_curr_sz_ac_inst->result_id(),
+        GetUintId(), spv::Op::OpAtomicIAdd, obuf_curr_sz_ac_inst->result_id(),
         scope_invok_id, mask_none_id, obuf_record_sz_id);
     uint32_t obuf_curr_sz_id = obuf_curr_sz_inst->result_id();
     // Compute new written size
     Instruction* obuf_new_sz_inst =
-        builder.AddBinaryOp(GetUintId(), SpvOpIAdd, obuf_curr_sz_id,
+        builder.AddBinaryOp(GetUintId(), spv::Op::OpIAdd, obuf_curr_sz_id,
                             builder.GetUintConstantId(obuf_record_sz));
     // Fetch the data bound
     Instruction* obuf_bnd_inst =
-        builder.AddIdLiteralOp(GetUintId(), SpvOpArrayLength,
+        builder.AddIdLiteralOp(GetUintId(), spv::Op::OpArrayLength,
                                GetOutputBufferId(), kDebugOutputDataOffset);
     // Test that new written size is less than or equal to debug output
     // data bound
     Instruction* obuf_safe_inst = builder.AddBinaryOp(
-        GetBoolId(), SpvOpULessThanEqual, obuf_new_sz_inst->result_id(),
+        GetBoolId(), spv::Op::OpULessThanEqual, obuf_new_sz_inst->result_id(),
         obuf_bnd_inst->result_id());
     uint32_t merge_blk_id = TakeNextId();
     uint32_t write_blk_id = TakeNextId();
     std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
     std::unique_ptr<Instruction> write_label(NewLabel(write_blk_id));
-    (void)builder.AddConditionalBranch(obuf_safe_inst->result_id(),
-                                       write_blk_id, merge_blk_id, merge_blk_id,
-                                       SpvSelectionControlMaskNone);
+    (void)builder.AddConditionalBranch(
+        obuf_safe_inst->result_id(), write_blk_id, merge_blk_id, merge_blk_id,
+        uint32_t(spv::SelectionControlMask::MaskNone));
     // Close safety test block and gen write block
     output_func->AddBasicBlock(std::move(new_blk_ptr));
     new_blk_ptr = MakeUnique<BasicBlock>(std::move(write_label));
@@ -776,13 +839,19 @@
     new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
     builder.SetInsertPoint(&*new_blk_ptr);
     // Close merge block and function and add function to module
-    (void)builder.AddNullaryOp(0, SpvOpReturn);
+    (void)builder.AddNullaryOp(0, spv::Op::OpReturn);
     output_func->AddBasicBlock(std::move(new_blk_ptr));
-    std::unique_ptr<Instruction> func_end_inst(
-        new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
+    std::unique_ptr<Instruction> func_end_inst(new Instruction(
+        get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
     output_func->SetFunctionEnd(std::move(func_end_inst));
     context()->AddFunction(std::move(output_func));
+
+    std::string name("stream_write_");
+    name += std::to_string(param_cnt);
+
+    context()->AddDebug2Inst(
+        NewGlobalName(param2output_func_id_[param_cnt], name));
   }
   return param2output_func_id_[param_cnt];
 }
@@ -800,9 +869,9 @@
   analysis::Function func_ty(type_mgr->GetType(ibuf_type_id), param_types);
   analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
   std::unique_ptr<Instruction> func_inst(new Instruction(
-      get_module()->context(), SpvOpFunction, ibuf_type_id, func_id,
+      get_module()->context(), spv::Op::OpFunction, ibuf_type_id, func_id,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-        {SpvFunctionControlMaskNone}},
+        {uint32_t(spv::FunctionControlMask::MaskNone)}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
         {type_mgr->GetTypeInstruction(reg_func_ty)}}}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
@@ -813,8 +882,9 @@
   for (uint32_t c = 0; c < param_cnt; ++c) {
     uint32_t pid = TakeNextId();
     param_vec.push_back(pid);
-    std::unique_ptr<Instruction> param_inst(new Instruction(
-        get_module()->context(), SpvOpFunctionParameter, GetUintId(), pid, {}));
+    std::unique_ptr<Instruction> param_inst(
+        new Instruction(get_module()->context(), spv::Op::OpFunctionParameter,
+                        GetUintId(), pid, {}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
     input_func->AddParameter(std::move(param_inst));
   }
@@ -839,30 +909,35 @@
     } else {
       if (ibuf_type_id != GetUintId()) {
         Instruction* ucvt_inst =
-            builder.AddUnaryOp(GetUintId(), SpvOpUConvert, last_value_id);
+            builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, last_value_id);
         last_value_id = ucvt_inst->result_id();
       }
       Instruction* offset_inst = builder.AddBinaryOp(
-          GetUintId(), SpvOpIAdd, last_value_id, param_vec[p]);
+          GetUintId(), spv::Op::OpIAdd, last_value_id, param_vec[p]);
       offset_id = offset_inst->result_id();
     }
     Instruction* ac_inst = builder.AddTernaryOp(
-        buf_ptr_id, SpvOpAccessChain, buf_id,
+        buf_ptr_id, spv::Op::OpAccessChain, buf_id,
         builder.GetUintConstantId(kDebugInputDataOffset), offset_id);
     Instruction* load_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, ac_inst->result_id());
+        builder.AddUnaryOp(ibuf_type_id, spv::Op::OpLoad, ac_inst->result_id());
     last_value_id = load_inst->result_id();
   }
   (void)builder.AddInstruction(MakeUnique<Instruction>(
-      context(), SpvOpReturnValue, 0, 0,
+      context(), spv::Op::OpReturnValue, 0, 0,
       std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {last_value_id}}}));
   // Close block and function and add function to module
   input_func->AddBasicBlock(std::move(new_blk_ptr));
-  std::unique_ptr<Instruction> func_end_inst(
-      new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
+  std::unique_ptr<Instruction> func_end_inst(new Instruction(
+      get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
   input_func->SetFunctionEnd(std::move(func_end_inst));
   context()->AddFunction(std::move(input_func));
+
+  std::string name("direct_read_");
+  name += std::to_string(param_cnt);
+  context()->AddDebug2Inst(NewGlobalName(func_id, name));
+
   param2input_func_id_[param_cnt] = func_id;
   return func_id;
 }
@@ -905,7 +980,7 @@
       // block. This will allow function calls to be inserted into the first
       // block without interfering with the instrumentation algorithm.
       if (opt_direct_reads_ && !first_block_split) {
-        if (ii->opcode() != SpvOpVariable) {
+        if (ii->opcode() != spv::Op::OpVariable) {
           SplitBlock(ii, bi, &new_blks);
           first_block_split = true;
         }
@@ -936,7 +1011,9 @@
       // Restart instrumenting at beginning of last new block,
       // but skip over any new phi or copy instruction.
       ii = bi->begin();
-      if (ii->opcode() == SpvOpPhi || ii->opcode() == SpvOpCopyObject) ++ii;
+      if (ii->opcode() == spv::Op::OpPhi ||
+          ii->opcode() == spv::Op::OpCopyObject)
+        ++ii;
       new_blks.clear();
     }
   }
@@ -974,34 +1051,24 @@
   // one model per module. In such cases we will need
   // to clone any functions which are in the call trees of entrypoints
   // with differing execution models.
-  uint32_t ecnt = 0;
-  uint32_t stage = SpvExecutionModelMax;
-  for (auto& e : get_module()->entry_points()) {
-    if (ecnt == 0)
-      stage = e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx);
-    else if (e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx) !=
-             stage) {
-      if (consumer()) {
-        std::string message = "Mixed stage shader module not supported";
-        consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str());
-      }
-      return false;
-    }
-    ++ecnt;
-  }
+  spv::ExecutionModel stage = context()->GetStage();
   // Check for supported stages
-  if (stage != SpvExecutionModelVertex && stage != SpvExecutionModelFragment &&
-      stage != SpvExecutionModelGeometry &&
-      stage != SpvExecutionModelGLCompute &&
-      stage != SpvExecutionModelTessellationControl &&
-      stage != SpvExecutionModelTessellationEvaluation &&
-      stage != SpvExecutionModelTaskNV && stage != SpvExecutionModelMeshNV &&
-      stage != SpvExecutionModelRayGenerationNV &&
-      stage != SpvExecutionModelIntersectionNV &&
-      stage != SpvExecutionModelAnyHitNV &&
-      stage != SpvExecutionModelClosestHitNV &&
-      stage != SpvExecutionModelMissNV &&
-      stage != SpvExecutionModelCallableNV) {
+  if (stage != spv::ExecutionModel::Vertex &&
+      stage != spv::ExecutionModel::Fragment &&
+      stage != spv::ExecutionModel::Geometry &&
+      stage != spv::ExecutionModel::GLCompute &&
+      stage != spv::ExecutionModel::TessellationControl &&
+      stage != spv::ExecutionModel::TessellationEvaluation &&
+      stage != spv::ExecutionModel::TaskNV &&
+      stage != spv::ExecutionModel::MeshNV &&
+      stage != spv::ExecutionModel::RayGenerationNV &&
+      stage != spv::ExecutionModel::IntersectionNV &&
+      stage != spv::ExecutionModel::AnyHitNV &&
+      stage != spv::ExecutionModel::ClosestHitNV &&
+      stage != spv::ExecutionModel::MissNV &&
+      stage != spv::ExecutionModel::CallableNV &&
+      stage != spv::ExecutionModel::TaskEXT &&
+      stage != spv::ExecutionModel::MeshEXT) {
     if (consumer()) {
       std::string message = "Stage not supported by instrumentation";
       consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str());
@@ -1013,7 +1080,7 @@
   for (auto& e : get_module()->entry_points()) {
     roots.push(e.GetSingleWordInOperand(kEntryPointFunctionIdInIdx));
   }
-  bool modified = InstProcessCallTreeFromRoots(pfn, &roots, stage);
+  bool modified = InstProcessCallTreeFromRoots(pfn, &roots, uint32_t(stage));
   return modified;
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/instrument_pass.h b/third_party/SPIRV-Tools/source/opt/instrument_pass.h
index 90c1dd4..e98ba88 100644
--- a/third_party/SPIRV-Tools/source/opt/instrument_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/instrument_pass.h
@@ -55,13 +55,14 @@
 
 namespace spvtools {
 namespace opt {
-
+namespace {
 // Validation Ids
 // These are used to identify the general validation being done and map to
 // its output buffers.
-static const uint32_t kInstValidationIdBindless = 0;
-static const uint32_t kInstValidationIdBuffAddr = 1;
-static const uint32_t kInstValidationIdDebugPrintf = 2;
+constexpr uint32_t kInstValidationIdBindless = 0;
+constexpr uint32_t kInstValidationIdBuffAddr = 1;
+constexpr uint32_t kInstValidationIdDebugPrintf = 2;
+}  // namespace
 
 class InstrumentPass : public Pass {
   using cbb_ptr = const BasicBlock*;
@@ -224,6 +225,19 @@
   // Return new label.
   std::unique_ptr<Instruction> NewLabel(uint32_t label_id);
 
+  // Set the name function parameter or local variable
+  std::unique_ptr<Instruction> NewName(uint32_t id,
+                                       const std::string& name_str);
+
+  // Set the name for a function or global variable, names will be
+  // prefixed to identify which instrumentation pass generated them.
+  std::unique_ptr<Instruction> NewGlobalName(uint32_t id,
+                                             const std::string& name_str);
+
+  // Set the name for a structure member
+  std::unique_ptr<Instruction> NewMemberName(uint32_t id, uint32_t member_index,
+                                             const std::string& name_str);
+
   // Return id for 32-bit unsigned type
   uint32_t GetUintId();
 
diff --git a/third_party/SPIRV-Tools/source/opt/interface_var_sroa.cpp b/third_party/SPIRV-Tools/source/opt/interface_var_sroa.cpp
index 1b2cb36..8205c75 100644
--- a/third_party/SPIRV-Tools/source/opt/interface_var_sroa.cpp
+++ b/third_party/SPIRV-Tools/source/opt/interface_var_sroa.cpp
@@ -23,29 +23,28 @@
 #include "source/opt/type_manager.h"
 #include "source/util/make_unique.h"
 
-const static uint32_t kOpDecorateDecorationInOperandIndex = 1;
-const static uint32_t kOpDecorateLiteralInOperandIndex = 2;
-const static uint32_t kOpEntryPointInOperandInterface = 3;
-const static uint32_t kOpVariableStorageClassInOperandIndex = 0;
-const static uint32_t kOpTypeArrayElemTypeInOperandIndex = 0;
-const static uint32_t kOpTypeArrayLengthInOperandIndex = 1;
-const static uint32_t kOpTypeMatrixColCountInOperandIndex = 1;
-const static uint32_t kOpTypeMatrixColTypeInOperandIndex = 0;
-const static uint32_t kOpTypePtrTypeInOperandIndex = 1;
-const static uint32_t kOpConstantValueInOperandIndex = 0;
-
 namespace spvtools {
 namespace opt {
 namespace {
+constexpr uint32_t kOpDecorateDecorationInOperandIndex = 1;
+constexpr uint32_t kOpDecorateLiteralInOperandIndex = 2;
+constexpr uint32_t kOpEntryPointInOperandInterface = 3;
+constexpr uint32_t kOpVariableStorageClassInOperandIndex = 0;
+constexpr uint32_t kOpTypeArrayElemTypeInOperandIndex = 0;
+constexpr uint32_t kOpTypeArrayLengthInOperandIndex = 1;
+constexpr uint32_t kOpTypeMatrixColCountInOperandIndex = 1;
+constexpr uint32_t kOpTypeMatrixColTypeInOperandIndex = 0;
+constexpr uint32_t kOpTypePtrTypeInOperandIndex = 1;
+constexpr uint32_t kOpConstantValueInOperandIndex = 0;
 
 // Get the length of the OpTypeArray |array_type|.
 uint32_t GetArrayLength(analysis::DefUseManager* def_use_mgr,
                         Instruction* array_type) {
-  assert(array_type->opcode() == SpvOpTypeArray);
+  assert(array_type->opcode() == spv::Op::OpTypeArray);
   uint32_t const_int_id =
       array_type->GetSingleWordInOperand(kOpTypeArrayLengthInOperandIndex);
   Instruction* array_length_inst = def_use_mgr->GetDef(const_int_id);
-  assert(array_length_inst->opcode() == SpvOpConstant);
+  assert(array_length_inst->opcode() == spv::Op::OpConstant);
   return array_length_inst->GetSingleWordInOperand(
       kOpConstantValueInOperandIndex);
 }
@@ -53,7 +52,7 @@
 // Get the element type instruction of the OpTypeArray |array_type|.
 Instruction* GetArrayElementType(analysis::DefUseManager* def_use_mgr,
                                  Instruction* array_type) {
-  assert(array_type->opcode() == SpvOpTypeArray);
+  assert(array_type->opcode() == spv::Op::OpTypeArray);
   uint32_t elem_type_id =
       array_type->GetSingleWordInOperand(kOpTypeArrayElemTypeInOperandIndex);
   return def_use_mgr->GetDef(elem_type_id);
@@ -62,7 +61,7 @@
 // Get the column type instruction of the OpTypeMatrix |matrix_type|.
 Instruction* GetMatrixColumnType(analysis::DefUseManager* def_use_mgr,
                                  Instruction* matrix_type) {
-  assert(matrix_type->opcode() == SpvOpTypeMatrix);
+  assert(matrix_type->opcode() == spv::Op::OpTypeMatrix);
   uint32_t column_type_id =
       matrix_type->GetSingleWordInOperand(kOpTypeMatrixColTypeInOperandIndex);
   return def_use_mgr->GetDef(column_type_id);
@@ -77,14 +76,14 @@
   if (depth_to_component == 0) return type_id;
 
   Instruction* type_inst = def_use_mgr->GetDef(type_id);
-  if (type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeArray) {
     uint32_t elem_type_id =
         type_inst->GetSingleWordInOperand(kOpTypeArrayElemTypeInOperandIndex);
     return GetComponentTypeOfArrayMatrix(def_use_mgr, elem_type_id,
                                          depth_to_component - 1);
   }
 
-  assert(type_inst->opcode() == SpvOpTypeMatrix);
+  assert(type_inst->opcode() == spv::Op::OpTypeMatrix);
   uint32_t column_type_id =
       type_inst->GetSingleWordInOperand(kOpTypeMatrixColTypeInOperandIndex);
   return GetComponentTypeOfArrayMatrix(def_use_mgr, column_type_id,
@@ -94,7 +93,7 @@
 // Creates an OpDecorate instruction whose Target is |var_id| and Decoration is
 // |decoration|. Adds |literal| as an extra operand of the instruction.
 void CreateDecoration(analysis::DecorationManager* decoration_mgr,
-                      uint32_t var_id, SpvDecoration decoration,
+                      uint32_t var_id, spv::Decoration decoration,
                       uint32_t literal) {
   std::vector<Operand> operands({
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {var_id}},
@@ -102,7 +101,7 @@
        {static_cast<uint32_t>(decoration)}},
       {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {literal}},
   });
-  decoration_mgr->AddDecoration(SpvOpDecorate, std::move(operands));
+  decoration_mgr->AddDecoration(spv::Op::OpDecorate, std::move(operands));
 }
 
 // Replaces load instructions with composite construct instructions in all the
@@ -128,8 +127,8 @@
 }
 
 // Returns the storage class of the instruction |var|.
-SpvStorageClass GetStorageClass(Instruction* var) {
-  return static_cast<SpvStorageClass>(
+spv::StorageClass GetStorageClass(Instruction* var) {
+  return static_cast<spv::StorageClass>(
       var->GetSingleWordInOperand(kOpVariableStorageClassInOperandIndex));
 }
 
@@ -137,16 +136,17 @@
 
 bool InterfaceVariableScalarReplacement::HasExtraArrayness(
     Instruction& entry_point, Instruction* var) {
-  SpvExecutionModel execution_model =
-      static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
-  if (execution_model != SpvExecutionModelTessellationEvaluation &&
-      execution_model != SpvExecutionModelTessellationControl) {
+  spv::ExecutionModel execution_model =
+      static_cast<spv::ExecutionModel>(entry_point.GetSingleWordInOperand(0));
+  if (execution_model != spv::ExecutionModel::TessellationEvaluation &&
+      execution_model != spv::ExecutionModel::TessellationControl) {
     return false;
   }
-  if (!context()->get_decoration_mgr()->HasDecoration(var->result_id(),
-                                                      SpvDecorationPatch)) {
-    if (execution_model == SpvExecutionModelTessellationControl) return true;
-    return GetStorageClass(var) != SpvStorageClassOutput;
+  if (!context()->get_decoration_mgr()->HasDecoration(
+          var->result_id(), uint32_t(spv::Decoration::Patch))) {
+    if (execution_model == spv::ExecutionModel::TessellationControl)
+      return true;
+    return GetStorageClass(var) != spv::StorageClass::Output;
   }
   return false;
 }
@@ -163,7 +163,7 @@
 bool InterfaceVariableScalarReplacement::GetVariableLocation(
     Instruction* var, uint32_t* location) {
   return !context()->get_decoration_mgr()->WhileEachDecoration(
-      var->result_id(), SpvDecorationLocation,
+      var->result_id(), uint32_t(spv::Decoration::Location),
       [location](const Instruction& inst) {
         *location =
             inst.GetSingleWordInOperand(kOpDecorateLiteralInOperandIndex);
@@ -174,7 +174,7 @@
 bool InterfaceVariableScalarReplacement::GetVariableComponent(
     Instruction* var, uint32_t* component) {
   return !context()->get_decoration_mgr()->WhileEachDecoration(
-      var->result_id(), SpvDecorationComponent,
+      var->result_id(), uint32_t(spv::Decoration::Component),
       [component](const Instruction& inst) {
         *component =
             inst.GetSingleWordInOperand(kOpDecorateLiteralInOperandIndex);
@@ -190,11 +190,11 @@
        i < entry_point.NumInOperands(); ++i) {
     Instruction* interface_var = context()->get_def_use_mgr()->GetDef(
         entry_point.GetSingleWordInOperand(i));
-    assert(interface_var->opcode() == SpvOpVariable);
+    assert(interface_var->opcode() == spv::Op::OpVariable);
 
-    SpvStorageClass storage_class = GetStorageClass(interface_var);
-    if (storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    spv::StorageClass storage_class = GetStorageClass(interface_var);
+    if (storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       continue;
     }
 
@@ -205,10 +205,10 @@
 
 void InterfaceVariableScalarReplacement::KillInstructionAndUsers(
     Instruction* inst) {
-  if (inst->opcode() == SpvOpEntryPoint) {
+  if (inst->opcode() == spv::Op::OpEntryPoint) {
     return;
   }
-  if (inst->opcode() != SpvOpAccessChain) {
+  if (inst->opcode() != spv::Op::OpAccessChain) {
     context()->KillInst(inst);
     return;
   }
@@ -232,10 +232,10 @@
     uint32_t var_id) {
   context()->get_decoration_mgr()->RemoveDecorationsFrom(
       var_id, [](const Instruction& inst) {
-        uint32_t decoration =
-            inst.GetSingleWordInOperand(kOpDecorateDecorationInOperandIndex);
-        return decoration == SpvDecorationLocation ||
-               decoration == SpvDecorationComponent;
+        spv::Decoration decoration = spv::Decoration(
+            inst.GetSingleWordInOperand(kOpDecorateDecorationInOperandIndex));
+        return decoration == spv::Decoration::Location ||
+               decoration == spv::Decoration::Component;
       });
 }
 
@@ -307,9 +307,9 @@
   if (!vars.HasMultipleComponents()) {
     uint32_t var_id = vars.GetComponentVariable()->result_id();
     CreateDecoration(context()->get_decoration_mgr(), var_id,
-                     SpvDecorationLocation, *location);
+                     spv::Decoration::Location, *location);
     CreateDecoration(context()->get_decoration_mgr(), var_id,
-                     SpvDecorationComponent, component);
+                     spv::Decoration::Component, component);
     ++(*location);
     return;
   }
@@ -389,15 +389,15 @@
     std::unordered_map<Instruction*, Instruction*>* loads_to_component_values,
     std::unordered_map<Instruction*, Instruction*>*
         loads_for_access_chain_to_component_values) {
-  SpvOp opcode = interface_var_user->opcode();
-  if (opcode == SpvOpStore) {
+  spv::Op opcode = interface_var_user->opcode();
+  if (opcode == spv::Op::OpStore) {
     uint32_t value_id = interface_var_user->GetSingleWordInOperand(1);
     StoreComponentOfValueToScalarVar(value_id, interface_var_component_indices,
                                      scalar_var, extra_array_index,
                                      interface_var_user);
     return true;
   }
-  if (opcode == SpvOpLoad) {
+  if (opcode == spv::Op::OpLoad) {
     Instruction* scalar_load =
         LoadScalarVar(scalar_var, extra_array_index, interface_var_user);
     loads_to_component_values->insert({interface_var_user, scalar_load});
@@ -408,25 +408,25 @@
   // them only for the first element of the extra array.
   if (extra_array_index && *extra_array_index != 0) return true;
 
-  if (opcode == SpvOpDecorateId || opcode == SpvOpDecorateString ||
-      opcode == SpvOpDecorate) {
+  if (opcode == spv::Op::OpDecorateId || opcode == spv::Op::OpDecorateString ||
+      opcode == spv::Op::OpDecorate) {
     CloneAnnotationForVariable(interface_var_user, scalar_var->result_id());
     return true;
   }
 
-  if (opcode == SpvOpName) {
+  if (opcode == spv::Op::OpName) {
     std::unique_ptr<Instruction> new_inst(interface_var_user->Clone(context()));
     new_inst->SetInOperand(0, {scalar_var->result_id()});
     context()->AddDebug2Inst(std::move(new_inst));
     return true;
   }
 
-  if (opcode == SpvOpEntryPoint) {
+  if (opcode == spv::Op::OpEntryPoint) {
     return ReplaceInterfaceVarInEntryPoint(interface_var, interface_var_user,
                                            scalar_var->result_id());
   }
 
-  if (opcode == SpvOpAccessChain) {
+  if (opcode == spv::Op::OpAccessChain) {
     ReplaceAccessChainWith(interface_var_user, interface_var_component_indices,
                            scalar_var,
                            loads_for_access_chain_to_component_values);
@@ -445,8 +445,8 @@
 
 void InterfaceVariableScalarReplacement::UseBaseAccessChainForAccessChain(
     Instruction* access_chain, Instruction* base_access_chain) {
-  assert(base_access_chain->opcode() == SpvOpAccessChain &&
-         access_chain->opcode() == SpvOpAccessChain &&
+  assert(base_access_chain->opcode() == spv::Op::OpAccessChain &&
+         access_chain->opcode() == spv::Op::OpAccessChain &&
          access_chain->GetSingleWordInOperand(0) ==
              base_access_chain->result_id());
   Instruction::OperandList new_operands;
@@ -470,10 +470,10 @@
   uint32_t ptr_type_id =
       GetPointerType(*component_type_id, GetStorageClass(var));
 
-  std::unique_ptr<Instruction> new_access_chain(
-      new Instruction(context(), SpvOpAccessChain, ptr_type_id, TakeNextId(),
-                      std::initializer_list<Operand>{
-                          {SPV_OPERAND_TYPE_ID, {var->result_id()}}}));
+  std::unique_ptr<Instruction> new_access_chain(new Instruction(
+      context(), spv::Op::OpAccessChain, ptr_type_id, TakeNextId(),
+      std::initializer_list<Operand>{
+          {SPV_OPERAND_TYPE_ID, {var->result_id()}}}));
   for (uint32_t index_id : index_ids) {
     new_access_chain->AddOperand({SPV_OPERAND_TYPE_ID, {index_id}});
   }
@@ -490,12 +490,12 @@
   uint32_t ptr_type_id =
       GetPointerType(component_type_id, GetStorageClass(var));
   uint32_t index_id = context()->get_constant_mgr()->GetUIntConst(index);
-  std::unique_ptr<Instruction> new_access_chain(
-      new Instruction(context(), SpvOpAccessChain, ptr_type_id, TakeNextId(),
-                      std::initializer_list<Operand>{
-                          {SPV_OPERAND_TYPE_ID, {var->result_id()}},
-                          {SPV_OPERAND_TYPE_ID, {index_id}},
-                      }));
+  std::unique_ptr<Instruction> new_access_chain(new Instruction(
+      context(), spv::Op::OpAccessChain, ptr_type_id, TakeNextId(),
+      std::initializer_list<Operand>{
+          {SPV_OPERAND_TYPE_ID, {var->result_id()}},
+          {SPV_OPERAND_TYPE_ID, {index_id}},
+      }));
   Instruction* inst = new_access_chain.get();
   context()->get_def_use_mgr()->AnalyzeInstDefUse(inst);
   insert_before->InsertBefore(std::move(new_access_chain));
@@ -519,20 +519,20 @@
       [this, access_chain, &indexes, &interface_var_component_indices,
        scalar_var, loads_to_component_values](Instruction* user) {
         switch (user->opcode()) {
-          case SpvOpAccessChain: {
+          case spv::Op::OpAccessChain: {
             UseBaseAccessChainForAccessChain(user, access_chain);
             ReplaceAccessChainWith(user, interface_var_component_indices,
                                    scalar_var, loads_to_component_values);
             return;
           }
-          case SpvOpStore: {
+          case spv::Op::OpStore: {
             uint32_t value_id = user->GetSingleWordInOperand(1);
             StoreComponentOfValueToAccessChainToScalarVar(
                 value_id, interface_var_component_indices, scalar_var, indexes,
                 user);
             return;
           }
-          case SpvOpLoad: {
+          case spv::Op::OpLoad: {
             Instruction* value =
                 LoadAccessChainToVar(scalar_var, indexes, user);
             loads_to_component_values->insert({user, value});
@@ -546,9 +546,9 @@
 
 void InterfaceVariableScalarReplacement::CloneAnnotationForVariable(
     Instruction* annotation_inst, uint32_t var_id) {
-  assert(annotation_inst->opcode() == SpvOpDecorate ||
-         annotation_inst->opcode() == SpvOpDecorateId ||
-         annotation_inst->opcode() == SpvOpDecorateString);
+  assert(annotation_inst->opcode() == spv::Op::OpDecorate ||
+         annotation_inst->opcode() == spv::Op::OpDecorateId ||
+         annotation_inst->opcode() == spv::Op::OpDecorateString);
   std::unique_ptr<Instruction> new_inst(annotation_inst->Clone(context()));
   new_inst->SetInOperand(0, {var_id});
   context()->AddAnnotationInst(std::move(new_inst));
@@ -593,13 +593,13 @@
 
 uint32_t InterfaceVariableScalarReplacement::GetPointeeTypeIdOfVar(
     Instruction* var) {
-  assert(var->opcode() == SpvOpVariable);
+  assert(var->opcode() == spv::Op::OpVariable);
 
   uint32_t ptr_type_id = var->type_id();
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   Instruction* ptr_type_inst = def_use_mgr->GetDef(ptr_type_id);
 
-  assert(ptr_type_inst->opcode() == SpvOpTypePointer &&
+  assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Variable must have a pointer type.");
   return ptr_type_inst->GetSingleWordInOperand(kOpTypePtrTypeInOperandIndex);
 }
@@ -643,7 +643,7 @@
 Instruction* InterfaceVariableScalarReplacement::CreateLoad(
     uint32_t type_id, Instruction* ptr, Instruction* insert_before) {
   std::unique_ptr<Instruction> load(
-      new Instruction(context(), SpvOpLoad, type_id, TakeNextId(),
+      new Instruction(context(), spv::Op::OpLoad, type_id, TakeNextId(),
                       std::initializer_list<Operand>{
                           {SPV_OPERAND_TYPE_ID, {ptr->result_id()}}}));
   Instruction* load_inst = load.get();
@@ -660,7 +660,7 @@
       component_type_id, value_id, component_indices, extra_array_index));
 
   std::unique_ptr<Instruction> new_store(
-      new Instruction(context(), SpvOpStore));
+      new Instruction(context(), spv::Op::OpStore));
   new_store->AddOperand({SPV_OPERAND_TYPE_ID, {ptr->result_id()}});
   new_store->AddOperand(
       {SPV_OPERAND_TYPE_ID, {composite_extract->result_id()}});
@@ -678,7 +678,7 @@
     const std::vector<uint32_t>& indexes, const uint32_t* extra_first_index) {
   uint32_t component_id = TakeNextId();
   Instruction* composite_extract = new Instruction(
-      context(), SpvOpCompositeExtract, type_id, component_id,
+      context(), spv::Op::OpCompositeExtract, type_id, component_id,
       std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {composite_id}}});
   if (extra_first_index) {
     composite_extract->AddOperand(
@@ -731,8 +731,8 @@
                                             depth_to_component);
   }
   uint32_t new_id = context()->TakeNextId();
-  std::unique_ptr<Instruction> new_composite_construct(
-      new Instruction(context(), SpvOpCompositeConstruct, type_id, new_id, {}));
+  std::unique_ptr<Instruction> new_composite_construct(new Instruction(
+      context(), spv::Op::OpCompositeConstruct, type_id, new_id, {}));
   Instruction* composite_construct = new_composite_construct.get();
   def_use_mgr->AnalyzeInstDefUse(composite_construct);
 
@@ -789,7 +789,7 @@
 }
 
 uint32_t InterfaceVariableScalarReplacement::GetPointerType(
-    uint32_t type_id, SpvStorageClass storage_class) {
+    uint32_t type_id, spv::StorageClass storage_class) {
   analysis::Type* type = context()->get_type_mgr()->GetType(type_id);
   analysis::Pointer ptr_type(type, storage_class);
   return context()->get_type_mgr()->GetTypeInstruction(&ptr_type);
@@ -797,9 +797,9 @@
 
 InterfaceVariableScalarReplacement::NestedCompositeComponents
 InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForArray(
-    Instruction* interface_var_type, SpvStorageClass storage_class,
+    Instruction* interface_var_type, spv::StorageClass storage_class,
     uint32_t extra_array_length) {
-  assert(interface_var_type->opcode() == SpvOpTypeArray);
+  assert(interface_var_type->opcode() == spv::Op::OpTypeArray);
 
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   uint32_t array_length = GetArrayLength(def_use_mgr, interface_var_type);
@@ -818,9 +818,9 @@
 
 InterfaceVariableScalarReplacement::NestedCompositeComponents
 InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForMatrix(
-    Instruction* interface_var_type, SpvStorageClass storage_class,
+    Instruction* interface_var_type, spv::StorageClass storage_class,
     uint32_t extra_array_length) {
-  assert(interface_var_type->opcode() == SpvOpTypeMatrix);
+  assert(interface_var_type->opcode() == spv::Op::OpTypeMatrix);
 
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   uint32_t column_count = interface_var_type->GetSingleWordInOperand(
@@ -841,16 +841,16 @@
 
 InterfaceVariableScalarReplacement::NestedCompositeComponents
 InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForReplacement(
-    Instruction* interface_var_type, SpvStorageClass storage_class,
+    Instruction* interface_var_type, spv::StorageClass storage_class,
     uint32_t extra_array_length) {
   // Handle array case.
-  if (interface_var_type->opcode() == SpvOpTypeArray) {
+  if (interface_var_type->opcode() == spv::Op::OpTypeArray) {
     return CreateScalarInterfaceVarsForArray(interface_var_type, storage_class,
                                              extra_array_length);
   }
 
   // Handle matrix case.
-  if (interface_var_type->opcode() == SpvOpTypeMatrix) {
+  if (interface_var_type->opcode() == spv::Op::OpTypeMatrix) {
     return CreateScalarInterfaceVarsForMatrix(interface_var_type, storage_class,
                                               extra_array_length);
   }
@@ -865,7 +865,7 @@
       context()->get_type_mgr()->FindPointerToType(type_id, storage_class);
   uint32_t id = TakeNextId();
   std::unique_ptr<Instruction> variable(
-      new Instruction(context(), SpvOpVariable, ptr_type_id, id,
+      new Instruction(context(), spv::Op::OpVariable, ptr_type_id, id,
                       std::initializer_list<Operand>{
                           {SPV_OPERAND_TYPE_STORAGE_CLASS,
                            {static_cast<uint32_t>(storage_class)}}}));
@@ -948,8 +948,8 @@
       return Pass::Status::Failure;
     }
 
-    if (interface_var_type->opcode() != SpvOpTypeArray &&
-        interface_var_type->opcode() != SpvOpTypeMatrix) {
+    if (interface_var_type->opcode() != spv::Op::OpTypeArray &&
+        interface_var_type->opcode() != spv::Op::OpTypeMatrix) {
       continue;
     }
 
diff --git a/third_party/SPIRV-Tools/source/opt/interface_var_sroa.h b/third_party/SPIRV-Tools/source/opt/interface_var_sroa.h
index 23baad0..df7511b 100644
--- a/third_party/SPIRV-Tools/source/opt/interface_var_sroa.h
+++ b/third_party/SPIRV-Tools/source/opt/interface_var_sroa.h
@@ -115,7 +115,7 @@
   // |extra_array_length| is not zero, adds the extra arrayness to the created
   // scalar variables.
   NestedCompositeComponents CreateScalarInterfaceVarsForReplacement(
-      Instruction* interface_var_type, SpvStorageClass storage_class,
+      Instruction* interface_var_type, spv::StorageClass storage_class,
       uint32_t extra_array_length);
 
   // Creates scalar variables with the storage classe |storage_class| to replace
@@ -123,7 +123,7 @@
   // If |extra_array_length| is not zero, adds the extra arrayness to all the
   // scalar variables.
   NestedCompositeComponents CreateScalarInterfaceVarsForArray(
-      Instruction* interface_var_type, SpvStorageClass storage_class,
+      Instruction* interface_var_type, spv::StorageClass storage_class,
       uint32_t extra_array_length);
 
   // Creates scalar variables with the storage classe |storage_class| to replace
@@ -131,7 +131,7 @@
   // with. If |extra_array_length| is not zero, adds the extra arrayness to all
   // the scalar variables.
   NestedCompositeComponents CreateScalarInterfaceVarsForMatrix(
-      Instruction* interface_var_type, SpvStorageClass storage_class,
+      Instruction* interface_var_type, spv::StorageClass storage_class,
       uint32_t extra_array_length);
 
   // Recursively adds Location and Component decorations to variables in
@@ -345,7 +345,7 @@
 
   // Returns the result id of OpTypePointer instrunction whose Type
   // operand is |type_id| and Storage Class operand is |storage_class|.
-  uint32_t GetPointerType(uint32_t type_id, SpvStorageClass storage_class);
+  uint32_t GetPointerType(uint32_t type_id, spv::StorageClass storage_class);
 
   // Kills an instrunction |inst| and its users.
   void KillInstructionAndUsers(Instruction* inst);
diff --git a/third_party/SPIRV-Tools/source/opt/interp_fixup_pass.cpp b/third_party/SPIRV-Tools/source/opt/interp_fixup_pass.cpp
index e8cdd99..bb6f610 100644
--- a/third_party/SPIRV-Tools/source/opt/interp_fixup_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/interp_fixup_pass.cpp
@@ -25,11 +25,10 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
 
 // Input Operand Indices
-static const int kSpvVariableStorageClassInIdx = 0;
+constexpr int kSpvVariableStorageClassInIdx = 0;
 
 // Folding rule function which attempts to replace |op(OpLoad(a),...)|
 // by |op(a,...)|, where |op| is one of the GLSLstd450 InterpolateAt*
@@ -45,12 +44,12 @@
   uint32_t op1_id = inst->GetSingleWordInOperand(2);
 
   Instruction* load_inst = ctx->get_def_use_mgr()->GetDef(op1_id);
-  if (load_inst->opcode() != SpvOpLoad) return false;
+  if (load_inst->opcode() != spv::Op::OpLoad) return false;
 
   Instruction* base_inst = load_inst->GetBaseAddress();
-  USE_ASSERT(base_inst->opcode() == SpvOpVariable &&
-             base_inst->GetSingleWordInOperand(kSpvVariableStorageClassInIdx) ==
-                 SpvStorageClassInput &&
+  USE_ASSERT(base_inst->opcode() == spv::Op::OpVariable &&
+             spv::StorageClass(base_inst->GetSingleWordInOperand(
+                 kSpvVariableStorageClassInIdx)) == spv::StorageClass::Input &&
              "unexpected interpolant in InterpolateAt*");
 
   uint32_t ptr_id = load_inst->GetSingleWordInOperand(0);
diff --git a/third_party/SPIRV-Tools/source/opt/ir_builder.h b/third_party/SPIRV-Tools/source/opt/ir_builder.h
index 9d4fa8f..93289a6 100644
--- a/third_party/SPIRV-Tools/source/opt/ir_builder.h
+++ b/third_party/SPIRV-Tools/source/opt/ir_builder.h
@@ -30,7 +30,7 @@
 
 // In SPIR-V, ids are encoded as uint16_t, this id is guaranteed to be always
 // invalid.
-const uint32_t kInvalidId = std::numeric_limits<uint32_t>::max();
+constexpr uint32_t kInvalidId = std::numeric_limits<uint32_t>::max();
 
 // Helper class to abstract instruction construction and insertion.
 // The instruction builder can preserve the following analyses (specified via
@@ -58,7 +58,7 @@
       : InstructionBuilder(context, parent_block, parent_block->end(),
                            preserved_analyses) {}
 
-  Instruction* AddNullaryOp(uint32_t type_id, SpvOp opcode) {
+  Instruction* AddNullaryOp(uint32_t type_id, spv::Op opcode) {
     uint32_t result_id = 0;
     if (type_id != 0) {
       result_id = GetContext()->TakeNextId();
@@ -71,7 +71,7 @@
     return AddInstruction(std::move(new_inst));
   }
 
-  Instruction* AddUnaryOp(uint32_t type_id, SpvOp opcode, uint32_t operand1) {
+  Instruction* AddUnaryOp(uint32_t type_id, spv::Op opcode, uint32_t operand1) {
     uint32_t result_id = 0;
     if (type_id != 0) {
       result_id = GetContext()->TakeNextId();
@@ -85,7 +85,7 @@
     return AddInstruction(std::move(newUnOp));
   }
 
-  Instruction* AddBinaryOp(uint32_t type_id, SpvOp opcode, uint32_t operand1,
+  Instruction* AddBinaryOp(uint32_t type_id, spv::Op opcode, uint32_t operand1,
                            uint32_t operand2) {
     uint32_t result_id = 0;
     if (type_id != 0) {
@@ -95,13 +95,14 @@
       }
     }
     std::unique_ptr<Instruction> newBinOp(new Instruction(
-        GetContext(), opcode, type_id, opcode == SpvOpStore ? 0 : result_id,
+        GetContext(), opcode, type_id,
+        opcode == spv::Op::OpStore ? 0 : result_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand1}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand2}}}));
     return AddInstruction(std::move(newBinOp));
   }
 
-  Instruction* AddTernaryOp(uint32_t type_id, SpvOp opcode, uint32_t operand1,
+  Instruction* AddTernaryOp(uint32_t type_id, spv::Op opcode, uint32_t operand1,
                             uint32_t operand2, uint32_t operand3) {
     uint32_t result_id = 0;
     if (type_id != 0) {
@@ -118,7 +119,7 @@
     return AddInstruction(std::move(newTernOp));
   }
 
-  Instruction* AddQuadOp(uint32_t type_id, SpvOp opcode, uint32_t operand1,
+  Instruction* AddQuadOp(uint32_t type_id, spv::Op opcode, uint32_t operand1,
                          uint32_t operand2, uint32_t operand3,
                          uint32_t operand4) {
     uint32_t result_id = 0;
@@ -137,7 +138,7 @@
     return AddInstruction(std::move(newQuadOp));
   }
 
-  Instruction* AddIdLiteralOp(uint32_t type_id, SpvOp opcode, uint32_t id,
+  Instruction* AddIdLiteralOp(uint32_t type_id, spv::Op opcode, uint32_t id,
                               uint32_t uliteral) {
     uint32_t result_id = 0;
     if (type_id != 0) {
@@ -157,7 +158,7 @@
   // |typid| must be the id of the instruction's type.
   // |operands| must be a sequence of operand ids.
   // Use |result| for the result id if non-zero.
-  Instruction* AddNaryOp(uint32_t type_id, SpvOp opcode,
+  Instruction* AddNaryOp(uint32_t type_id, spv::Op opcode,
                          const std::vector<uint32_t>& operands,
                          uint32_t result = 0) {
     std::vector<Operand> ops;
@@ -174,10 +175,10 @@
   // Creates a new selection merge instruction.
   // The id |merge_id| is the merge basic block id.
   Instruction* AddSelectionMerge(
-      uint32_t merge_id,
-      uint32_t selection_control = SpvSelectionControlMaskNone) {
+      uint32_t merge_id, uint32_t selection_control = static_cast<uint32_t>(
+                             spv::SelectionControlMask::MaskNone)) {
     std::unique_ptr<Instruction> new_branch_merge(new Instruction(
-        GetContext(), SpvOpSelectionMerge, 0, 0,
+        GetContext(), spv::Op::OpSelectionMerge, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {merge_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_SELECTION_CONTROL,
           {selection_control}}}));
@@ -189,9 +190,10 @@
   // |continue_id| is the id of the continue block.
   // |loop_control| are the loop control flags to be added to the instruction.
   Instruction* AddLoopMerge(uint32_t merge_id, uint32_t continue_id,
-                            uint32_t loop_control = SpvLoopControlMaskNone) {
+                            uint32_t loop_control = static_cast<uint32_t>(
+                                spv::LoopControlMask::MaskNone)) {
     std::unique_ptr<Instruction> new_branch_merge(new Instruction(
-        GetContext(), SpvOpLoopMerge, 0, 0,
+        GetContext(), spv::Op::OpLoopMerge, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {merge_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {continue_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_LOOP_CONTROL, {loop_control}}}));
@@ -203,7 +205,7 @@
   // well formed.
   Instruction* AddBranch(uint32_t label_id) {
     std::unique_ptr<Instruction> new_branch(new Instruction(
-        GetContext(), SpvOpBranch, 0, 0,
+        GetContext(), spv::Op::OpBranch, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {label_id}}}));
     return AddInstruction(std::move(new_branch));
   }
@@ -226,12 +228,13 @@
   Instruction* AddConditionalBranch(
       uint32_t cond_id, uint32_t true_id, uint32_t false_id,
       uint32_t merge_id = kInvalidId,
-      uint32_t selection_control = SpvSelectionControlMaskNone) {
+      uint32_t selection_control =
+          static_cast<uint32_t>(spv::SelectionControlMask::MaskNone)) {
     if (merge_id != kInvalidId) {
       AddSelectionMerge(merge_id, selection_control);
     }
     std::unique_ptr<Instruction> new_branch(new Instruction(
-        GetContext(), SpvOpBranchConditional, 0, 0,
+        GetContext(), spv::Op::OpBranchConditional, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {cond_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {true_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {false_id}}}));
@@ -255,7 +258,8 @@
       uint32_t selector_id, uint32_t default_id,
       const std::vector<std::pair<Operand::OperandData, uint32_t>>& targets,
       uint32_t merge_id = kInvalidId,
-      uint32_t selection_control = SpvSelectionControlMaskNone) {
+      uint32_t selection_control =
+          static_cast<uint32_t>(spv::SelectionControlMask::MaskNone)) {
     if (merge_id != kInvalidId) {
       AddSelectionMerge(merge_id, selection_control);
     }
@@ -272,7 +276,7 @@
           Operand{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {target.second}});
     }
     std::unique_ptr<Instruction> new_switch(
-        new Instruction(GetContext(), SpvOpSwitch, 0, 0, operands));
+        new Instruction(GetContext(), spv::Op::OpSwitch, 0, 0, operands));
     return AddInstruction(std::move(new_switch));
   }
 
@@ -283,7 +287,7 @@
   Instruction* AddPhi(uint32_t type, const std::vector<uint32_t>& incomings,
                       uint32_t result = 0) {
     assert(incomings.size() % 2 == 0 && "A sequence of pairs is expected");
-    return AddNaryOp(type, SpvOpPhi, incomings, result);
+    return AddNaryOp(type, spv::Op::OpPhi, incomings, result);
   }
 
   // Creates an addition instruction.
@@ -294,7 +298,7 @@
   Instruction* AddIAdd(uint32_t type, uint32_t op1, uint32_t op2) {
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> inst(new Instruction(
-        GetContext(), SpvOpIAdd, type, GetContext()->TakeNextId(),
+        GetContext(), spv::Op::OpIAdd, type, GetContext()->TakeNextId(),
         {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}}));
     return AddInstruction(std::move(inst));
   }
@@ -308,7 +312,7 @@
     uint32_t type = GetContext()->get_type_mgr()->GetId(&bool_type);
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> inst(new Instruction(
-        GetContext(), SpvOpULessThan, type, GetContext()->TakeNextId(),
+        GetContext(), spv::Op::OpULessThan, type, GetContext()->TakeNextId(),
         {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}}));
     return AddInstruction(std::move(inst));
   }
@@ -322,7 +326,7 @@
     uint32_t type = GetContext()->get_type_mgr()->GetId(&bool_type);
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> inst(new Instruction(
-        GetContext(), SpvOpSLessThan, type, GetContext()->TakeNextId(),
+        GetContext(), spv::Op::OpSLessThan, type, GetContext()->TakeNextId(),
         {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}}));
     return AddInstruction(std::move(inst));
   }
@@ -352,7 +356,7 @@
                          uint32_t false_value) {
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> select(new Instruction(
-        GetContext(), SpvOpSelect, type, GetContext()->TakeNextId(),
+        GetContext(), spv::Op::OpSelect, type, GetContext()->TakeNextId(),
         std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cond}},
                                        {SPV_OPERAND_TYPE_ID, {true_value}},
                                        {SPV_OPERAND_TYPE_ID, {false_value}}}));
@@ -378,7 +382,7 @@
     }
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> construct(
-        new Instruction(GetContext(), SpvOpCompositeConstruct, type,
+        new Instruction(GetContext(), spv::Op::OpCompositeConstruct, type,
                         GetContext()->TakeNextId(), ops));
     return AddInstruction(std::move(construct));
   }
@@ -447,7 +451,7 @@
 
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpCompositeExtract, type,
+        new Instruction(GetContext(), spv::Op::OpCompositeExtract, type,
                         GetContext()->TakeNextId(), operands));
     return AddInstruction(std::move(new_inst));
   }
@@ -455,7 +459,7 @@
   // Creates an unreachable instruction.
   Instruction* AddUnreachable() {
     std::unique_ptr<Instruction> select(
-        new Instruction(GetContext(), SpvOpUnreachable, 0, 0,
+        new Instruction(GetContext(), spv::Op::OpUnreachable, 0, 0,
                         std::initializer_list<Operand>{}));
     return AddInstruction(std::move(select));
   }
@@ -471,7 +475,7 @@
 
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpAccessChain, type_id,
+        new Instruction(GetContext(), spv::Op::OpAccessChain, type_id,
                         GetContext()->TakeNextId(), operands));
     return AddInstruction(std::move(new_inst));
   }
@@ -482,7 +486,7 @@
 
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpLoad, type_id,
+        new Instruction(GetContext(), spv::Op::OpLoad, type_id,
                         GetContext()->TakeNextId(), operands));
     return AddInstruction(std::move(new_inst));
   }
@@ -491,7 +495,7 @@
     std::vector<Operand> operands;
     operands.push_back({SPV_OPERAND_TYPE_ID, {storage_class}});
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpVariable, type_id,
+        new Instruction(GetContext(), spv::Op::OpVariable, type_id,
                         GetContext()->TakeNextId(), operands));
     return AddInstruction(std::move(new_inst));
   }
@@ -502,7 +506,7 @@
     operands.push_back({SPV_OPERAND_TYPE_ID, {obj_id}});
 
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpStore, 0, 0, operands));
+        new Instruction(GetContext(), spv::Op::OpStore, 0, 0, operands));
     return AddInstruction(std::move(new_inst));
   }
 
@@ -518,8 +522,9 @@
     if (result_id == 0) {
       return nullptr;
     }
-    std::unique_ptr<Instruction> new_inst(new Instruction(
-        GetContext(), SpvOpFunctionCall, result_type, result_id, operands));
+    std::unique_ptr<Instruction> new_inst(
+        new Instruction(GetContext(), spv::Op::OpFunctionCall, result_type,
+                        result_id, operands));
     return AddInstruction(std::move(new_inst));
   }
 
@@ -538,8 +543,9 @@
       return nullptr;
     }
 
-    std::unique_ptr<Instruction> new_inst(new Instruction(
-        GetContext(), SpvOpVectorShuffle, result_type, result_id, operands));
+    std::unique_ptr<Instruction> new_inst(
+        new Instruction(GetContext(), spv::Op::OpVectorShuffle, result_type,
+                        result_id, operands));
     return AddInstruction(std::move(new_inst));
   }
 
@@ -560,7 +566,7 @@
     }
 
     std::unique_ptr<Instruction> new_inst(new Instruction(
-        GetContext(), SpvOpExtInst, result_type, result_id, operands));
+        GetContext(), spv::Op::OpExtInst, result_type, result_id, operands));
     return AddInstruction(std::move(new_inst));
   }
 
diff --git a/third_party/SPIRV-Tools/source/opt/ir_context.cpp b/third_party/SPIRV-Tools/source/opt/ir_context.cpp
index c9c3f1b..0a047e9 100644
--- a/third_party/SPIRV-Tools/source/opt/ir_context.cpp
+++ b/third_party/SPIRV-Tools/source/opt/ir_context.cpp
@@ -22,23 +22,21 @@
 #include "source/opt/mem_pass.h"
 #include "source/opt/reflect.h"
 
+namespace spvtools {
+namespace opt {
 namespace {
-
-static const int kSpvDecorateTargetIdInIdx = 0;
-static const int kSpvDecorateDecorationInIdx = 1;
-static const int kSpvDecorateBuiltinInIdx = 2;
-static const int kEntryPointInterfaceInIdx = 3;
-static const int kEntryPointFunctionIdInIdx = 1;
+constexpr int kSpvDecorateTargetIdInIdx = 0;
+constexpr int kSpvDecorateDecorationInIdx = 1;
+constexpr int kSpvDecorateBuiltinInIdx = 2;
+constexpr int kEntryPointInterfaceInIdx = 3;
+constexpr int kEntryPointFunctionIdInIdx = 1;
+constexpr int kEntryPointExecutionModelInIdx = 0;
 
 // Constants for OpenCL.DebugInfo.100 / NonSemantic.Shader.DebugInfo.100
 // extension instructions.
-static const uint32_t kDebugFunctionOperandFunctionIndex = 13;
-static const uint32_t kDebugGlobalVariableOperandVariableIndex = 11;
-
-}  // anonymous namespace
-
-namespace spvtools {
-namespace opt {
+constexpr uint32_t kDebugFunctionOperandFunctionIndex = 13;
+constexpr uint32_t kDebugGlobalVariableOperandVariableIndex = 11;
+}  // namespace
 
 void IRContext::BuildInvalidAnalyses(IRContext::Analysis set) {
   set = Analysis(set & ~valid_analyses_);
@@ -152,6 +150,9 @@
   if (analyses_to_invalidate & kAnalysisConstants) {
     constant_mgr_.reset(nullptr);
   }
+  if (analyses_to_invalidate & kAnalysisLiveness) {
+    liveness_mgr_.reset(nullptr);
+  }
   if (analyses_to_invalidate & kAnalysisTypes) {
     type_mgr_.reset(nullptr);
   }
@@ -195,7 +196,8 @@
   if (constant_mgr_ && IsConstantInst(inst->opcode())) {
     constant_mgr_->RemoveId(inst->result_id());
   }
-  if (inst->opcode() == SpvOpCapability || inst->opcode() == SpvOpExtension) {
+  if (inst->opcode() == spv::Op::OpCapability ||
+      inst->opcode() == spv::Op::OpExtension) {
     // We reset the feature manager, instead of updating it, because it is just
     // as much work.  We would have to remove all capabilities implied by this
     // capability that are not also implied by the remaining OpCapability
@@ -398,8 +400,8 @@
   if (AreAnalysesValid(kAnalysisDebugInfo)) {
     get_debug_info_mgr()->AnalyzeDebugInst(inst);
   }
-  if (id_to_name_ &&
-      (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
+  if (id_to_name_ && (inst->opcode() == spv::Op::OpName ||
+                      inst->opcode() == spv::Op::OpMemberName)) {
     id_to_name_->insert({inst->GetSingleWordInOperand(0), inst});
   }
 }
@@ -427,7 +429,7 @@
   const auto opcode = inst->opcode();
   const uint32_t id = inst->result_id();
   // Kill id of OpFunction from DebugFunction.
-  if (opcode == SpvOpFunction) {
+  if (opcode == spv::Op::OpFunction) {
     for (auto it = module()->ext_inst_debuginfo_begin();
          it != module()->ext_inst_debuginfo_end(); ++it) {
       if (it->GetOpenCL100DebugOpcode() != OpenCLDebugInfo100DebugFunction)
@@ -441,7 +443,7 @@
     }
   }
   // Kill id of OpVariable for global variable from DebugGlobalVariable.
-  if (opcode == SpvOpVariable || IsConstantInst(opcode)) {
+  if (opcode == spv::Op::OpVariable || IsConstantInst(opcode)) {
     for (auto it = module()->ext_inst_debuginfo_begin();
          it != module()->ext_inst_debuginfo_end(); ++it) {
       if (it->GetCommonDebugOpcode() != CommonDebugInfoDebugGlobalVariable)
@@ -457,255 +459,258 @@
 }
 
 void IRContext::AddCombinatorsForCapability(uint32_t capability) {
-  if (capability == SpvCapabilityShader) {
-    combinator_ops_[0].insert({SpvOpNop,
-                               SpvOpUndef,
-                               SpvOpConstant,
-                               SpvOpConstantTrue,
-                               SpvOpConstantFalse,
-                               SpvOpConstantComposite,
-                               SpvOpConstantSampler,
-                               SpvOpConstantNull,
-                               SpvOpTypeVoid,
-                               SpvOpTypeBool,
-                               SpvOpTypeInt,
-                               SpvOpTypeFloat,
-                               SpvOpTypeVector,
-                               SpvOpTypeMatrix,
-                               SpvOpTypeImage,
-                               SpvOpTypeSampler,
-                               SpvOpTypeSampledImage,
-                               SpvOpTypeAccelerationStructureNV,
-                               SpvOpTypeAccelerationStructureKHR,
-                               SpvOpTypeRayQueryKHR,
-                               SpvOpTypeArray,
-                               SpvOpTypeRuntimeArray,
-                               SpvOpTypeStruct,
-                               SpvOpTypeOpaque,
-                               SpvOpTypePointer,
-                               SpvOpTypeFunction,
-                               SpvOpTypeEvent,
-                               SpvOpTypeDeviceEvent,
-                               SpvOpTypeReserveId,
-                               SpvOpTypeQueue,
-                               SpvOpTypePipe,
-                               SpvOpTypeForwardPointer,
-                               SpvOpVariable,
-                               SpvOpImageTexelPointer,
-                               SpvOpLoad,
-                               SpvOpAccessChain,
-                               SpvOpInBoundsAccessChain,
-                               SpvOpArrayLength,
-                               SpvOpVectorExtractDynamic,
-                               SpvOpVectorInsertDynamic,
-                               SpvOpVectorShuffle,
-                               SpvOpCompositeConstruct,
-                               SpvOpCompositeExtract,
-                               SpvOpCompositeInsert,
-                               SpvOpCopyObject,
-                               SpvOpTranspose,
-                               SpvOpSampledImage,
-                               SpvOpImageSampleImplicitLod,
-                               SpvOpImageSampleExplicitLod,
-                               SpvOpImageSampleDrefImplicitLod,
-                               SpvOpImageSampleDrefExplicitLod,
-                               SpvOpImageSampleProjImplicitLod,
-                               SpvOpImageSampleProjExplicitLod,
-                               SpvOpImageSampleProjDrefImplicitLod,
-                               SpvOpImageSampleProjDrefExplicitLod,
-                               SpvOpImageFetch,
-                               SpvOpImageGather,
-                               SpvOpImageDrefGather,
-                               SpvOpImageRead,
-                               SpvOpImage,
-                               SpvOpImageQueryFormat,
-                               SpvOpImageQueryOrder,
-                               SpvOpImageQuerySizeLod,
-                               SpvOpImageQuerySize,
-                               SpvOpImageQueryLevels,
-                               SpvOpImageQuerySamples,
-                               SpvOpConvertFToU,
-                               SpvOpConvertFToS,
-                               SpvOpConvertSToF,
-                               SpvOpConvertUToF,
-                               SpvOpUConvert,
-                               SpvOpSConvert,
-                               SpvOpFConvert,
-                               SpvOpQuantizeToF16,
-                               SpvOpBitcast,
-                               SpvOpSNegate,
-                               SpvOpFNegate,
-                               SpvOpIAdd,
-                               SpvOpFAdd,
-                               SpvOpISub,
-                               SpvOpFSub,
-                               SpvOpIMul,
-                               SpvOpFMul,
-                               SpvOpUDiv,
-                               SpvOpSDiv,
-                               SpvOpFDiv,
-                               SpvOpUMod,
-                               SpvOpSRem,
-                               SpvOpSMod,
-                               SpvOpFRem,
-                               SpvOpFMod,
-                               SpvOpVectorTimesScalar,
-                               SpvOpMatrixTimesScalar,
-                               SpvOpVectorTimesMatrix,
-                               SpvOpMatrixTimesVector,
-                               SpvOpMatrixTimesMatrix,
-                               SpvOpOuterProduct,
-                               SpvOpDot,
-                               SpvOpIAddCarry,
-                               SpvOpISubBorrow,
-                               SpvOpUMulExtended,
-                               SpvOpSMulExtended,
-                               SpvOpAny,
-                               SpvOpAll,
-                               SpvOpIsNan,
-                               SpvOpIsInf,
-                               SpvOpLogicalEqual,
-                               SpvOpLogicalNotEqual,
-                               SpvOpLogicalOr,
-                               SpvOpLogicalAnd,
-                               SpvOpLogicalNot,
-                               SpvOpSelect,
-                               SpvOpIEqual,
-                               SpvOpINotEqual,
-                               SpvOpUGreaterThan,
-                               SpvOpSGreaterThan,
-                               SpvOpUGreaterThanEqual,
-                               SpvOpSGreaterThanEqual,
-                               SpvOpULessThan,
-                               SpvOpSLessThan,
-                               SpvOpULessThanEqual,
-                               SpvOpSLessThanEqual,
-                               SpvOpFOrdEqual,
-                               SpvOpFUnordEqual,
-                               SpvOpFOrdNotEqual,
-                               SpvOpFUnordNotEqual,
-                               SpvOpFOrdLessThan,
-                               SpvOpFUnordLessThan,
-                               SpvOpFOrdGreaterThan,
-                               SpvOpFUnordGreaterThan,
-                               SpvOpFOrdLessThanEqual,
-                               SpvOpFUnordLessThanEqual,
-                               SpvOpFOrdGreaterThanEqual,
-                               SpvOpFUnordGreaterThanEqual,
-                               SpvOpShiftRightLogical,
-                               SpvOpShiftRightArithmetic,
-                               SpvOpShiftLeftLogical,
-                               SpvOpBitwiseOr,
-                               SpvOpBitwiseXor,
-                               SpvOpBitwiseAnd,
-                               SpvOpNot,
-                               SpvOpBitFieldInsert,
-                               SpvOpBitFieldSExtract,
-                               SpvOpBitFieldUExtract,
-                               SpvOpBitReverse,
-                               SpvOpBitCount,
-                               SpvOpPhi,
-                               SpvOpImageSparseSampleImplicitLod,
-                               SpvOpImageSparseSampleExplicitLod,
-                               SpvOpImageSparseSampleDrefImplicitLod,
-                               SpvOpImageSparseSampleDrefExplicitLod,
-                               SpvOpImageSparseSampleProjImplicitLod,
-                               SpvOpImageSparseSampleProjExplicitLod,
-                               SpvOpImageSparseSampleProjDrefImplicitLod,
-                               SpvOpImageSparseSampleProjDrefExplicitLod,
-                               SpvOpImageSparseFetch,
-                               SpvOpImageSparseGather,
-                               SpvOpImageSparseDrefGather,
-                               SpvOpImageSparseTexelsResident,
-                               SpvOpImageSparseRead,
-                               SpvOpSizeOf});
+  spv::Capability cap = spv::Capability(capability);
+  if (cap == spv::Capability::Shader) {
+    combinator_ops_[0].insert(
+        {(uint32_t)spv::Op::OpNop,
+         (uint32_t)spv::Op::OpUndef,
+         (uint32_t)spv::Op::OpConstant,
+         (uint32_t)spv::Op::OpConstantTrue,
+         (uint32_t)spv::Op::OpConstantFalse,
+         (uint32_t)spv::Op::OpConstantComposite,
+         (uint32_t)spv::Op::OpConstantSampler,
+         (uint32_t)spv::Op::OpConstantNull,
+         (uint32_t)spv::Op::OpTypeVoid,
+         (uint32_t)spv::Op::OpTypeBool,
+         (uint32_t)spv::Op::OpTypeInt,
+         (uint32_t)spv::Op::OpTypeFloat,
+         (uint32_t)spv::Op::OpTypeVector,
+         (uint32_t)spv::Op::OpTypeMatrix,
+         (uint32_t)spv::Op::OpTypeImage,
+         (uint32_t)spv::Op::OpTypeSampler,
+         (uint32_t)spv::Op::OpTypeSampledImage,
+         (uint32_t)spv::Op::OpTypeAccelerationStructureNV,
+         (uint32_t)spv::Op::OpTypeAccelerationStructureKHR,
+         (uint32_t)spv::Op::OpTypeRayQueryKHR,
+         (uint32_t)spv::Op::OpTypeArray,
+         (uint32_t)spv::Op::OpTypeRuntimeArray,
+         (uint32_t)spv::Op::OpTypeStruct,
+         (uint32_t)spv::Op::OpTypeOpaque,
+         (uint32_t)spv::Op::OpTypePointer,
+         (uint32_t)spv::Op::OpTypeFunction,
+         (uint32_t)spv::Op::OpTypeEvent,
+         (uint32_t)spv::Op::OpTypeDeviceEvent,
+         (uint32_t)spv::Op::OpTypeReserveId,
+         (uint32_t)spv::Op::OpTypeQueue,
+         (uint32_t)spv::Op::OpTypePipe,
+         (uint32_t)spv::Op::OpTypeForwardPointer,
+         (uint32_t)spv::Op::OpVariable,
+         (uint32_t)spv::Op::OpImageTexelPointer,
+         (uint32_t)spv::Op::OpLoad,
+         (uint32_t)spv::Op::OpAccessChain,
+         (uint32_t)spv::Op::OpInBoundsAccessChain,
+         (uint32_t)spv::Op::OpArrayLength,
+         (uint32_t)spv::Op::OpVectorExtractDynamic,
+         (uint32_t)spv::Op::OpVectorInsertDynamic,
+         (uint32_t)spv::Op::OpVectorShuffle,
+         (uint32_t)spv::Op::OpCompositeConstruct,
+         (uint32_t)spv::Op::OpCompositeExtract,
+         (uint32_t)spv::Op::OpCompositeInsert,
+         (uint32_t)spv::Op::OpCopyObject,
+         (uint32_t)spv::Op::OpTranspose,
+         (uint32_t)spv::Op::OpSampledImage,
+         (uint32_t)spv::Op::OpImageSampleImplicitLod,
+         (uint32_t)spv::Op::OpImageSampleExplicitLod,
+         (uint32_t)spv::Op::OpImageSampleDrefImplicitLod,
+         (uint32_t)spv::Op::OpImageSampleDrefExplicitLod,
+         (uint32_t)spv::Op::OpImageSampleProjImplicitLod,
+         (uint32_t)spv::Op::OpImageSampleProjExplicitLod,
+         (uint32_t)spv::Op::OpImageSampleProjDrefImplicitLod,
+         (uint32_t)spv::Op::OpImageSampleProjDrefExplicitLod,
+         (uint32_t)spv::Op::OpImageFetch,
+         (uint32_t)spv::Op::OpImageGather,
+         (uint32_t)spv::Op::OpImageDrefGather,
+         (uint32_t)spv::Op::OpImageRead,
+         (uint32_t)spv::Op::OpImage,
+         (uint32_t)spv::Op::OpImageQueryFormat,
+         (uint32_t)spv::Op::OpImageQueryOrder,
+         (uint32_t)spv::Op::OpImageQuerySizeLod,
+         (uint32_t)spv::Op::OpImageQuerySize,
+         (uint32_t)spv::Op::OpImageQueryLevels,
+         (uint32_t)spv::Op::OpImageQuerySamples,
+         (uint32_t)spv::Op::OpConvertFToU,
+         (uint32_t)spv::Op::OpConvertFToS,
+         (uint32_t)spv::Op::OpConvertSToF,
+         (uint32_t)spv::Op::OpConvertUToF,
+         (uint32_t)spv::Op::OpUConvert,
+         (uint32_t)spv::Op::OpSConvert,
+         (uint32_t)spv::Op::OpFConvert,
+         (uint32_t)spv::Op::OpQuantizeToF16,
+         (uint32_t)spv::Op::OpBitcast,
+         (uint32_t)spv::Op::OpSNegate,
+         (uint32_t)spv::Op::OpFNegate,
+         (uint32_t)spv::Op::OpIAdd,
+         (uint32_t)spv::Op::OpFAdd,
+         (uint32_t)spv::Op::OpISub,
+         (uint32_t)spv::Op::OpFSub,
+         (uint32_t)spv::Op::OpIMul,
+         (uint32_t)spv::Op::OpFMul,
+         (uint32_t)spv::Op::OpUDiv,
+         (uint32_t)spv::Op::OpSDiv,
+         (uint32_t)spv::Op::OpFDiv,
+         (uint32_t)spv::Op::OpUMod,
+         (uint32_t)spv::Op::OpSRem,
+         (uint32_t)spv::Op::OpSMod,
+         (uint32_t)spv::Op::OpFRem,
+         (uint32_t)spv::Op::OpFMod,
+         (uint32_t)spv::Op::OpVectorTimesScalar,
+         (uint32_t)spv::Op::OpMatrixTimesScalar,
+         (uint32_t)spv::Op::OpVectorTimesMatrix,
+         (uint32_t)spv::Op::OpMatrixTimesVector,
+         (uint32_t)spv::Op::OpMatrixTimesMatrix,
+         (uint32_t)spv::Op::OpOuterProduct,
+         (uint32_t)spv::Op::OpDot,
+         (uint32_t)spv::Op::OpIAddCarry,
+         (uint32_t)spv::Op::OpISubBorrow,
+         (uint32_t)spv::Op::OpUMulExtended,
+         (uint32_t)spv::Op::OpSMulExtended,
+         (uint32_t)spv::Op::OpAny,
+         (uint32_t)spv::Op::OpAll,
+         (uint32_t)spv::Op::OpIsNan,
+         (uint32_t)spv::Op::OpIsInf,
+         (uint32_t)spv::Op::OpLogicalEqual,
+         (uint32_t)spv::Op::OpLogicalNotEqual,
+         (uint32_t)spv::Op::OpLogicalOr,
+         (uint32_t)spv::Op::OpLogicalAnd,
+         (uint32_t)spv::Op::OpLogicalNot,
+         (uint32_t)spv::Op::OpSelect,
+         (uint32_t)spv::Op::OpIEqual,
+         (uint32_t)spv::Op::OpINotEqual,
+         (uint32_t)spv::Op::OpUGreaterThan,
+         (uint32_t)spv::Op::OpSGreaterThan,
+         (uint32_t)spv::Op::OpUGreaterThanEqual,
+         (uint32_t)spv::Op::OpSGreaterThanEqual,
+         (uint32_t)spv::Op::OpULessThan,
+         (uint32_t)spv::Op::OpSLessThan,
+         (uint32_t)spv::Op::OpULessThanEqual,
+         (uint32_t)spv::Op::OpSLessThanEqual,
+         (uint32_t)spv::Op::OpFOrdEqual,
+         (uint32_t)spv::Op::OpFUnordEqual,
+         (uint32_t)spv::Op::OpFOrdNotEqual,
+         (uint32_t)spv::Op::OpFUnordNotEqual,
+         (uint32_t)spv::Op::OpFOrdLessThan,
+         (uint32_t)spv::Op::OpFUnordLessThan,
+         (uint32_t)spv::Op::OpFOrdGreaterThan,
+         (uint32_t)spv::Op::OpFUnordGreaterThan,
+         (uint32_t)spv::Op::OpFOrdLessThanEqual,
+         (uint32_t)spv::Op::OpFUnordLessThanEqual,
+         (uint32_t)spv::Op::OpFOrdGreaterThanEqual,
+         (uint32_t)spv::Op::OpFUnordGreaterThanEqual,
+         (uint32_t)spv::Op::OpShiftRightLogical,
+         (uint32_t)spv::Op::OpShiftRightArithmetic,
+         (uint32_t)spv::Op::OpShiftLeftLogical,
+         (uint32_t)spv::Op::OpBitwiseOr,
+         (uint32_t)spv::Op::OpBitwiseXor,
+         (uint32_t)spv::Op::OpBitwiseAnd,
+         (uint32_t)spv::Op::OpNot,
+         (uint32_t)spv::Op::OpBitFieldInsert,
+         (uint32_t)spv::Op::OpBitFieldSExtract,
+         (uint32_t)spv::Op::OpBitFieldUExtract,
+         (uint32_t)spv::Op::OpBitReverse,
+         (uint32_t)spv::Op::OpBitCount,
+         (uint32_t)spv::Op::OpPhi,
+         (uint32_t)spv::Op::OpImageSparseSampleImplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleExplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleDrefImplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleDrefExplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleProjImplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleProjExplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+         (uint32_t)spv::Op::OpImageSparseFetch,
+         (uint32_t)spv::Op::OpImageSparseGather,
+         (uint32_t)spv::Op::OpImageSparseDrefGather,
+         (uint32_t)spv::Op::OpImageSparseTexelsResident,
+         (uint32_t)spv::Op::OpImageSparseRead,
+         (uint32_t)spv::Op::OpSizeOf});
   }
 }
 
 void IRContext::AddCombinatorsForExtension(Instruction* extension) {
-  assert(extension->opcode() == SpvOpExtInstImport &&
+  assert(extension->opcode() == spv::Op::OpExtInstImport &&
          "Expecting an import of an extension's instruction set.");
   const std::string extension_name = extension->GetInOperand(0).AsString();
   if (extension_name == "GLSL.std.450") {
-    combinator_ops_[extension->result_id()] = {GLSLstd450Round,
-                                               GLSLstd450RoundEven,
-                                               GLSLstd450Trunc,
-                                               GLSLstd450FAbs,
-                                               GLSLstd450SAbs,
-                                               GLSLstd450FSign,
-                                               GLSLstd450SSign,
-                                               GLSLstd450Floor,
-                                               GLSLstd450Ceil,
-                                               GLSLstd450Fract,
-                                               GLSLstd450Radians,
-                                               GLSLstd450Degrees,
-                                               GLSLstd450Sin,
-                                               GLSLstd450Cos,
-                                               GLSLstd450Tan,
-                                               GLSLstd450Asin,
-                                               GLSLstd450Acos,
-                                               GLSLstd450Atan,
-                                               GLSLstd450Sinh,
-                                               GLSLstd450Cosh,
-                                               GLSLstd450Tanh,
-                                               GLSLstd450Asinh,
-                                               GLSLstd450Acosh,
-                                               GLSLstd450Atanh,
-                                               GLSLstd450Atan2,
-                                               GLSLstd450Pow,
-                                               GLSLstd450Exp,
-                                               GLSLstd450Log,
-                                               GLSLstd450Exp2,
-                                               GLSLstd450Log2,
-                                               GLSLstd450Sqrt,
-                                               GLSLstd450InverseSqrt,
-                                               GLSLstd450Determinant,
-                                               GLSLstd450MatrixInverse,
-                                               GLSLstd450ModfStruct,
-                                               GLSLstd450FMin,
-                                               GLSLstd450UMin,
-                                               GLSLstd450SMin,
-                                               GLSLstd450FMax,
-                                               GLSLstd450UMax,
-                                               GLSLstd450SMax,
-                                               GLSLstd450FClamp,
-                                               GLSLstd450UClamp,
-                                               GLSLstd450SClamp,
-                                               GLSLstd450FMix,
-                                               GLSLstd450IMix,
-                                               GLSLstd450Step,
-                                               GLSLstd450SmoothStep,
-                                               GLSLstd450Fma,
-                                               GLSLstd450FrexpStruct,
-                                               GLSLstd450Ldexp,
-                                               GLSLstd450PackSnorm4x8,
-                                               GLSLstd450PackUnorm4x8,
-                                               GLSLstd450PackSnorm2x16,
-                                               GLSLstd450PackUnorm2x16,
-                                               GLSLstd450PackHalf2x16,
-                                               GLSLstd450PackDouble2x32,
-                                               GLSLstd450UnpackSnorm2x16,
-                                               GLSLstd450UnpackUnorm2x16,
-                                               GLSLstd450UnpackHalf2x16,
-                                               GLSLstd450UnpackSnorm4x8,
-                                               GLSLstd450UnpackUnorm4x8,
-                                               GLSLstd450UnpackDouble2x32,
-                                               GLSLstd450Length,
-                                               GLSLstd450Distance,
-                                               GLSLstd450Cross,
-                                               GLSLstd450Normalize,
-                                               GLSLstd450FaceForward,
-                                               GLSLstd450Reflect,
-                                               GLSLstd450Refract,
-                                               GLSLstd450FindILsb,
-                                               GLSLstd450FindSMsb,
-                                               GLSLstd450FindUMsb,
-                                               GLSLstd450InterpolateAtCentroid,
-                                               GLSLstd450InterpolateAtSample,
-                                               GLSLstd450InterpolateAtOffset,
-                                               GLSLstd450NMin,
-                                               GLSLstd450NMax,
-                                               GLSLstd450NClamp};
+    combinator_ops_[extension->result_id()] = {
+        (uint32_t)GLSLstd450Round,
+        (uint32_t)GLSLstd450RoundEven,
+        (uint32_t)GLSLstd450Trunc,
+        (uint32_t)GLSLstd450FAbs,
+        (uint32_t)GLSLstd450SAbs,
+        (uint32_t)GLSLstd450FSign,
+        (uint32_t)GLSLstd450SSign,
+        (uint32_t)GLSLstd450Floor,
+        (uint32_t)GLSLstd450Ceil,
+        (uint32_t)GLSLstd450Fract,
+        (uint32_t)GLSLstd450Radians,
+        (uint32_t)GLSLstd450Degrees,
+        (uint32_t)GLSLstd450Sin,
+        (uint32_t)GLSLstd450Cos,
+        (uint32_t)GLSLstd450Tan,
+        (uint32_t)GLSLstd450Asin,
+        (uint32_t)GLSLstd450Acos,
+        (uint32_t)GLSLstd450Atan,
+        (uint32_t)GLSLstd450Sinh,
+        (uint32_t)GLSLstd450Cosh,
+        (uint32_t)GLSLstd450Tanh,
+        (uint32_t)GLSLstd450Asinh,
+        (uint32_t)GLSLstd450Acosh,
+        (uint32_t)GLSLstd450Atanh,
+        (uint32_t)GLSLstd450Atan2,
+        (uint32_t)GLSLstd450Pow,
+        (uint32_t)GLSLstd450Exp,
+        (uint32_t)GLSLstd450Log,
+        (uint32_t)GLSLstd450Exp2,
+        (uint32_t)GLSLstd450Log2,
+        (uint32_t)GLSLstd450Sqrt,
+        (uint32_t)GLSLstd450InverseSqrt,
+        (uint32_t)GLSLstd450Determinant,
+        (uint32_t)GLSLstd450MatrixInverse,
+        (uint32_t)GLSLstd450ModfStruct,
+        (uint32_t)GLSLstd450FMin,
+        (uint32_t)GLSLstd450UMin,
+        (uint32_t)GLSLstd450SMin,
+        (uint32_t)GLSLstd450FMax,
+        (uint32_t)GLSLstd450UMax,
+        (uint32_t)GLSLstd450SMax,
+        (uint32_t)GLSLstd450FClamp,
+        (uint32_t)GLSLstd450UClamp,
+        (uint32_t)GLSLstd450SClamp,
+        (uint32_t)GLSLstd450FMix,
+        (uint32_t)GLSLstd450IMix,
+        (uint32_t)GLSLstd450Step,
+        (uint32_t)GLSLstd450SmoothStep,
+        (uint32_t)GLSLstd450Fma,
+        (uint32_t)GLSLstd450FrexpStruct,
+        (uint32_t)GLSLstd450Ldexp,
+        (uint32_t)GLSLstd450PackSnorm4x8,
+        (uint32_t)GLSLstd450PackUnorm4x8,
+        (uint32_t)GLSLstd450PackSnorm2x16,
+        (uint32_t)GLSLstd450PackUnorm2x16,
+        (uint32_t)GLSLstd450PackHalf2x16,
+        (uint32_t)GLSLstd450PackDouble2x32,
+        (uint32_t)GLSLstd450UnpackSnorm2x16,
+        (uint32_t)GLSLstd450UnpackUnorm2x16,
+        (uint32_t)GLSLstd450UnpackHalf2x16,
+        (uint32_t)GLSLstd450UnpackSnorm4x8,
+        (uint32_t)GLSLstd450UnpackUnorm4x8,
+        (uint32_t)GLSLstd450UnpackDouble2x32,
+        (uint32_t)GLSLstd450Length,
+        (uint32_t)GLSLstd450Distance,
+        (uint32_t)GLSLstd450Cross,
+        (uint32_t)GLSLstd450Normalize,
+        (uint32_t)GLSLstd450FaceForward,
+        (uint32_t)GLSLstd450Reflect,
+        (uint32_t)GLSLstd450Refract,
+        (uint32_t)GLSLstd450FindILsb,
+        (uint32_t)GLSLstd450FindSMsb,
+        (uint32_t)GLSLstd450FindUMsb,
+        (uint32_t)GLSLstd450InterpolateAtCentroid,
+        (uint32_t)GLSLstd450InterpolateAtSample,
+        (uint32_t)GLSLstd450InterpolateAtOffset,
+        (uint32_t)GLSLstd450NMin,
+        (uint32_t)GLSLstd450NMax,
+        (uint32_t)GLSLstd450NClamp};
   } else {
     // Map the result id to the empty set.
     combinator_ops_[extension->result_id()];
@@ -713,8 +718,9 @@
 }
 
 void IRContext::InitializeCombinators() {
-  get_feature_mgr()->GetCapabilities()->ForEach(
-      [this](SpvCapability cap) { AddCombinatorsForCapability(cap); });
+  get_feature_mgr()->GetCapabilities()->ForEach([this](spv::Capability cap) {
+    AddCombinatorsForCapability(uint32_t(cap));
+  });
 
   for (auto& extension : module()->ext_inst_imports()) {
     AddCombinatorsForExtension(&extension);
@@ -724,8 +730,8 @@
 }
 
 void IRContext::RemoveFromIdToName(const Instruction* inst) {
-  if (id_to_name_ &&
-      (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
+  if (id_to_name_ && (inst->opcode() == spv::Op::OpName ||
+                      inst->opcode() == spv::Op::OpMemberName)) {
     auto range = id_to_name_->equal_range(inst->GetSingleWordInOperand(0));
     for (auto it = range.first; it != range.second; ++it) {
       if (it->second == inst) {
@@ -754,15 +760,17 @@
 
 uint32_t IRContext::FindBuiltinInputVar(uint32_t builtin) {
   for (auto& a : module_->annotations()) {
-    if (a.opcode() != SpvOpDecorate) continue;
-    if (a.GetSingleWordInOperand(kSpvDecorateDecorationInIdx) !=
-        SpvDecorationBuiltIn)
+    if (spv::Op(a.opcode()) != spv::Op::OpDecorate) continue;
+    if (spv::Decoration(a.GetSingleWordInOperand(
+            kSpvDecorateDecorationInIdx)) != spv::Decoration::BuiltIn)
       continue;
     if (a.GetSingleWordInOperand(kSpvDecorateBuiltinInIdx) != builtin) continue;
     uint32_t target_id = a.GetSingleWordInOperand(kSpvDecorateTargetIdInIdx);
     Instruction* b_var = get_def_use_mgr()->GetDef(target_id);
-    if (b_var->opcode() != SpvOpVariable) continue;
-    if (b_var->GetSingleWordInOperand(0) != SpvStorageClassInput) continue;
+    if (b_var->opcode() != spv::Op::OpVariable) continue;
+    if (spv::StorageClass(b_var->GetSingleWordInOperand(0)) !=
+        spv::StorageClass::Input)
+      continue;
     return target_id;
   }
   return 0;
@@ -798,39 +806,39 @@
     // TODO(greg-lunarg): Add support for all builtins
     analysis::TypeManager* type_mgr = get_type_mgr();
     analysis::Type* reg_type;
-    switch (builtin) {
-      case SpvBuiltInFragCoord: {
+    switch (spv::BuiltIn(builtin)) {
+      case spv::BuiltIn::FragCoord: {
         analysis::Float float_ty(32);
         analysis::Type* reg_float_ty = type_mgr->GetRegisteredType(&float_ty);
         analysis::Vector v4float_ty(reg_float_ty, 4);
         reg_type = type_mgr->GetRegisteredType(&v4float_ty);
         break;
       }
-      case SpvBuiltInVertexIndex:
-      case SpvBuiltInInstanceIndex:
-      case SpvBuiltInPrimitiveId:
-      case SpvBuiltInInvocationId:
-      case SpvBuiltInSubgroupLocalInvocationId: {
+      case spv::BuiltIn::VertexIndex:
+      case spv::BuiltIn::InstanceIndex:
+      case spv::BuiltIn::PrimitiveId:
+      case spv::BuiltIn::InvocationId:
+      case spv::BuiltIn::SubgroupLocalInvocationId: {
         analysis::Integer uint_ty(32, false);
         reg_type = type_mgr->GetRegisteredType(&uint_ty);
         break;
       }
-      case SpvBuiltInGlobalInvocationId:
-      case SpvBuiltInLaunchIdNV: {
+      case spv::BuiltIn::GlobalInvocationId:
+      case spv::BuiltIn::LaunchIdNV: {
         analysis::Integer uint_ty(32, false);
         analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
         analysis::Vector v3uint_ty(reg_uint_ty, 3);
         reg_type = type_mgr->GetRegisteredType(&v3uint_ty);
         break;
       }
-      case SpvBuiltInTessCoord: {
+      case spv::BuiltIn::TessCoord: {
         analysis::Float float_ty(32);
         analysis::Type* reg_float_ty = type_mgr->GetRegisteredType(&float_ty);
         analysis::Vector v3float_ty(reg_float_ty, 3);
         reg_type = type_mgr->GetRegisteredType(&v3float_ty);
         break;
       }
-      case SpvBuiltInSubgroupLtMask: {
+      case spv::BuiltIn::SubgroupLtMask: {
         analysis::Integer uint_ty(32, false);
         analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
         analysis::Vector v4uint_ty(reg_uint_ty, 4);
@@ -844,17 +852,17 @@
     }
     uint32_t type_id = type_mgr->GetTypeInstruction(reg_type);
     uint32_t varTyPtrId =
-        type_mgr->FindPointerToType(type_id, SpvStorageClassInput);
+        type_mgr->FindPointerToType(type_id, spv::StorageClass::Input);
     // TODO(1841): Handle id overflow.
     var_id = TakeNextId();
     std::unique_ptr<Instruction> newVarOp(
-        new Instruction(this, SpvOpVariable, varTyPtrId, var_id,
+        new Instruction(this, spv::Op::OpVariable, varTyPtrId, var_id,
                         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                          {SpvStorageClassInput}}}));
+                          {uint32_t(spv::StorageClass::Input)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*newVarOp);
     module()->AddGlobalValue(std::move(newVarOp));
-    get_decoration_mgr()->AddDecorationVal(var_id, SpvDecorationBuiltIn,
-                                           builtin);
+    get_decoration_mgr()->AddDecorationVal(
+        var_id, uint32_t(spv::Decoration::BuiltIn), builtin);
     AddVarToEntryPoints(var_id);
   }
   builtin_var_id_map_[builtin] = var_id;
@@ -864,7 +872,7 @@
 void IRContext::AddCalls(const Function* func, std::queue<uint32_t>* todo) {
   for (auto bi = func->begin(); bi != func->end(); ++bi)
     for (auto ii = bi->begin(); ii != bi->end(); ++ii)
-      if (ii->opcode() == SpvOpFunctionCall)
+      if (ii->opcode() == spv::Op::OpFunctionCall)
         todo->push(ii->GetSingleWordInOperand(0));
 }
 
@@ -889,12 +897,12 @@
   for (auto& a : annotations()) {
     // TODO: Handle group decorations as well.  Currently not generate by any
     // front-end, but could be coming.
-    if (a.opcode() == SpvOp::SpvOpDecorate) {
-      if (a.GetSingleWordOperand(1) ==
-          SpvDecoration::SpvDecorationLinkageAttributes) {
+    if (a.opcode() == spv::Op::OpDecorate) {
+      if (spv::Decoration(a.GetSingleWordOperand(1)) ==
+          spv::Decoration::LinkageAttributes) {
         uint32_t lastOperand = a.NumOperands() - 1;
-        if (a.GetSingleWordOperand(lastOperand) ==
-            SpvLinkageType::SpvLinkageTypeExport) {
+        if (spv::LinkageType(a.GetSingleWordOperand(lastOperand)) ==
+            spv::LinkageType::Export) {
           uint32_t id = a.GetSingleWordOperand(0);
           if (GetFunction(id)) {
             roots.push(id);
@@ -1058,5 +1066,26 @@
   return GetDominatorAnalysis(enclosing_function)
       ->Dominates(enclosing_function->entry().get(), &bb);
 }
+
+spv::ExecutionModel IRContext::GetStage() {
+  const auto& entry_points = module()->entry_points();
+  if (entry_points.empty()) {
+    return spv::ExecutionModel::Max;
+  }
+
+  uint32_t stage = entry_points.begin()->GetSingleWordInOperand(
+      kEntryPointExecutionModelInIdx);
+  auto it = std::find_if(
+      entry_points.begin(), entry_points.end(), [stage](const Instruction& x) {
+        return x.GetSingleWordInOperand(kEntryPointExecutionModelInIdx) !=
+               stage;
+      });
+  if (it != entry_points.end()) {
+    EmitErrorMessage("Mixed stage shader module not supported", &(*it));
+  }
+
+  return static_cast<spv::ExecutionModel>(stage);
+}
+
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/ir_context.h b/third_party/SPIRV-Tools/source/opt/ir_context.h
index 2f27942..d4dbbaa 100644
--- a/third_party/SPIRV-Tools/source/opt/ir_context.h
+++ b/third_party/SPIRV-Tools/source/opt/ir_context.h
@@ -35,6 +35,7 @@
 #include "source/opt/dominator_analysis.h"
 #include "source/opt/feature_manager.h"
 #include "source/opt/fold.h"
+#include "source/opt/liveness.h"
 #include "source/opt/loop_descriptor.h"
 #include "source/opt/module.h"
 #include "source/opt/register_pressure.h"
@@ -81,6 +82,7 @@
     kAnalysisConstants = 1 << 14,
     kAnalysisTypes = 1 << 15,
     kAnalysisDebugInfo = 1 << 16,
+    kAnalysisLiveness = 1 << 17,
     kAnalysisEnd = 1 << 17
   };
 
@@ -201,7 +203,7 @@
   inline IteratorRange<Module::const_inst_iterator> ext_inst_debuginfo() const;
 
   // Add |capability| to the module, if it is not already enabled.
-  inline void AddCapability(SpvCapability capability);
+  inline void AddCapability(spv::Capability capability);
 
   // Appends a capability instruction to this module.
   inline void AddCapability(std::unique_ptr<Instruction>&& c);
@@ -248,6 +250,15 @@
     return def_use_mgr_.get();
   }
 
+  // Returns a pointer to a liveness manager.  If the liveness manager is
+  // invalid, it is rebuilt first.
+  analysis::LivenessManager* get_liveness_mgr() {
+    if (!AreAnalysesValid(kAnalysisLiveness)) {
+      BuildLivenessManager();
+    }
+    return liveness_mgr_.get();
+  }
+
   // Returns a pointer to a value number table.  If the liveness analysis is
   // invalid, it is rebuilt first.
   ValueNumberTable* GetValueNumberTable() {
@@ -475,14 +486,14 @@
     if (!AreAnalysesValid(kAnalysisCombinators)) {
       InitializeCombinators();
     }
-    const uint32_t kExtInstSetIdInIndx = 0;
-    const uint32_t kExtInstInstructionInIndx = 1;
+    constexpr uint32_t kExtInstSetIdInIndx = 0;
+    constexpr uint32_t kExtInstInstructionInIndx = 1;
 
-    if (inst->opcode() != SpvOpExtInst) {
-      return combinator_ops_[0].count(inst->opcode()) != 0;
+    if (inst->opcode() != spv::Op::OpExtInst) {
+      return combinator_ops_[0].count(uint32_t(inst->opcode())) != 0;
     } else {
       uint32_t set = inst->GetSingleWordInOperand(kExtInstSetIdInIndx);
-      uint32_t op = inst->GetSingleWordInOperand(kExtInstInstructionInIndx);
+      auto op = inst->GetSingleWordInOperand(kExtInstInstructionInIndx);
       return combinator_ops_[set].count(op) != 0;
     }
   }
@@ -591,7 +602,7 @@
   }
 
   Function* GetFunction(Instruction* inst) {
-    if (inst->opcode() != SpvOpFunction) {
+    if (inst->opcode() != spv::Op::OpFunction) {
       return nullptr;
     }
     return GetFunction(inst->result_id());
@@ -625,6 +636,10 @@
   // the function that contains |bb|.
   bool IsReachable(const opt::BasicBlock& bb);
 
+  // Return the stage of the module. Will generate error if entry points don't
+  // all have the same stage.
+  spv::ExecutionModel GetStage();
+
  private:
   // Builds the def-use manager from scratch, even if it was already valid.
   void BuildDefUseManager() {
@@ -632,6 +647,12 @@
     valid_analyses_ = valid_analyses_ | kAnalysisDefUse;
   }
 
+  // Builds the liveness manager from scratch, even if it was already valid.
+  void BuildLivenessManager() {
+    liveness_mgr_ = MakeUnique<analysis::LivenessManager>(this);
+    valid_analyses_ = valid_analyses_ | kAnalysisLiveness;
+  }
+
   // Builds the instruction-block map for the whole module.
   void BuildInstrToBlockMapping() {
     instr_to_block_.clear();
@@ -852,6 +873,9 @@
 
   std::unique_ptr<StructuredCFGAnalysis> struct_cfg_analysis_;
 
+  // The liveness manager for |module_|.
+  std::unique_ptr<analysis::LivenessManager> liveness_mgr_;
+
   // The maximum legal value for the id bound.
   uint32_t max_id_bound_;
 
@@ -1014,10 +1038,10 @@
   return ((const Module*)module_.get())->ext_inst_debuginfo();
 }
 
-void IRContext::AddCapability(SpvCapability capability) {
+void IRContext::AddCapability(spv::Capability capability) {
   if (!get_feature_mgr()->HasCapability(capability)) {
     std::unique_ptr<Instruction> capability_inst(new Instruction(
-        this, SpvOpCapability, 0, 0,
+        this, spv::Op::OpCapability, 0, 0,
         {{SPV_OPERAND_TYPE_CAPABILITY, {static_cast<uint32_t>(capability)}}}));
     AddCapability(std::move(capability_inst));
   }
@@ -1027,7 +1051,7 @@
   AddCombinatorsForCapability(c->GetSingleWordInOperand(0));
   if (feature_mgr_ != nullptr) {
     feature_mgr_->AddCapability(
-        static_cast<SpvCapability>(c->GetSingleWordInOperand(0)));
+        static_cast<spv::Capability>(c->GetSingleWordInOperand(0)));
   }
   if (AreAnalysesValid(kAnalysisDefUse)) {
     get_def_use_mgr()->AnalyzeInstDefUse(c.get());
@@ -1038,7 +1062,7 @@
 void IRContext::AddExtension(const std::string& ext_name) {
   std::vector<uint32_t> ext_words = spvtools::utils::MakeVector(ext_name);
   AddExtension(std::unique_ptr<Instruction>(
-      new Instruction(this, SpvOpExtension, 0u, 0u,
+      new Instruction(this, spv::Op::OpExtension, 0u, 0u,
                       {{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
 }
 
@@ -1055,7 +1079,7 @@
 void IRContext::AddExtInstImport(const std::string& name) {
   std::vector<uint32_t> ext_words = spvtools::utils::MakeVector(name);
   AddExtInstImport(std::unique_ptr<Instruction>(
-      new Instruction(this, SpvOpExtInstImport, 0u, TakeNextId(),
+      new Instruction(this, spv::Op::OpExtInstImport, 0u, TakeNextId(),
                       {{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
 }
 
@@ -1088,7 +1112,8 @@
 
 void IRContext::AddDebug2Inst(std::unique_ptr<Instruction>&& d) {
   if (AreAnalysesValid(kAnalysisNameMap)) {
-    if (d->opcode() == SpvOpName || d->opcode() == SpvOpMemberName) {
+    if (d->opcode() == spv::Op::OpName ||
+        d->opcode() == spv::Op::OpMemberName) {
       // OpName and OpMemberName do not have result-ids. The target of the
       // instruction is at InOperand index 0.
       id_to_name_->insert({d->GetSingleWordInOperand(0), d.get()});
@@ -1151,8 +1176,8 @@
 void IRContext::BuildIdToNameMap() {
   id_to_name_ = MakeUnique<std::multimap<uint32_t, Instruction*>>();
   for (Instruction& debug_inst : debugs2()) {
-    if (debug_inst.opcode() == SpvOpMemberName ||
-        debug_inst.opcode() == SpvOpName) {
+    if (debug_inst.opcode() == spv::Op::OpMemberName ||
+        debug_inst.opcode() == spv::Op::OpName) {
       id_to_name_->insert({debug_inst.GetSingleWordInOperand(0), &debug_inst});
     }
   }
@@ -1175,7 +1200,7 @@
   auto result = id_to_name_->equal_range(struct_type_id);
   for (auto i = result.first; i != result.second; ++i) {
     auto* name_instr = i->second;
-    if (name_instr->opcode() == SpvOpMemberName &&
+    if (name_instr->opcode() == spv::Op::OpMemberName &&
         name_instr->GetSingleWordInOperand(1) == index) {
       return name_instr;
     }
diff --git a/third_party/SPIRV-Tools/source/opt/ir_loader.cpp b/third_party/SPIRV-Tools/source/opt/ir_loader.cpp
index 734ad55..e9b7bbf 100644
--- a/third_party/SPIRV-Tools/source/opt/ir_loader.cpp
+++ b/third_party/SPIRV-Tools/source/opt/ir_loader.cpp
@@ -24,12 +24,13 @@
 #include "source/opt/reflect.h"
 #include "source/util/make_unique.h"
 
-static const uint32_t kExtInstSetIndex = 4;
-static const uint32_t kLexicalScopeIndex = 5;
-static const uint32_t kInlinedAtIndex = 6;
-
 namespace spvtools {
 namespace opt {
+namespace {
+constexpr uint32_t kExtInstSetIndex = 4;
+constexpr uint32_t kLexicalScopeIndex = 5;
+constexpr uint32_t kInlinedAtIndex = 6;
+}  // namespace
 
 IrLoader::IrLoader(const MessageConsumer& consumer, Module* m)
     : consumer_(consumer),
@@ -39,9 +40,9 @@
       last_dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
 bool IsLineInst(const spv_parsed_instruction_t* inst) {
-  const auto opcode = static_cast<SpvOp>(inst->opcode);
+  const auto opcode = static_cast<spv::Op>(inst->opcode);
   if (IsOpLineInst(opcode)) return true;
-  if (opcode != SpvOpExtInst) return false;
+  if (opcode != spv::Op::OpExtInst) return false;
   if (inst->ext_inst_type != SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100)
     return false;
   const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
@@ -63,8 +64,9 @@
   // If it is a DebugScope or DebugNoScope of debug extension, we do not
   // create a new instruction, but simply keep the information in
   // struct DebugScope.
-  const auto opcode = static_cast<SpvOp>(inst->opcode);
-  if (opcode == SpvOpExtInst && spvExtInstIsDebugInfo(inst->ext_inst_type)) {
+  const auto opcode = static_cast<spv::Op>(inst->opcode);
+  if (opcode == spv::Op::OpExtInst &&
+      spvExtInstIsDebugInfo(inst->ext_inst_type)) {
     const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
     if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
         inst->ext_inst_type ==
@@ -130,13 +132,13 @@
 
   // Handle function and basic block boundaries first, then normal
   // instructions.
-  if (opcode == SpvOpFunction) {
+  if (opcode == spv::Op::OpFunction) {
     if (function_ != nullptr) {
       Error(consumer_, src, loc, "function inside function");
       return false;
     }
     function_ = MakeUnique<Function>(std::move(spv_inst));
-  } else if (opcode == SpvOpFunctionEnd) {
+  } else if (opcode == spv::Op::OpFunctionEnd) {
     if (function_ == nullptr) {
       Error(consumer_, src, loc,
             "OpFunctionEnd without corresponding OpFunction");
@@ -149,7 +151,7 @@
     function_->SetFunctionEnd(std::move(spv_inst));
     module_->AddFunction(std::move(function_));
     function_ = nullptr;
-  } else if (opcode == SpvOpLabel) {
+  } else if (opcode == spv::Op::OpLabel) {
     if (function_ == nullptr) {
       Error(consumer_, src, loc, "OpLabel outside function");
       return false;
@@ -179,20 +181,20 @@
   } else {
     if (function_ == nullptr) {  // Outside function definition
       SPIRV_ASSERT(consumer_, block_ == nullptr);
-      if (opcode == SpvOpCapability) {
+      if (opcode == spv::Op::OpCapability) {
         module_->AddCapability(std::move(spv_inst));
-      } else if (opcode == SpvOpExtension) {
+      } else if (opcode == spv::Op::OpExtension) {
         module_->AddExtension(std::move(spv_inst));
-      } else if (opcode == SpvOpExtInstImport) {
+      } else if (opcode == spv::Op::OpExtInstImport) {
         module_->AddExtInstImport(std::move(spv_inst));
-      } else if (opcode == SpvOpMemoryModel) {
+      } else if (opcode == spv::Op::OpMemoryModel) {
         module_->SetMemoryModel(std::move(spv_inst));
-      } else if (opcode == SpvOpSamplerImageAddressingModeNV) {
+      } else if (opcode == spv::Op::OpSamplerImageAddressingModeNV) {
         module_->SetSampledImageAddressMode(std::move(spv_inst));
-      } else if (opcode == SpvOpEntryPoint) {
+      } else if (opcode == spv::Op::OpEntryPoint) {
         module_->AddEntryPoint(std::move(spv_inst));
-      } else if (opcode == SpvOpExecutionMode ||
-                 opcode == SpvOpExecutionModeId) {
+      } else if (opcode == spv::Op::OpExecutionMode ||
+                 opcode == spv::Op::OpExecutionModeId) {
         module_->AddExecutionMode(std::move(spv_inst));
       } else if (IsDebug1Inst(opcode)) {
         module_->AddDebug1Inst(std::move(spv_inst));
@@ -204,13 +206,13 @@
         module_->AddAnnotationInst(std::move(spv_inst));
       } else if (IsTypeInst(opcode)) {
         module_->AddType(std::move(spv_inst));
-      } else if (IsConstantInst(opcode) || opcode == SpvOpVariable ||
-                 opcode == SpvOpUndef) {
+      } else if (IsConstantInst(opcode) || opcode == spv::Op::OpVariable ||
+                 opcode == spv::Op::OpUndef) {
         module_->AddGlobalValue(std::move(spv_inst));
-      } else if (opcode == SpvOpExtInst &&
+      } else if (opcode == spv::Op::OpExtInst &&
                  spvExtInstIsDebugInfo(inst->ext_inst_type)) {
         module_->AddExtInstDebugInfo(std::move(spv_inst));
-      } else if (opcode == SpvOpExtInst &&
+      } else if (opcode == spv::Op::OpExtInst &&
                  spvExtInstIsNonSemantic(inst->ext_inst_type)) {
         // If there are no functions, add the non-semantic instructions to the
         // global values. Otherwise append it to the list of the last function.
@@ -229,11 +231,11 @@
         return false;
       }
     } else {
-      if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge)
+      if (opcode == spv::Op::OpLoopMerge || opcode == spv::Op::OpSelectionMerge)
         last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
       if (last_dbg_scope_.GetLexicalScope() != kNoDebugScope)
         spv_inst->SetDebugScope(last_dbg_scope_);
-      if (opcode == SpvOpExtInst &&
+      if (opcode == spv::Op::OpExtInst &&
           spvExtInstIsDebugInfo(inst->ext_inst_type)) {
         const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
         if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
@@ -322,7 +324,7 @@
         }
       } else {
         if (block_ == nullptr) {  // Inside function but outside blocks
-          if (opcode != SpvOpFunctionParameter) {
+          if (opcode != spv::Op::OpFunctionParameter) {
             Errorf(consumer_, src, loc,
                    "Non-OpFunctionParameter (opcode: %d) found inside "
                    "function but outside basic block",
diff --git a/third_party/SPIRV-Tools/source/opt/licm_pass.cpp b/third_party/SPIRV-Tools/source/opt/licm_pass.cpp
index 82851fd..514518b 100644
--- a/third_party/SPIRV-Tools/source/opt/licm_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/licm_pass.cpp
@@ -126,8 +126,8 @@
   }
   Instruction* insertion_point = &*pre_header_bb->tail();
   Instruction* previous_node = insertion_point->PreviousNode();
-  if (previous_node && (previous_node->opcode() == SpvOpLoopMerge ||
-                        previous_node->opcode() == SpvOpSelectionMerge)) {
+  if (previous_node && (previous_node->opcode() == spv::Op::OpLoopMerge ||
+                        previous_node->opcode() == spv::Op::OpSelectionMerge)) {
     insertion_point = previous_node;
   }
 
diff --git a/third_party/SPIRV-Tools/source/opt/liveness.cpp b/third_party/SPIRV-Tools/source/opt/liveness.cpp
new file mode 100644
index 0000000..fdf3f4e
--- /dev/null
+++ b/third_party/SPIRV-Tools/source/opt/liveness.cpp
@@ -0,0 +1,332 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+// Copyright (c) 2022 LunarG Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "source/opt/liveness.h"
+
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace opt {
+namespace analysis {
+namespace {
+constexpr uint32_t kDecorationLocationInIdx = 2;
+constexpr uint32_t kOpDecorateMemberMemberInIdx = 1;
+constexpr uint32_t kOpDecorateMemberLocationInIdx = 3;
+constexpr uint32_t kOpDecorateBuiltInLiteralInIdx = 2;
+constexpr uint32_t kOpDecorateMemberBuiltInLiteralInIdx = 3;
+}  // namespace
+
+LivenessManager::LivenessManager(IRContext* ctx) : ctx_(ctx), computed_(false) {
+  // Liveness sets computed when queried
+}
+
+void LivenessManager::InitializeAnalysis() {
+  live_locs_.clear();
+  live_builtins_.clear();
+  // Mark all builtins live for frag shader.
+  if (context()->GetStage() == spv::ExecutionModel::Fragment) {
+    live_builtins_.insert(uint32_t(spv::BuiltIn::PointSize));
+    live_builtins_.insert(uint32_t(spv::BuiltIn::ClipDistance));
+    live_builtins_.insert(uint32_t(spv::BuiltIn::CullDistance));
+  }
+}
+
+bool LivenessManager::IsAnalyzedBuiltin(uint32_t bi) {
+  // There are only three builtins that can be analyzed and removed between
+  // two stages: PointSize, ClipDistance and CullDistance. All others are
+  // always consumed implicitly by the downstream stage.
+  const auto builtin = spv::BuiltIn(bi);
+  return builtin == spv::BuiltIn::PointSize ||
+         builtin == spv::BuiltIn::ClipDistance ||
+         builtin == spv::BuiltIn::CullDistance;
+}
+
+bool LivenessManager::AnalyzeBuiltIn(uint32_t id) {
+  auto deco_mgr = context()->get_decoration_mgr();
+  bool saw_builtin = false;
+  // Analyze all builtin decorations of |id|.
+  (void)deco_mgr->ForEachDecoration(
+      id, uint32_t(spv::Decoration::BuiltIn),
+      [this, &saw_builtin](const Instruction& deco_inst) {
+        saw_builtin = true;
+        // No need to process builtins in frag shader. All assumed used.
+        if (context()->GetStage() == spv::ExecutionModel::Fragment) return;
+        uint32_t builtin = uint32_t(spv::BuiltIn::Max);
+        if (deco_inst.opcode() == spv::Op::OpDecorate)
+          builtin =
+              deco_inst.GetSingleWordInOperand(kOpDecorateBuiltInLiteralInIdx);
+        else if (deco_inst.opcode() == spv::Op::OpMemberDecorate)
+          builtin = deco_inst.GetSingleWordInOperand(
+              kOpDecorateMemberBuiltInLiteralInIdx);
+        else
+          assert(false && "unexpected decoration");
+        if (IsAnalyzedBuiltin(builtin)) live_builtins_.insert(builtin);
+      });
+  return saw_builtin;
+}
+
+void LivenessManager::MarkLocsLive(uint32_t start, uint32_t count) {
+  auto finish = start + count;
+  for (uint32_t u = start; u < finish; ++u) {
+    live_locs_.insert(u);
+  }
+}
+
+uint32_t LivenessManager::GetLocSize(const analysis::Type* type) const {
+  auto arr_type = type->AsArray();
+  if (arr_type) {
+    auto comp_type = arr_type->element_type();
+    auto len_info = arr_type->length_info();
+    assert(len_info.words[0] == analysis::Array::LengthInfo::kConstant &&
+           "unexpected array length");
+    auto comp_len = len_info.words[1];
+    return comp_len * GetLocSize(comp_type);
+  }
+  auto struct_type = type->AsStruct();
+  if (struct_type) {
+    uint32_t size = 0u;
+    for (auto& el_type : struct_type->element_types())
+      size += GetLocSize(el_type);
+    return size;
+  }
+  auto mat_type = type->AsMatrix();
+  if (mat_type) {
+    auto cnt = mat_type->element_count();
+    auto comp_type = mat_type->element_type();
+    return cnt * GetLocSize(comp_type);
+  }
+  auto vec_type = type->AsVector();
+  if (vec_type) {
+    auto comp_type = vec_type->element_type();
+    if (comp_type->AsInteger()) return 1;
+    auto float_type = comp_type->AsFloat();
+    assert(float_type && "unexpected vector component type");
+    auto width = float_type->width();
+    if (width == 32 || width == 16) return 1;
+    assert(width == 64 && "unexpected float type width");
+    auto comp_cnt = vec_type->element_count();
+    return (comp_cnt > 2) ? 2 : 1;
+  }
+  assert((type->AsInteger() || type->AsFloat()) && "unexpected input type");
+  return 1;
+}
+
+const analysis::Type* LivenessManager::GetComponentType(
+    uint32_t index, const analysis::Type* agg_type) const {
+  auto arr_type = agg_type->AsArray();
+  if (arr_type) return arr_type->element_type();
+  auto struct_type = agg_type->AsStruct();
+  if (struct_type) return struct_type->element_types()[index];
+  auto mat_type = agg_type->AsMatrix();
+  if (mat_type) return mat_type->element_type();
+  auto vec_type = agg_type->AsVector();
+  assert(vec_type && "unexpected non-aggregate type");
+  return vec_type->element_type();
+}
+
+uint32_t LivenessManager::GetLocOffset(uint32_t index,
+                                       const analysis::Type* agg_type) const {
+  auto arr_type = agg_type->AsArray();
+  if (arr_type) return index * GetLocSize(arr_type->element_type());
+  auto struct_type = agg_type->AsStruct();
+  if (struct_type) {
+    uint32_t offset = 0u;
+    uint32_t cnt = 0u;
+    for (auto& el_type : struct_type->element_types()) {
+      if (cnt == index) break;
+      offset += GetLocSize(el_type);
+      ++cnt;
+    }
+    return offset;
+  }
+  auto mat_type = agg_type->AsMatrix();
+  if (mat_type) return index * GetLocSize(mat_type->element_type());
+  auto vec_type = agg_type->AsVector();
+  assert(vec_type && "unexpected non-aggregate type");
+  auto comp_type = vec_type->element_type();
+  auto flt_type = comp_type->AsFloat();
+  if (flt_type && flt_type->width() == 64u && index >= 2u) return 1;
+  return 0;
+}
+
+void LivenessManager::AnalyzeAccessChainLoc(const Instruction* ac,
+                                            const analysis::Type** curr_type,
+                                            uint32_t* offset, bool* no_loc,
+                                            bool is_patch, bool input) {
+  analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr();
+  // For tesc, tese and geom input variables, and tesc output variables,
+  // first array index does not contribute to offset.
+  auto stage = context()->GetStage();
+  bool skip_first_index = false;
+  if ((input && (stage == spv::ExecutionModel::TessellationControl ||
+                 stage == spv::ExecutionModel::TessellationEvaluation ||
+                 stage == spv::ExecutionModel::Geometry)) ||
+      (!input && stage == spv::ExecutionModel::TessellationControl))
+    skip_first_index = !is_patch;
+  uint32_t ocnt = 0;
+  ac->WhileEachInOperand([this, &ocnt, def_use_mgr, type_mgr, deco_mgr,
+                          curr_type, offset, no_loc,
+                          skip_first_index](const uint32_t* opnd) {
+    if (ocnt >= 1) {
+      // Skip first index's contribution to offset if indicated
+      if (ocnt == 1 && skip_first_index) {
+        auto arr_type = (*curr_type)->AsArray();
+        assert(arr_type && "unexpected wrapper type");
+        *curr_type = arr_type->element_type();
+        ocnt++;
+        return true;
+      }
+      // If any non-constant index, mark the entire current object and return.
+      auto idx_inst = def_use_mgr->GetDef(*opnd);
+      if (idx_inst->opcode() != spv::Op::OpConstant) return false;
+      // If current type is struct, look for location decoration on member and
+      // reset offset if found.
+      auto index = idx_inst->GetSingleWordInOperand(0);
+      auto str_type = (*curr_type)->AsStruct();
+      if (str_type) {
+        uint32_t loc = 0;
+        auto str_type_id = type_mgr->GetId(str_type);
+        bool no_mem_loc = deco_mgr->WhileEachDecoration(
+            str_type_id, uint32_t(spv::Decoration::Location),
+            [&loc, index, no_loc](const Instruction& deco) {
+              assert(deco.opcode() == spv::Op::OpMemberDecorate &&
+                     "unexpected decoration");
+              if (deco.GetSingleWordInOperand(kOpDecorateMemberMemberInIdx) ==
+                  index) {
+                loc =
+                    deco.GetSingleWordInOperand(kOpDecorateMemberLocationInIdx);
+                *no_loc = false;
+                return false;
+              }
+              return true;
+            });
+        if (!no_mem_loc) {
+          *offset = loc;
+          *curr_type = GetComponentType(index, *curr_type);
+          ocnt++;
+          return true;
+        }
+      }
+
+      // Update offset and current type based on constant index.
+      *offset += GetLocOffset(index, *curr_type);
+      *curr_type = GetComponentType(index, *curr_type);
+    }
+    ocnt++;
+    return true;
+  });
+}
+
+void LivenessManager::MarkRefLive(const Instruction* ref, Instruction* var) {
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr();
+  // Find variable location if present.
+  uint32_t loc = 0;
+  auto var_id = var->result_id();
+  bool no_loc = deco_mgr->WhileEachDecoration(
+      var_id, uint32_t(spv::Decoration::Location),
+      [&loc](const Instruction& deco) {
+        assert(deco.opcode() == spv::Op::OpDecorate && "unexpected decoration");
+        loc = deco.GetSingleWordInOperand(kDecorationLocationInIdx);
+        return false;
+      });
+  // Find patch decoration if present
+  bool is_patch = !deco_mgr->WhileEachDecoration(
+      var_id, uint32_t(spv::Decoration::Patch), [](const Instruction& deco) {
+        if (deco.opcode() != spv::Op::OpDecorate)
+          assert(false && "unexpected decoration");
+        return false;
+      });
+  // If use is a load, mark all locations of var
+  auto ptr_type = type_mgr->GetType(var->type_id())->AsPointer();
+  assert(ptr_type && "unexpected var type");
+  auto var_type = ptr_type->pointee_type();
+  if (ref->opcode() == spv::Op::OpLoad) {
+    assert(!no_loc && "missing input variable location");
+    MarkLocsLive(loc, GetLocSize(var_type));
+    return;
+  }
+  // Mark just those locations indicated by access chain
+  assert((ref->opcode() == spv::Op::OpAccessChain ||
+          ref->opcode() == spv::Op::OpInBoundsAccessChain) &&
+         "unexpected use of input variable");
+  // Traverse access chain, compute location offset and type of reference
+  // through constant indices and mark those locs live. Assert if no location
+  // found.
+  uint32_t offset = loc;
+  auto curr_type = var_type;
+  AnalyzeAccessChainLoc(ref, &curr_type, &offset, &no_loc, is_patch);
+  assert(!no_loc && "missing input variable location");
+  MarkLocsLive(offset, GetLocSize(curr_type));
+}
+
+void LivenessManager::ComputeLiveness() {
+  InitializeAnalysis();
+  analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  // Process all input variables
+  for (auto& var : context()->types_values()) {
+    if (var.opcode() != spv::Op::OpVariable) {
+      continue;
+    }
+    analysis::Type* var_type = type_mgr->GetType(var.type_id());
+    analysis::Pointer* ptr_type = var_type->AsPointer();
+    if (ptr_type->storage_class() != spv::StorageClass::Input) {
+      continue;
+    }
+    // If var is builtin, mark live if analyzed and continue to next variable
+    auto var_id = var.result_id();
+    if (AnalyzeBuiltIn(var_id)) continue;
+    // If interface block with builtin members, mark live if analyzed and
+    // continue to next variable. Input interface blocks will only appear
+    // in tesc, tese and geom shaders. Will need to strip off one level of
+    // arrayness to get to block type.
+    auto pte_type = ptr_type->pointee_type();
+    auto arr_type = pte_type->AsArray();
+    if (arr_type) {
+      auto elt_type = arr_type->element_type();
+      auto str_type = elt_type->AsStruct();
+      if (str_type) {
+        auto str_type_id = type_mgr->GetId(str_type);
+        if (AnalyzeBuiltIn(str_type_id)) continue;
+      }
+    }
+    // Mark all used locations of var live
+    def_use_mgr->ForEachUser(var_id, [this, &var](Instruction* user) {
+      auto op = user->opcode();
+      if (op == spv::Op::OpEntryPoint || op == spv::Op::OpName ||
+          op == spv::Op::OpDecorate) {
+        return;
+      }
+      MarkRefLive(user, &var);
+    });
+  }
+}
+
+void LivenessManager::GetLiveness(std::unordered_set<uint32_t>* live_locs,
+                                  std::unordered_set<uint32_t>* live_builtins) {
+  if (!computed_) {
+    ComputeLiveness();
+    computed_ = true;
+  }
+  *live_locs = live_locs_;
+  *live_builtins = live_builtins_;
+}
+
+}  // namespace analysis
+}  // namespace opt
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/liveness.h b/third_party/SPIRV-Tools/source/opt/liveness.h
new file mode 100644
index 0000000..7d8a9fb
--- /dev/null
+++ b/third_party/SPIRV-Tools/source/opt/liveness.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+// Copyright (c) 2022 LunarG Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SOURCE_OPT_LIVENESS_H_
+#define SOURCE_OPT_LIVENESS_H_
+
+#include <cstdint>
+#include <unordered_set>
+
+namespace spvtools {
+namespace opt {
+
+class IRContext;
+class Instruction;
+
+namespace analysis {
+
+class Type;
+
+// This class represents the liveness of the input variables of a module
+class LivenessManager {
+ public:
+  LivenessManager(IRContext* ctx);
+
+  // Copy liveness info into |live_locs| and |builtin_locs|.
+  void GetLiveness(std::unordered_set<uint32_t>* live_locs,
+                   std::unordered_set<uint32_t>* live_builtins);
+
+  // Return true if builtin |bi| is being analyzed.
+  bool IsAnalyzedBuiltin(uint32_t bi);
+
+  // Determine starting loc |offset| and the type |cur_type| of
+  // access chain |ac|. Set |no_loc| to true if no loc found.
+  // |is_patch| indicates if patch variable. |input| is true
+  // if input variable, otherwise output variable.
+  void AnalyzeAccessChainLoc(const Instruction* ac,
+                             const analysis::Type** curr_type, uint32_t* offset,
+                             bool* no_loc, bool is_patch, bool input = true);
+
+  // Return size of |type_id| in units of locations
+  uint32_t GetLocSize(const analysis::Type* type) const;
+
+ private:
+  IRContext* context() const { return ctx_; }
+
+  // Initialize analysis
+  void InitializeAnalysis();
+
+  // Analyze |id| for builtin var and struct members. Return true if builtins
+  // found.
+  bool AnalyzeBuiltIn(uint32_t id);
+
+  // Mark all live locations resulting from |user| of |var| at |loc|.
+  void MarkRefLive(const Instruction* user, Instruction* var);
+
+  // Mark |count| locations starting at location |start|.
+  void MarkLocsLive(uint32_t start, uint32_t count);
+
+  // Return type of component of aggregate type |agg_type| at |index|
+  const analysis::Type* GetComponentType(uint32_t index,
+                                         const analysis::Type* agg_type) const;
+
+  // Return offset of |index| into aggregate type |agg_type| in units of
+  // input locations
+  uint32_t GetLocOffset(uint32_t index, const analysis::Type* agg_type) const;
+
+  // Populate live_locs_ and live_builtins_
+  void ComputeLiveness();
+
+  // IR context that owns this liveness manager.
+  IRContext* ctx_;
+
+  // True if live_locs_ and live_builtins_ are computed
+  bool computed_;
+
+  // Live locations
+  std::unordered_set<uint32_t> live_locs_;
+
+  // Live builtins
+  std::unordered_set<uint32_t> live_builtins_;
+};
+
+}  // namespace analysis
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // SOURCE_OPT_LIVENESS_H_
diff --git a/third_party/SPIRV-Tools/source/opt/local_access_chain_convert_pass.cpp b/third_party/SPIRV-Tools/source/opt/local_access_chain_convert_pass.cpp
index 9491798..66e8813 100644
--- a/third_party/SPIRV-Tools/source/opt/local_access_chain_convert_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/local_access_chain_convert_pass.cpp
@@ -23,16 +23,13 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
-
-const uint32_t kStoreValIdInIdx = 1;
-const uint32_t kAccessChainPtrIdInIdx = 0;
-
-}  // anonymous namespace
+constexpr uint32_t kStoreValIdInIdx = 1;
+constexpr uint32_t kAccessChainPtrIdInIdx = 0;
+}  // namespace
 
 void LocalAccessChainConvertPass::BuildAndAppendInst(
-    SpvOp opcode, uint32_t typeId, uint32_t resultId,
+    spv::Op opcode, uint32_t typeId, uint32_t resultId,
     const std::vector<Operand>& in_opnds,
     std::vector<std::unique_ptr<Instruction>>* newInsts) {
   std::unique_ptr<Instruction> newInst(
@@ -51,9 +48,9 @@
 
   *varId = ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx);
   const Instruction* varInst = get_def_use_mgr()->GetDef(*varId);
-  assert(varInst->opcode() == SpvOpVariable);
+  assert(varInst->opcode() == spv::Op::OpVariable);
   *varPteTypeId = GetPointeeTypeId(varInst);
-  BuildAndAppendInst(SpvOpLoad, *varPteTypeId, ldResultId,
+  BuildAndAppendInst(spv::Op::OpLoad, *varPteTypeId, ldResultId,
                      {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {*varId}}},
                      newInsts);
   return ldResultId;
@@ -108,7 +105,8 @@
 
   new_inst[0]->UpdateDebugInfoFrom(original_load);
   context()->get_decoration_mgr()->CloneDecorations(
-      original_load->result_id(), ldResultId, {SpvDecorationRelaxedPrecision});
+      original_load->result_id(), ldResultId,
+      {spv::Decoration::RelaxedPrecision});
   original_load->InsertBefore(std::move(new_inst));
   context()->get_debug_info_mgr()->AnalyzeDebugInst(
       original_load->PreviousNode());
@@ -123,7 +121,7 @@
   new_operands.emplace_back(
       Operand({spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ldResultId}}));
   AppendConstantOperands(address_inst, &new_operands);
-  original_load->SetOpcode(SpvOpCompositeExtract);
+  original_load->SetOpcode(spv::Op::OpCompositeExtract);
   original_load->ReplaceOperands(new_operands);
   context()->UpdateDefUse(original_load);
   return true;
@@ -136,7 +134,7 @@
     // An access chain with no indices is essentially a copy.  However, we still
     // have to create a new store because the old ones will be deleted.
     BuildAndAppendInst(
-        SpvOpStore, 0, 0,
+        spv::Op::OpStore, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
           {ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx)}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {valId}}},
@@ -154,7 +152,7 @@
   }
 
   context()->get_decoration_mgr()->CloneDecorations(
-      varId, ldResultId, {SpvDecorationRelaxedPrecision});
+      varId, ldResultId, {spv::Decoration::RelaxedPrecision});
 
   // Build and append Insert
   const uint32_t insResultId = TakeNextId();
@@ -165,14 +163,14 @@
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {valId}},
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ldResultId}}};
   AppendConstantOperands(ptrInst, &ins_in_opnds);
-  BuildAndAppendInst(SpvOpCompositeInsert, varPteTypeId, insResultId,
+  BuildAndAppendInst(spv::Op::OpCompositeInsert, varPteTypeId, insResultId,
                      ins_in_opnds, newInsts);
 
   context()->get_decoration_mgr()->CloneDecorations(
-      varId, insResultId, {SpvDecorationRelaxedPrecision});
+      varId, insResultId, {spv::Decoration::RelaxedPrecision});
 
   // Build and append Store
-  BuildAndAppendInst(SpvOpStore, 0, 0,
+  BuildAndAppendInst(spv::Op::OpStore, 0, 0,
                      {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {varId}},
                       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {insResultId}}},
                      newInsts);
@@ -185,10 +183,12 @@
   return acp->WhileEachInId([&inIdx, this](const uint32_t* tid) {
     if (inIdx > 0) {
       Instruction* opInst = get_def_use_mgr()->GetDef(*tid);
-      if (opInst->opcode() != SpvOpConstant) return false;
+      if (opInst->opcode() != spv::Op::OpConstant) return false;
       const auto* index =
           context()->get_constant_mgr()->GetConstantFromInst(opInst);
-      if (index->GetSignExtendedValue() > UINT32_MAX) return false;
+      int64_t index_value = index->GetSignExtendedValue();
+      if (index_value > UINT32_MAX) return false;
+      if (index_value < 0) return false;
     }
     ++inIdx;
     return true;
@@ -202,13 +202,13 @@
             user->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) {
           return true;
         }
-        SpvOp op = user->opcode();
-        if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
+        spv::Op op = user->opcode();
+        if (IsNonPtrAccessChain(op) || op == spv::Op::OpCopyObject) {
           if (!HasOnlySupportedRefs(user->result_id())) {
             return false;
           }
-        } else if (op != SpvOpStore && op != SpvOpLoad && op != SpvOpName &&
-                   !IsNonTypeDecorate(op)) {
+        } else if (op != spv::Op::OpStore && op != spv::Op::OpLoad &&
+                   op != spv::Op::OpName && !IsNonTypeDecorate(op)) {
           return false;
         }
         return true;
@@ -223,12 +223,12 @@
   for (auto bi = func->begin(); bi != func->end(); ++bi) {
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
       switch (ii->opcode()) {
-        case SpvOpStore:
-        case SpvOpLoad: {
+        case spv::Op::OpStore:
+        case spv::Op::OpLoad: {
           uint32_t varId;
           Instruction* ptrInst = GetPtr(&*ii, &varId);
           if (!IsTargetVar(varId)) break;
-          const SpvOp op = ptrInst->opcode();
+          const spv::Op op = ptrInst->opcode();
           // Rule out variables with non-supported refs eg function calls
           if (!HasOnlySupportedRefs(varId)) {
             seen_non_target_vars_.insert(varId);
@@ -274,7 +274,7 @@
     std::vector<Instruction*> dead_instructions;
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
       switch (ii->opcode()) {
-        case SpvOpLoad: {
+        case spv::Op::OpLoad: {
           uint32_t varId;
           Instruction* ptrInst = GetPtr(&*ii, &varId);
           if (!IsNonPtrAccessChain(ptrInst->opcode())) break;
@@ -284,7 +284,7 @@
           }
           modified = true;
         } break;
-        case SpvOpStore: {
+        case spv::Op::OpStore: {
           uint32_t varId;
           Instruction* store = &*ii;
           Instruction* ptrInst = GetPtr(store, &varId);
@@ -345,7 +345,7 @@
   // for the capability.  This pass is only looking at function scope symbols,
   // so we do not care if there are variable pointers on storage buffers.
   if (context()->get_feature_mgr()->HasCapability(
-          SpvCapabilityVariablePointers))
+          spv::Capability::VariablePointers))
     return false;
   // If any extension not in allowlist, return false
   for (auto& ei : get_module()->extensions()) {
@@ -357,7 +357,7 @@
   // around unknown extended
   // instruction sets even if they are non-semantic
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
@@ -373,7 +373,8 @@
   // support required in KillNamesAndDecorates().
   // TODO(greg-lunarg): Add support for OpGroupDecorate
   for (auto& ai : get_module()->annotations())
-    if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
+    if (ai.opcode() == spv::Op::OpGroupDecorate)
+      return Status::SuccessWithoutChange;
   // Do not process if any disallowed extensions are enabled
   if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
 
diff --git a/third_party/SPIRV-Tools/source/opt/local_access_chain_convert_pass.h b/third_party/SPIRV-Tools/source/opt/local_access_chain_convert_pass.h
index eabf864..0cda196 100644
--- a/third_party/SPIRV-Tools/source/opt/local_access_chain_convert_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/local_access_chain_convert_pass.h
@@ -64,7 +64,7 @@
 
   // Build instruction from |opcode|, |typeId|, |resultId|, and |in_opnds|.
   // Append to |newInsts|.
-  void BuildAndAppendInst(SpvOp opcode, uint32_t typeId, uint32_t resultId,
+  void BuildAndAppendInst(spv::Op opcode, uint32_t typeId, uint32_t resultId,
                           const std::vector<Operand>& in_opnds,
                           std::vector<std::unique_ptr<Instruction>>* newInsts);
 
@@ -94,8 +94,8 @@
   bool ReplaceAccessChainLoad(const Instruction* address_inst,
                               Instruction* original_load);
 
-  // Return true if all indices of access chain |acp| are OpConstant integers
-  // whose values can fit into an unsigned 32-bit value.
+  // Return true if all indices of the access chain |acp| are OpConstant
+  // integers whose signed values can be represented as unsigned 32-bit values.
   bool Is32BitConstantIndexAccessChain(const Instruction* acp) const;
 
   // Identify all function scope variables of target type which are
diff --git a/third_party/SPIRV-Tools/source/opt/local_single_block_elim_pass.cpp b/third_party/SPIRV-Tools/source/opt/local_single_block_elim_pass.cpp
index a58e8e4..c1789c8 100644
--- a/third_party/SPIRV-Tools/source/opt/local_single_block_elim_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/local_single_block_elim_pass.cpp
@@ -24,10 +24,8 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-const uint32_t kStoreValIdInIdx = 1;
-
-}  // anonymous namespace
+constexpr uint32_t kStoreValIdInIdx = 1;
+}  // namespace
 
 bool LocalSingleBlockLoadStoreElimPass::HasOnlySupportedRefs(uint32_t ptrId) {
   if (supported_ref_ptrs_.find(ptrId) != supported_ref_ptrs_.end()) return true;
@@ -37,13 +35,13 @@
             dbg_op == CommonDebugInfoDebugValue) {
           return true;
         }
-        SpvOp op = user->opcode();
-        if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
+        spv::Op op = user->opcode();
+        if (IsNonPtrAccessChain(op) || op == spv::Op::OpCopyObject) {
           if (!HasOnlySupportedRefs(user->result_id())) {
             return false;
           }
-        } else if (op != SpvOpStore && op != SpvOpLoad && op != SpvOpName &&
-                   !IsNonTypeDecorate(op)) {
+        } else if (op != spv::Op::OpStore && op != spv::Op::OpLoad &&
+                   op != spv::Op::OpName && !IsNonTypeDecorate(op)) {
           return false;
         }
         return true;
@@ -68,7 +66,7 @@
     for (auto ii = next; ii != bi->end(); ii = next) {
       ++next;
       switch (ii->opcode()) {
-        case SpvOpStore: {
+        case spv::Op::OpStore: {
           // Verify store variable is target type
           uint32_t varId;
           Instruction* ptrInst = GetPtr(&*ii, &varId);
@@ -77,7 +75,7 @@
           // If a store to the whole variable, remember it for succeeding
           // loads and stores. Otherwise forget any previous store to that
           // variable.
-          if (ptrInst->opcode() == SpvOpVariable) {
+          if (ptrInst->opcode() == spv::Op::OpVariable) {
             // If a previous store to same variable, mark the store
             // for deletion if not still used. Don't delete store
             // if debugging; let ssa-rewrite and DCE handle it
@@ -114,14 +112,14 @@
             var2load_.erase(varId);
           }
         } break;
-        case SpvOpLoad: {
+        case spv::Op::OpLoad: {
           // Verify store variable is target type
           uint32_t varId;
           Instruction* ptrInst = GetPtr(&*ii, &varId);
           if (!IsTargetVar(varId)) continue;
           if (!HasOnlySupportedRefs(varId)) continue;
           uint32_t replId = 0;
-          if (ptrInst->opcode() == SpvOpVariable) {
+          if (ptrInst->opcode() == spv::Op::OpVariable) {
             // If a load from a variable, look for a previous store or
             // load from that variable and use its value.
             auto si = var2store_.find(varId);
@@ -146,11 +144,11 @@
             instructions_to_kill.push_back(&*ii);
             modified = true;
           } else {
-            if (ptrInst->opcode() == SpvOpVariable)
+            if (ptrInst->opcode() == spv::Op::OpVariable)
               var2load_[varId] = &*ii;  // register load
           }
         } break;
-        case SpvOpFunctionCall: {
+        case spv::Op::OpFunctionCall: {
           // Conservatively assume all locals are redefined for now.
           // TODO(): Handle more optimally
           var2store_.clear();
@@ -192,7 +190,7 @@
   // around unknown extended
   // instruction sets even if they are non-semantic
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
@@ -205,14 +203,15 @@
 
 Pass::Status LocalSingleBlockLoadStoreElimPass::ProcessImpl() {
   // Assumes relaxed logical addressing only (see instruction.h).
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
     return Status::SuccessWithoutChange;
 
   // Do not process if module contains OpGroupDecorate. Additional
   // support required in KillNamesAndDecorates().
   // TODO(greg-lunarg): Add support for OpGroupDecorate
   for (auto& ai : get_module()->annotations())
-    if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
+    if (ai.opcode() == spv::Op::OpGroupDecorate)
+      return Status::SuccessWithoutChange;
   // If any extensions in the module are not explicitly supported,
   // return unmodified.
   if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
diff --git a/third_party/SPIRV-Tools/source/opt/local_single_store_elim_pass.cpp b/third_party/SPIRV-Tools/source/opt/local_single_store_elim_pass.cpp
index 8cdd0ab..e494689 100644
--- a/third_party/SPIRV-Tools/source/opt/local_single_store_elim_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/local_single_store_elim_pass.cpp
@@ -23,13 +23,10 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
-
-const uint32_t kStoreValIdInIdx = 1;
-const uint32_t kVariableInitIdInIdx = 1;
-
-}  // anonymous namespace
+constexpr uint32_t kStoreValIdInIdx = 1;
+constexpr uint32_t kVariableInitIdInIdx = 1;
+}  // namespace
 
 bool LocalSingleStoreElimPass::LocalSingleStoreElim(Function* func) {
   bool modified = false;
@@ -37,7 +34,7 @@
   // Check all function scope variables in |func|.
   BasicBlock* entry_block = &*func->begin();
   for (Instruction& inst : *entry_block) {
-    if (inst.opcode() != SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       break;
     }
 
@@ -57,7 +54,7 @@
   // around unknown extended
   // instruction sets even if they are non-semantic
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
@@ -70,7 +67,7 @@
 
 Pass::Status LocalSingleStoreElimPass::ProcessImpl() {
   // Assumes relaxed logical addressing only (see instruction.h)
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
     return Status::SuccessWithoutChange;
 
   // Do not process if any disallowed extensions are enabled
@@ -175,29 +172,9 @@
 
 bool LocalSingleStoreElimPass::RewriteDebugDeclares(Instruction* store_inst,
                                                     uint32_t var_id) {
-  std::unordered_set<Instruction*> invisible_decls;
   uint32_t value_id = store_inst->GetSingleWordInOperand(1);
-  bool modified =
-      context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
-          store_inst, var_id, value_id, store_inst, &invisible_decls);
-
-  // For cases like the argument passing for an inlined function, the value
-  // assignment is out of DebugDeclare's scope, but we have to preserve the
-  // value assignment information using DebugValue. Generally, we need
-  // ssa-rewrite analysis to decide a proper value assignment but at this point
-  // we confirm that |var_id| has a single store. We can safely add DebugValue.
-  if (!invisible_decls.empty()) {
-    BasicBlock* store_block = context()->get_instr_block(store_inst);
-    DominatorAnalysis* dominator_analysis =
-        context()->GetDominatorAnalysis(store_block->GetParent());
-    for (auto* decl : invisible_decls) {
-      if (dominator_analysis->Dominates(store_inst, decl)) {
-        context()->get_debug_info_mgr()->AddDebugValueForDecl(decl, value_id,
-                                                              decl, store_inst);
-        modified = true;
-      }
-    }
-  }
+  bool modified = context()->get_debug_info_mgr()->AddDebugValueForVariable(
+      store_inst, var_id, value_id, store_inst);
   modified |= context()->get_debug_info_mgr()->KillDebugDeclares(var_id);
   return modified;
 }
@@ -214,7 +191,7 @@
 
   for (Instruction* user : users) {
     switch (user->opcode()) {
-      case SpvOpStore:
+      case spv::Op::OpStore:
         // Since we are in the relaxed addressing mode, the use has to be the
         // base address of the store, and not the value being store.  Otherwise,
         // we would have a pointer to a pointer to function scope memory, which
@@ -226,19 +203,19 @@
           return nullptr;
         }
         break;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
         if (FeedsAStore(user)) {
           // Has a partial store.  Cannot propagate that.
           return nullptr;
         }
         break;
-      case SpvOpLoad:
-      case SpvOpImageTexelPointer:
-      case SpvOpName:
-      case SpvOpCopyObject:
+      case spv::Op::OpLoad:
+      case spv::Op::OpImageTexelPointer:
+      case spv::Op::OpName:
+      case spv::Op::OpCopyObject:
         break;
-      case SpvOpExtInst: {
+      case spv::Op::OpExtInst: {
         auto dbg_op = user->GetCommonDebugOpcode();
         if (dbg_op == CommonDebugInfoDebugDeclare ||
             dbg_op == CommonDebugInfoDebugValue) {
@@ -263,7 +240,7 @@
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   def_use_mgr->ForEachUser(var_inst, [users, this](Instruction* user) {
     users->push_back(user);
-    if (user->opcode() == SpvOpCopyObject) {
+    if (user->opcode() == spv::Op::OpCopyObject) {
       FindUses(user, users);
     }
   });
@@ -273,15 +250,15 @@
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   return !def_use_mgr->WhileEachUser(inst, [this](Instruction* user) {
     switch (user->opcode()) {
-      case SpvOpStore:
+      case spv::Op::OpStore:
         return false;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
-      case SpvOpCopyObject:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
+      case spv::Op::OpCopyObject:
         return !FeedsAStore(user);
-      case SpvOpLoad:
-      case SpvOpImageTexelPointer:
-      case SpvOpName:
+      case spv::Op::OpLoad:
+      case spv::Op::OpImageTexelPointer:
+      case spv::Op::OpName:
         return true;
       default:
         // Don't know if this instruction modifies the variable.
@@ -299,7 +276,7 @@
       context()->GetDominatorAnalysis(store_block->GetParent());
 
   uint32_t stored_id;
-  if (store_inst->opcode() == SpvOpStore)
+  if (store_inst->opcode() == spv::Op::OpStore)
     stored_id = store_inst->GetSingleWordInOperand(kStoreValIdInIdx);
   else
     stored_id = store_inst->GetSingleWordInOperand(kVariableInitIdInIdx);
@@ -307,12 +284,12 @@
   *all_rewritten = true;
   bool modified = false;
   for (Instruction* use : uses) {
-    if (use->opcode() == SpvOpStore) continue;
+    if (use->opcode() == spv::Op::OpStore) continue;
     auto dbg_op = use->GetCommonDebugOpcode();
     if (dbg_op == CommonDebugInfoDebugDeclare ||
         dbg_op == CommonDebugInfoDebugValue)
       continue;
-    if (use->opcode() == SpvOpLoad &&
+    if (use->opcode() == spv::Op::OpLoad &&
         dominator_analysis->Dominates(store_inst, use)) {
       modified = true;
       context()->KillNamesAndDecorates(use->result_id());
diff --git a/third_party/SPIRV-Tools/source/opt/loop_dependence.cpp b/third_party/SPIRV-Tools/source/opt/loop_dependence.cpp
index d8de699..d7256bf 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_dependence.cpp
+++ b/third_party/SPIRV-Tools/source/opt/loop_dependence.cpp
@@ -192,8 +192,8 @@
   Instruction* destination_access_chain = GetOperandDefinition(destination, 0);
 
   auto num_access_chains =
-      (source_access_chain->opcode() == SpvOpAccessChain) +
-      (destination_access_chain->opcode() == SpvOpAccessChain);
+      (source_access_chain->opcode() == spv::Op::OpAccessChain) +
+      (destination_access_chain->opcode() == spv::Op::OpAccessChain);
 
   // If neither is an access chain, then they are load/store to a variable.
   if (num_access_chains == 0) {
@@ -211,7 +211,8 @@
 
   // If only one is an access chain, it could be accessing a part of a struct
   if (num_access_chains == 1) {
-    auto source_is_chain = source_access_chain->opcode() == SpvOpAccessChain;
+    auto source_is_chain =
+        source_access_chain->opcode() == spv::Op::OpAccessChain;
     auto access_chain =
         source_is_chain ? source_access_chain : destination_access_chain;
     auto variable =
@@ -238,8 +239,8 @@
       GetOperandDefinition(destination_access_chain, 0);
 
   // Nested access chains are not supported yet, bail out.
-  if (source_array->opcode() == SpvOpAccessChain ||
-      destination_array->opcode() == SpvOpAccessChain) {
+  if (source_array->opcode() == spv::Op::OpAccessChain ||
+      destination_array->opcode() == spv::Op::OpAccessChain) {
     for (auto& entry : distance_vector->GetEntries()) {
       entry = DistanceEntry();
     }
diff --git a/third_party/SPIRV-Tools/source/opt/loop_dependence_helpers.cpp b/third_party/SPIRV-Tools/source/opt/loop_dependence_helpers.cpp
index de27a0a..929c940 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_dependence_helpers.cpp
+++ b/third_party/SPIRV-Tools/source/opt/loop_dependence_helpers.cpp
@@ -54,20 +54,20 @@
   }
   Instruction* lower_inst = GetOperandDefinition(cond_inst, 0);
   switch (cond_inst->opcode()) {
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual: {
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual: {
       // If we have a phi we are looking at the induction variable. We look
       // through the phi to the initial value of the phi upon entering the loop.
-      if (lower_inst->opcode() == SpvOpPhi) {
+      if (lower_inst->opcode() == spv::Op::OpPhi) {
         lower_inst = GetOperandDefinition(lower_inst, 0);
         // We don't handle looking through multiple phis.
-        if (lower_inst->opcode() == SpvOpPhi) {
+        if (lower_inst->opcode() == spv::Op::OpPhi) {
           return nullptr;
         }
       }
@@ -86,8 +86,8 @@
   }
   Instruction* upper_inst = GetOperandDefinition(cond_inst, 1);
   switch (cond_inst->opcode()) {
-    case SpvOpULessThan:
-    case SpvOpSLessThan: {
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan: {
       // When we have a < condition we must subtract 1 from the analyzed upper
       // instruction.
       SENode* upper_bound = scalar_evolution_.SimplifyExpression(
@@ -96,8 +96,8 @@
               scalar_evolution_.CreateConstant(1)));
       return upper_bound;
     }
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan: {
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan: {
       // When we have a > condition we must add 1 to the analyzed upper
       // instruction.
       SENode* upper_bound =
@@ -106,10 +106,10 @@
               scalar_evolution_.CreateConstant(1)));
       return upper_bound;
     }
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual: {
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual: {
       // We don't need to modify the results of analyzing when we have <= or >=.
       SENode* upper_bound = scalar_evolution_.SimplifyExpression(
           scalar_evolution_.AnalyzeInstruction(upper_inst));
diff --git a/third_party/SPIRV-Tools/source/opt/loop_descriptor.cpp b/third_party/SPIRV-Tools/source/opt/loop_descriptor.cpp
index 13982d1..172b978 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_descriptor.cpp
+++ b/third_party/SPIRV-Tools/source/opt/loop_descriptor.cpp
@@ -39,7 +39,7 @@
 Instruction* Loop::GetInductionStepOperation(
     const Instruction* induction) const {
   // Induction must be a phi instruction.
-  assert(induction->opcode() == SpvOpPhi);
+  assert(induction->opcode() == spv::Op::OpPhi);
 
   Instruction* step = nullptr;
 
@@ -75,8 +75,8 @@
     return nullptr;
   }
 
-  if (def_use_manager->GetDef(lhs)->opcode() != SpvOp::SpvOpConstant &&
-      def_use_manager->GetDef(rhs)->opcode() != SpvOp::SpvOpConstant) {
+  if (def_use_manager->GetDef(lhs)->opcode() != spv::Op::OpConstant &&
+      def_use_manager->GetDef(rhs)->opcode() != spv::Op::OpConstant) {
     return nullptr;
   }
 
@@ -85,31 +85,31 @@
 
 // Returns true if the |step| operation is an induction variable step operation
 // which is currently handled.
-bool Loop::IsSupportedStepOp(SpvOp step) const {
+bool Loop::IsSupportedStepOp(spv::Op step) const {
   switch (step) {
-    case SpvOp::SpvOpISub:
-    case SpvOp::SpvOpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIAdd:
       return true;
     default:
       return false;
   }
 }
 
-bool Loop::IsSupportedCondition(SpvOp condition) const {
+bool Loop::IsSupportedCondition(spv::Op condition) const {
   switch (condition) {
     // <
-    case SpvOp::SpvOpULessThan:
-    case SpvOp::SpvOpSLessThan:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
     // >
-    case SpvOp::SpvOpUGreaterThan:
-    case SpvOp::SpvOpSGreaterThan:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
 
     // >=
-    case SpvOp::SpvOpSGreaterThanEqual:
-    case SpvOp::SpvOpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
     // <=
-    case SpvOp::SpvOpSLessThanEqual:
-    case SpvOp::SpvOpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpULessThanEqual:
 
       return true;
     default:
@@ -117,7 +117,8 @@
   }
 }
 
-int64_t Loop::GetResidualConditionValue(SpvOp condition, int64_t initial_value,
+int64_t Loop::GetResidualConditionValue(spv::Op condition,
+                                        int64_t initial_value,
                                         int64_t step_value,
                                         size_t number_of_iterations,
                                         size_t factor) {
@@ -128,13 +129,13 @@
   // loop where just less than or greater than. Adding or subtracting one should
   // give a functionally equivalent value.
   switch (condition) {
-    case SpvOp::SpvOpSGreaterThanEqual:
-    case SpvOp::SpvOpUGreaterThanEqual: {
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual: {
       remainder -= 1;
       break;
     }
-    case SpvOp::SpvOpSLessThanEqual:
-    case SpvOp::SpvOpULessThanEqual: {
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpULessThanEqual: {
       remainder += 1;
       break;
     }
@@ -152,7 +153,7 @@
   }
   Instruction* branch_conditional = &*condition_block->tail();
   if (!branch_conditional ||
-      branch_conditional->opcode() != SpvOpBranchConditional) {
+      branch_conditional->opcode() != spv::Op::OpBranchConditional) {
     return nullptr;
   }
   Instruction* condition_inst = context_->get_def_use_mgr()->GetDef(
@@ -318,7 +319,7 @@
 void Loop::SetPreHeaderBlock(BasicBlock* preheader) {
   if (preheader) {
     assert(!IsInsideLoop(preheader) && "The preheader block is in the loop");
-    assert(preheader->tail()->opcode() == SpvOpBranch &&
+    assert(preheader->tail()->opcode() == spv::Op::OpBranch &&
            "The preheader block does not unconditionally branch to the header "
            "block");
     assert(preheader->tail()->GetSingleWordOperand(0) ==
@@ -387,7 +388,7 @@
 
 namespace {
 
-static inline bool IsBasicBlockSafeToClone(IRContext* context, BasicBlock* bb) {
+inline bool IsBasicBlockSafeToClone(IRContext* context, BasicBlock* bb) {
   for (Instruction& inst : *bb) {
     if (!inst.IsBranch() && !context->IsCombinatorInstruction(&inst))
       return false;
@@ -443,7 +444,7 @@
                 BasicBlock* parent = ir_context->get_instr_block(use);
                 assert(parent && "Invalid analysis");
                 if (IsInsideLoop(parent)) return true;
-                if (use->opcode() != SpvOpPhi) return false;
+                if (use->opcode() != spv::Op::OpPhi) return false;
                 return exit_blocks.count(parent->id());
               }))
         return false;
@@ -486,7 +487,7 @@
     ordered_loop_blocks->push_back(loop_preheader_);
 
   bool is_shader =
-      context_->get_feature_mgr()->HasCapability(SpvCapabilityShader);
+      context_->get_feature_mgr()->HasCapability(spv::Capability::Shader);
   if (!is_shader) {
     cfg.ForEachBlockInReversePostOrder(
         loop_header_, [ordered_loop_blocks, this](BasicBlock* bb) {
@@ -647,7 +648,7 @@
   const Instruction& branch = *bb->ctail();
 
   // Make sure the branch is a conditional branch.
-  if (branch.opcode() != SpvOpBranchConditional) return nullptr;
+  if (branch.opcode() != spv::Op::OpBranchConditional) return nullptr;
 
   // Make sure one of the two possible branches is to the merge block.
   if (branch.GetSingleWordInOperand(1) == loop_merge_->id() ||
@@ -716,7 +717,7 @@
   }
 
   // If this is a subtraction step we should negate the step value.
-  if (step_inst->opcode() == SpvOp::SpvOpISub) {
+  if (step_inst->opcode() == spv::Op::OpISub) {
     step_value = -step_value;
   }
 
@@ -753,7 +754,7 @@
 // |step_value| where diff is calculated differently according to the
 // |condition| and uses the |condition_value| and |init_value|. If diff /
 // |step_value| is NOT cleanly divisible then we add one to the sum.
-int64_t Loop::GetIterations(SpvOp condition, int64_t condition_value,
+int64_t Loop::GetIterations(spv::Op condition, int64_t condition_value,
                             int64_t init_value, int64_t step_value) const {
   if (step_value == 0) {
     return 0;
@@ -762,8 +763,8 @@
   int64_t diff = 0;
 
   switch (condition) {
-    case SpvOp::SpvOpSLessThan:
-    case SpvOp::SpvOpULessThan: {
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThan: {
       // If the condition is not met to begin with the loop will never iterate.
       if (!(init_value < condition_value)) return 0;
 
@@ -778,8 +779,8 @@
 
       break;
     }
-    case SpvOp::SpvOpSGreaterThan:
-    case SpvOp::SpvOpUGreaterThan: {
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThan: {
       // If the condition is not met to begin with the loop will never iterate.
       if (!(init_value > condition_value)) return 0;
 
@@ -795,12 +796,12 @@
       break;
     }
 
-    case SpvOp::SpvOpSGreaterThanEqual:
-    case SpvOp::SpvOpUGreaterThanEqual: {
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual: {
       // If the condition is not met to begin with the loop will never iterate.
       if (!(init_value >= condition_value)) return 0;
 
-      // We subtract one to make it the same as SpvOpGreaterThan as it is
+      // We subtract one to make it the same as spv::Op::OpGreaterThan as it is
       // functionally equivalent.
       diff = init_value - (condition_value - 1);
 
@@ -814,13 +815,13 @@
       break;
     }
 
-    case SpvOp::SpvOpSLessThanEqual:
-    case SpvOp::SpvOpULessThanEqual: {
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpULessThanEqual: {
       // If the condition is not met to begin with the loop will never iterate.
       if (!(init_value <= condition_value)) return 0;
 
-      // We add one to make it the same as SpvOpLessThan as it is functionally
-      // equivalent.
+      // We add one to make it the same as spv::Op::OpLessThan as it is
+      // functionally equivalent.
       diff = (condition_value + 1) - init_value;
 
       // If the operation is a less than operation then the diff and step must
@@ -854,7 +855,7 @@
 void Loop::GetInductionVariables(
     std::vector<Instruction*>& induction_variables) const {
   for (Instruction& inst : *loop_header_) {
-    if (inst.opcode() == SpvOp::SpvOpPhi) {
+    if (inst.opcode() == spv::Op::OpPhi) {
       induction_variables.push_back(&inst);
     }
   }
@@ -867,7 +868,7 @@
 
   Instruction* induction = nullptr;
   // Verify that the branch instruction is a conditional branch.
-  if (branch_inst.opcode() == SpvOp::SpvOpBranchConditional) {
+  if (branch_inst.opcode() == spv::Op::OpBranchConditional) {
     // From the branch instruction find the branch condition.
     analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr();
 
@@ -883,7 +884,8 @@
           def_use_manager->GetDef(condition->GetSingleWordOperand(2));
 
       // Make sure the variable instruction used is a phi.
-      if (!variable_inst || variable_inst->opcode() != SpvOpPhi) return nullptr;
+      if (!variable_inst || variable_inst->opcode() != spv::Op::OpPhi)
+        return nullptr;
 
       // Make sure the phi instruction only has two incoming blocks. Each
       // incoming block will be represented by two in operands in the phi
diff --git a/third_party/SPIRV-Tools/source/opt/loop_descriptor.h b/third_party/SPIRV-Tools/source/opt/loop_descriptor.h
index df01227..35256bc 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_descriptor.h
+++ b/third_party/SPIRV-Tools/source/opt/loop_descriptor.h
@@ -316,12 +316,12 @@
   // Returns true if we can deduce the number of loop iterations in the step
   // operation |step|. IsSupportedCondition must also be true for the condition
   // instruction.
-  bool IsSupportedStepOp(SpvOp step) const;
+  bool IsSupportedStepOp(spv::Op step) const;
 
   // Returns true if we can deduce the number of loop iterations in the
   // condition operation |condition|. IsSupportedStepOp must also be true for
   // the step instruction.
-  bool IsSupportedCondition(SpvOp condition) const;
+  bool IsSupportedCondition(spv::Op condition) const;
 
   // Creates the list of the loop's basic block in structured order and store
   // the result in |ordered_loop_blocks|. If |include_pre_header| is true, the
@@ -335,7 +335,7 @@
   // Given the loop |condition|, |initial_value|, |step_value|, the trip count
   // |number_of_iterations|, and the |unroll_factor| requested, get the new
   // condition value for the residual loop.
-  static int64_t GetResidualConditionValue(SpvOp condition,
+  static int64_t GetResidualConditionValue(spv::Op condition,
                                            int64_t initial_value,
                                            int64_t step_value,
                                            size_t number_of_iterations,
@@ -400,7 +400,7 @@
   // the induction variable. This method will return the number of iterations in
   // a loop with those values for a given |condition|.  Returns 0 if the number
   // of iterations could not be computed.
-  int64_t GetIterations(SpvOp condition, int64_t condition_value,
+  int64_t GetIterations(spv::Op condition, int64_t condition_value,
                         int64_t init_value, int64_t step_value) const;
 
   // This is to allow for loops to be removed mid iteration without invalidating
diff --git a/third_party/SPIRV-Tools/source/opt/loop_fission.cpp b/third_party/SPIRV-Tools/source/opt/loop_fission.cpp
index b4df8c6..2ae05c3 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_fission.cpp
+++ b/third_party/SPIRV-Tools/source/opt/loop_fission.cpp
@@ -110,10 +110,10 @@
 };
 
 bool LoopFissionImpl::MovableInstruction(const Instruction& inst) const {
-  return inst.opcode() == SpvOp::SpvOpLoad ||
-         inst.opcode() == SpvOp::SpvOpStore ||
-         inst.opcode() == SpvOp::SpvOpSelectionMerge ||
-         inst.opcode() == SpvOp::SpvOpPhi || inst.IsOpcodeCodeMotionSafe();
+  return inst.opcode() == spv::Op::OpLoad ||
+         inst.opcode() == spv::Op::OpStore ||
+         inst.opcode() == spv::Op::OpSelectionMerge ||
+         inst.opcode() == spv::Op::OpPhi || inst.IsOpcodeCodeMotionSafe();
 }
 
 void LoopFissionImpl::TraverseUseDef(Instruction* inst,
@@ -143,14 +143,14 @@
     // same labels (i.e phis). We already preempt the inclusion of
     // OpSelectionMerge by adding related instructions to the seen_instructions_
     // set.
-    if (user->opcode() == SpvOp::SpvOpLoopMerge ||
-        user->opcode() == SpvOp::SpvOpLabel)
+    if (user->opcode() == spv::Op::OpLoopMerge ||
+        user->opcode() == spv::Op::OpLabel)
       return;
 
     // If the |report_loads| flag is set, set the class field
     // load_used_in_condition_ to false. This is used to check that none of the
     // condition checks in the loop rely on loads.
-    if (user->opcode() == SpvOp::SpvOpLoad && report_loads) {
+    if (user->opcode() == spv::Op::OpLoad && report_loads) {
       load_used_in_condition_ = true;
     }
 
@@ -167,7 +167,7 @@
     user->ForEachInOperand(traverse_operand);
 
     // For the first traversal we want to ignore the users of the phi.
-    if (ignore_phi_users && user->opcode() == SpvOp::SpvOpPhi) return;
+    if (ignore_phi_users && user->opcode() == spv::Op::OpPhi) return;
 
     // Traverse each user with this lambda.
     def_use->ForEachUser(user, traverser_functor);
@@ -214,7 +214,7 @@
 
     for (Instruction& inst : block) {
       // Ignore all instructions related to control flow.
-      if (inst.opcode() == SpvOp::SpvOpSelectionMerge || inst.IsBranch()) {
+      if (inst.opcode() == spv::Op::OpSelectionMerge || inst.IsBranch()) {
         TraverseUseDef(&inst, &instructions_to_ignore, true, true);
       }
     }
@@ -229,8 +229,8 @@
 
     for (Instruction& inst : block) {
       // Record the order that each load/store is seen.
-      if (inst.opcode() == SpvOp::SpvOpLoad ||
-          inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpLoad ||
+          inst.opcode() == spv::Op::OpStore) {
         instruction_order_[&inst] = instruction_order_.size();
       }
 
@@ -292,9 +292,9 @@
 
   // Populate the above lists.
   for (Instruction* inst : cloned_loop_instructions_) {
-    if (inst->opcode() == SpvOp::SpvOpStore) {
+    if (inst->opcode() == spv::Op::OpStore) {
       set_one_stores.push_back(inst);
-    } else if (inst->opcode() == SpvOp::SpvOpLoad) {
+    } else if (inst->opcode() == spv::Op::OpLoad) {
       set_one_loads.push_back(inst);
     }
 
@@ -316,7 +316,7 @@
 
     // Look at the dependency between the loads in the original and stores in
     // the cloned loops.
-    if (inst->opcode() == SpvOp::SpvOpLoad) {
+    if (inst->opcode() == spv::Op::OpLoad) {
       for (Instruction* store : set_one_stores) {
         DistanceVector vec{loop_depth};
 
@@ -334,7 +334,7 @@
           }
         }
       }
-    } else if (inst->opcode() == SpvOp::SpvOpStore) {
+    } else if (inst->opcode() == spv::Op::OpStore) {
       for (Instruction* load : set_one_loads) {
         DistanceVector vec{loop_depth};
 
@@ -387,7 +387,7 @@
       if (cloned_loop_instructions_.count(&inst) == 1 &&
           original_loop_instructions_.count(&inst) == 0) {
         instructions_to_kill.push_back(&inst);
-        if (inst.opcode() == SpvOp::SpvOpPhi) {
+        if (inst.opcode() == spv::Op::OpPhi) {
           context_->ReplaceAllUsesWith(
               inst.result_id(), clone_results.value_map_[inst.result_id()]);
         }
diff --git a/third_party/SPIRV-Tools/source/opt/loop_fusion.cpp b/third_party/SPIRV-Tools/source/opt/loop_fusion.cpp
index f3aab28..dc63553 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_fusion.cpp
+++ b/third_party/SPIRV-Tools/source/opt/loop_fusion.cpp
@@ -23,7 +23,6 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
 
 // Append all the loops nested in |loop| to |loops|.
@@ -193,14 +192,15 @@
   // in LCSSA form.
   for (auto block : block_to_check) {
     for (auto& inst : *block) {
-      if (inst.opcode() == SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         // Get the definition of the target to check it's function scope so
         // there are no observable side effects.
         auto variable =
             context_->get_def_use_mgr()->GetDef(inst.GetSingleWordInOperand(0));
 
-        if (variable->opcode() != SpvOpVariable ||
-            variable->GetSingleWordInOperand(0) != SpvStorageClassFunction) {
+        if (variable->opcode() != spv::Op::OpVariable ||
+            spv::StorageClass(variable->GetSingleWordInOperand(0)) !=
+                spv::StorageClass::Function) {
           return false;
         }
 
@@ -209,7 +209,7 @@
         context_->get_def_use_mgr()->ForEachUse(
             inst.GetSingleWordInOperand(0),
             [&is_used](Instruction* use_inst, uint32_t) {
-              if (use_inst->opcode() == SpvOpLoad) {
+              if (use_inst->opcode() == spv::Op::OpLoad) {
                 is_used = true;
               }
             });
@@ -217,11 +217,11 @@
         if (is_used) {
           return false;
         }
-      } else if (inst.opcode() == SpvOpPhi) {
+      } else if (inst.opcode() == spv::Op::OpPhi) {
         if (inst.NumInOperands() != 2) {
           return false;
         }
-      } else if (inst.opcode() != SpvOpBranch) {
+      } else if (inst.opcode() != spv::Op::OpBranch) {
         return false;
       }
     }
@@ -234,10 +234,12 @@
   for (const auto& block : loop->GetBlocks()) {
     for (const auto& inst : *containing_function_->FindBlock(block)) {
       auto opcode = inst.opcode();
-      if (opcode == SpvOpFunctionCall || opcode == SpvOpControlBarrier ||
-          opcode == SpvOpMemoryBarrier || opcode == SpvOpTypeNamedBarrier ||
-          opcode == SpvOpNamedBarrierInitialize ||
-          opcode == SpvOpMemoryNamedBarrier) {
+      if (opcode == spv::Op::OpFunctionCall ||
+          opcode == spv::Op::OpControlBarrier ||
+          opcode == spv::Op::OpMemoryBarrier ||
+          opcode == spv::Op::OpTypeNamedBarrier ||
+          opcode == spv::Op::OpNamedBarrierInitialize ||
+          opcode == spv::Op::OpMemoryNamedBarrier) {
         return true;
       }
     }
@@ -344,7 +346,7 @@
     auto access_location = context_->get_def_use_mgr()->GetDef(
         instruction->GetSingleWordInOperand(0));
 
-    while (access_location->opcode() == SpvOpAccessChain) {
+    while (access_location->opcode() == spv::Op::OpAccessChain) {
       access_location = context_->get_def_use_mgr()->GetDef(
           access_location->GetSingleWordInOperand(0));
     }
@@ -366,9 +368,9 @@
     }
 
     for (auto& instruction : *containing_function_->FindBlock(block_id)) {
-      if (instruction.opcode() == SpvOpLoad) {
+      if (instruction.opcode() == spv::Op::OpLoad) {
         loads.push_back(&instruction);
-      } else if (instruction.opcode() == SpvOpStore) {
+      } else if (instruction.opcode() == spv::Op::OpStore) {
         stores.push_back(&instruction);
       }
     }
@@ -556,7 +558,7 @@
   // Update merge block id in the header of |loop_0_| to the merge block of
   // |loop_1_|.
   loop_0_->GetHeaderBlock()->ForEachInst([this](Instruction* inst) {
-    if (inst->opcode() == SpvOpLoopMerge) {
+    if (inst->opcode() == spv::Op::OpLoopMerge) {
       inst->SetInOperand(0, {loop_1_->GetMergeBlock()->id()});
     }
   });
@@ -564,7 +566,7 @@
   // Update condition branch target in |loop_0_| to the merge block of
   // |loop_1_|.
   condition_block_of_0->ForEachInst([this](Instruction* inst) {
-    if (inst->opcode() == SpvOpBranchConditional) {
+    if (inst->opcode() == spv::Op::OpBranchConditional) {
       auto loop_0_merge_block_id = loop_0_->GetMergeBlock()->id();
 
       if (inst->GetSingleWordInOperand(1) == loop_0_merge_block_id) {
@@ -579,7 +581,8 @@
   // the header of |loop_1_| to the header of |loop_0_|.
   std::vector<Instruction*> instructions_to_move{};
   for (auto& instruction : *loop_1_->GetHeaderBlock()) {
-    if (instruction.opcode() == SpvOpPhi && &instruction != induction_1_) {
+    if (instruction.opcode() == spv::Op::OpPhi &&
+        &instruction != induction_1_) {
       instructions_to_move.push_back(&instruction);
     }
   }
diff --git a/third_party/SPIRV-Tools/source/opt/loop_peeling.cpp b/third_party/SPIRV-Tools/source/opt/loop_peeling.cpp
index 34f0a8d..d512273 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_peeling.cpp
+++ b/third_party/SPIRV-Tools/source/opt/loop_peeling.cpp
@@ -29,6 +29,21 @@
 
 namespace spvtools {
 namespace opt {
+namespace {
+// Gather the set of blocks for all the path from |entry| to |root|.
+void GetBlocksInPath(uint32_t block, uint32_t entry,
+                     std::unordered_set<uint32_t>* blocks_in_path,
+                     const CFG& cfg) {
+  for (uint32_t pid : cfg.preds(block)) {
+    if (blocks_in_path->insert(pid).second) {
+      if (pid != entry) {
+        GetBlocksInPath(pid, entry, blocks_in_path, cfg);
+      }
+    }
+  }
+}
+}  // namespace
+
 size_t LoopPeelingPass::code_grow_threshold_ = 1000;
 
 void LoopPeeling::DuplicateAndConnectLoop(
@@ -186,7 +201,7 @@
   operations->insert(iterator);
   iterator->ForEachInId([def_use_mgr, loop, operations, this](uint32_t* id) {
     Instruction* insn = def_use_mgr->GetDef(*id);
-    if (insn->opcode() == SpvOpLabel) {
+    if (insn->opcode() == spv::Op::OpLabel) {
       return;
     }
     if (operations->count(insn)) {
@@ -199,19 +214,6 @@
   });
 }
 
-// Gather the set of blocks for all the path from |entry| to |root|.
-static void GetBlocksInPath(uint32_t block, uint32_t entry,
-                            std::unordered_set<uint32_t>* blocks_in_path,
-                            const CFG& cfg) {
-  for (uint32_t pid : cfg.preds(block)) {
-    if (blocks_in_path->insert(pid).second) {
-      if (pid != entry) {
-        GetBlocksInPath(pid, entry, blocks_in_path, cfg);
-      }
-    }
-  }
-}
-
 bool LoopPeeling::IsConditionCheckSideEffectFree() const {
   CFG& cfg = *context_->cfg();
 
@@ -231,9 +233,9 @@
       if (!bb->WhileEachInst([this](Instruction* insn) {
             if (insn->IsBranch()) return true;
             switch (insn->opcode()) {
-              case SpvOpLabel:
-              case SpvOpSelectionMerge:
-              case SpvOpLoopMerge:
+              case spv::Op::OpLabel:
+              case spv::Op::OpSelectionMerge:
+              case spv::Op::OpLoopMerge:
                 return true;
               default:
                 break;
@@ -322,7 +324,7 @@
 
   BasicBlock* condition_block = cfg.block(condition_block_id);
   Instruction* exit_condition = condition_block->terminator();
-  assert(exit_condition->opcode() == SpvOpBranchConditional);
+  assert(exit_condition->opcode() == spv::Op::OpBranchConditional);
   BasicBlock::iterator insert_point = condition_block->tail();
   if (condition_block->GetMergeInst()) {
     --insert_point;
@@ -350,7 +352,7 @@
   // TODO(1841): Handle id overflow.
   std::unique_ptr<BasicBlock> new_bb =
       MakeUnique<BasicBlock>(std::unique_ptr<Instruction>(new Instruction(
-          context_, SpvOpLabel, 0, context_->TakeNextId(), {})));
+          context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})));
   // Update the loop descriptor.
   Loop* in_loop = (*loop_utils_.GetLoopDescriptor())[bb];
   if (in_loop) {
@@ -791,18 +793,18 @@
   return 0;
 }
 
-static bool IsHandledCondition(SpvOp opcode) {
+static bool IsHandledCondition(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
       return true;
     default:
       return false;
@@ -811,7 +813,7 @@
 
 LoopPeelingPass::LoopPeelingInfo::Direction
 LoopPeelingPass::LoopPeelingInfo::GetPeelingInfo(BasicBlock* bb) const {
-  if (bb->terminator()->opcode() != SpvOpBranchConditional) {
+  if (bb->terminator()->opcode() != spv::Op::OpBranchConditional) {
     return GetNoneDirection();
   }
 
@@ -886,27 +888,27 @@
   switch (condition->opcode()) {
     default:
       return GetNoneDirection();
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
       return HandleEquality(lhs, rhs);
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan: {
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan: {
       cmp_operator = CmpOperator::kGT;
       break;
     }
-    case SpvOpULessThan:
-    case SpvOpSLessThan: {
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan: {
       cmp_operator = CmpOperator::kLT;
       break;
     }
     // We add one to transform >= into > and <= into <.
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual: {
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual: {
       cmp_operator = CmpOperator::kGE;
       break;
     }
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual: {
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual: {
       cmp_operator = CmpOperator::kLE;
       break;
     }
diff --git a/third_party/SPIRV-Tools/source/opt/loop_unroller.cpp b/third_party/SPIRV-Tools/source/opt/loop_unroller.cpp
index 6f4e6f4..07b529d 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_unroller.cpp
+++ b/third_party/SPIRV-Tools/source/opt/loop_unroller.cpp
@@ -68,10 +68,10 @@
 namespace {
 
 // Loop control constant value for DontUnroll flag.
-static const uint32_t kLoopControlDontUnrollIndex = 2;
+constexpr uint32_t kLoopControlDontUnrollIndex = 2;
 
 // Operand index of the loop control parameter of the OpLoopMerge.
-static const uint32_t kLoopControlIndex = 2;
+constexpr uint32_t kLoopControlIndex = 2;
 
 // This utility class encapsulates some of the state we need to maintain between
 // loop unrolls. Specifically it maintains key blocks and the induction variable
@@ -336,8 +336,7 @@
 
 // Retrieve the index of the OpPhi instruction |phi| which corresponds to the
 // incoming |block| id.
-static uint32_t GetPhiIndexFromLabel(const BasicBlock* block,
-                                     const Instruction* phi) {
+uint32_t GetPhiIndexFromLabel(const BasicBlock* block, const Instruction* phi) {
   for (uint32_t i = 1; i < phi->NumInOperands(); i += 2) {
     if (block->id() == phi->GetSingleWordInOperand(i)) {
       return i;
@@ -382,7 +381,7 @@
                                                           size_t factor) {
   // TODO(1841): Handle id overflow.
   std::unique_ptr<Instruction> new_label{new Instruction(
-      context_, SpvOp::SpvOpLabel, 0, context_->TakeNextId(), {})};
+      context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})};
   std::unique_ptr<BasicBlock> new_exit_bb{new BasicBlock(std::move(new_label))};
   new_exit_bb->SetParent(&function_);
 
@@ -991,7 +990,7 @@
 
   // Check that we can find and process the induction variable.
   const Instruction* induction = loop_->FindConditionVariable(condition);
-  if (!induction || induction->opcode() != SpvOpPhi) return false;
+  if (!induction || induction->opcode() != spv::Op::OpPhi) return false;
 
   // Check that we can find the number of loop iterations.
   if (!loop_->FindNumberOfIterations(induction, &*condition->ctail(), nullptr))
@@ -1002,7 +1001,7 @@
   // iteration counts. This can cause timeouts and memouts during fuzzing that
   // are not classed as bugs. To avoid this noise, loop unrolling is not applied
   // to loops with large iteration counts when fuzzing.
-  const size_t kFuzzerIterationLimit = 100;
+  constexpr size_t kFuzzerIterationLimit = 100;
   size_t num_iterations;
   loop_->FindNumberOfIterations(induction, &*condition->ctail(),
                                 &num_iterations);
@@ -1015,7 +1014,7 @@
   // block.
   const Instruction& branch = *loop_->GetLatchBlock()->ctail();
   bool branching_assumption =
-      branch.opcode() == SpvOpBranch &&
+      branch.opcode() == spv::Op::OpBranch &&
       branch.GetSingleWordInOperand(0) == loop_->GetHeaderBlock()->id();
   if (!branching_assumption) {
     return false;
@@ -1043,10 +1042,10 @@
   // exit the loop.
   for (uint32_t label_id : loop_->GetBlocks()) {
     const BasicBlock* block = context_->cfg()->block(label_id);
-    if (block->ctail()->opcode() == SpvOp::SpvOpKill ||
-        block->ctail()->opcode() == SpvOp::SpvOpReturn ||
-        block->ctail()->opcode() == SpvOp::SpvOpReturnValue ||
-        block->ctail()->opcode() == SpvOp::SpvOpTerminateInvocation) {
+    if (block->ctail()->opcode() == spv::Op::OpKill ||
+        block->ctail()->opcode() == spv::Op::OpReturn ||
+        block->ctail()->opcode() == spv::Op::OpReturnValue ||
+        block->ctail()->opcode() == spv::Op::OpTerminateInvocation) {
       return false;
     }
   }
diff --git a/third_party/SPIRV-Tools/source/opt/loop_unswitch_pass.cpp b/third_party/SPIRV-Tools/source/opt/loop_unswitch_pass.cpp
index 1ee7e5e..b00d66d 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_unswitch_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/loop_unswitch_pass.cpp
@@ -37,12 +37,7 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-static const uint32_t kTypePointerStorageClassInIdx = 0;
-
-}  // anonymous namespace
-
-namespace {
+constexpr uint32_t kTypePointerStorageClassInIdx = 0;
 
 // This class handle the unswitch procedure for a given loop.
 // The unswitch will not happen if:
@@ -77,7 +72,7 @@
       }
 
       if (bb->terminator()->IsBranch() &&
-          bb->terminator()->opcode() != SpvOpBranch) {
+          bb->terminator()->opcode() != spv::Op::OpBranch) {
         if (IsConditionNonConstantLoopInvariant(bb->terminator())) {
           switch_block_ = bb;
           break;
@@ -104,7 +99,7 @@
     // TODO(1841): Handle id overflow.
     BasicBlock* bb = &*ip.InsertBefore(std::unique_ptr<BasicBlock>(
         new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
-            context_, SpvOpLabel, 0, context_->TakeNextId(), {})))));
+            context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})))));
     bb->SetParent(function_);
     def_use_mgr->AnalyzeInstDef(bb->GetLabelInst());
     context_->set_instr_block(bb->GetLabelInst(), bb);
@@ -113,7 +108,7 @@
   }
 
   Instruction* GetValueForDefaultPathForSwitch(Instruction* switch_inst) {
-    assert(switch_inst->opcode() == SpvOpSwitch &&
+    assert(switch_inst->opcode() == spv::Op::OpSwitch &&
            "The given instructoin must be an OpSwitch.");
 
     // Find a value that can be used to select the default path.
@@ -291,7 +286,7 @@
     /////////////////////////////
 
     Instruction* iv_condition = &*switch_block_->tail();
-    SpvOp iv_opcode = iv_condition->opcode();
+    spv::Op iv_opcode = iv_condition->opcode();
     Instruction* condition =
         def_use_mgr->GetDef(iv_condition->GetOperand(0).words[0]);
 
@@ -304,7 +299,7 @@
     std::vector<std::pair<Instruction*, BasicBlock*>> constant_branch;
     // Special case for the original loop
     Instruction* original_loop_constant_value;
-    if (iv_opcode == SpvOpBranchConditional) {
+    if (iv_opcode == spv::Op::OpBranchConditional) {
       constant_branch.emplace_back(
           cst_mgr->GetDefiningInstruction(cst_mgr->GetConstant(cond_type, {0})),
           nullptr);
@@ -401,7 +396,7 @@
     // Delete the old jump
     context_->KillInst(&*if_block->tail());
     InstructionBuilder builder(context_, if_block);
-    if (iv_opcode == SpvOpBranchConditional) {
+    if (iv_opcode == spv::Op::OpBranchConditional) {
       assert(constant_branch.size() == 1);
       builder.AddConditionalBranch(
           condition->result_id(), original_loop_target->id(),
@@ -509,7 +504,8 @@
     bool& is_uniform = dynamically_uniform_[var->result_id()];
     is_uniform = false;
 
-    dec_mgr->WhileEachDecoration(var->result_id(), SpvDecorationUniform,
+    dec_mgr->WhileEachDecoration(var->result_id(),
+                                 uint32_t(spv::Decoration::Uniform),
                                  [&is_uniform](const Instruction&) {
                                    is_uniform = true;
                                    return false;
@@ -526,14 +522,14 @@
     if (!post_dom_tree.Dominates(parent->id(), entry->id())) {
       return is_uniform = false;
     }
-    if (var->opcode() == SpvOpLoad) {
+    if (var->opcode() == spv::Op::OpLoad) {
       const uint32_t PtrTypeId =
           def_use_mgr->GetDef(var->GetSingleWordInOperand(0))->type_id();
       const Instruction* PtrTypeInst = def_use_mgr->GetDef(PtrTypeId);
-      uint32_t storage_class =
-          PtrTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx);
-      if (storage_class != SpvStorageClassUniform &&
-          storage_class != SpvStorageClassUniformConstant) {
+      auto storage_class = spv::StorageClass(
+          PtrTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx));
+      if (storage_class != spv::StorageClass::Uniform &&
+          storage_class != spv::StorageClass::UniformConstant) {
         return is_uniform = false;
       }
     } else {
@@ -553,7 +549,7 @@
   // dynamically uniform.
   bool IsConditionNonConstantLoopInvariant(Instruction* insn) {
     assert(insn->IsBranch());
-    assert(insn->opcode() != SpvOpBranch);
+    assert(insn->opcode() != spv::Op::OpBranch);
     analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr();
 
     Instruction* condition = def_use_mgr->GetDef(insn->GetOperand(0).words[0]);
diff --git a/third_party/SPIRV-Tools/source/opt/loop_utils.cpp b/third_party/SPIRV-Tools/source/opt/loop_utils.cpp
index 8c6d355..20494e1 100644
--- a/third_party/SPIRV-Tools/source/opt/loop_utils.cpp
+++ b/third_party/SPIRV-Tools/source/opt/loop_utils.cpp
@@ -28,12 +28,11 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
 // Return true if |bb| is dominated by at least one block in |exits|
-static inline bool DominatesAnExit(BasicBlock* bb,
-                                   const std::unordered_set<BasicBlock*>& exits,
-                                   const DominatorTree& dom_tree) {
+inline bool DominatesAnExit(BasicBlock* bb,
+                            const std::unordered_set<BasicBlock*>& exits,
+                            const DominatorTree& dom_tree) {
   for (BasicBlock* e_bb : exits)
     if (dom_tree.Dominates(bb, e_bb)) return true;
   return false;
@@ -71,10 +70,10 @@
     // UpdateManagers.
     void RewriteUse(BasicBlock* bb, Instruction* user, uint32_t operand_index) {
       assert(
-          (user->opcode() != SpvOpPhi || bb != GetParent(user)) &&
+          (user->opcode() != spv::Op::OpPhi || bb != GetParent(user)) &&
           "The root basic block must be the incoming edge if |user| is a phi "
           "instruction");
-      assert((user->opcode() == SpvOpPhi || bb == GetParent(user)) &&
+      assert((user->opcode() == spv::Op::OpPhi || bb == GetParent(user)) &&
              "The root basic block must be the instruction parent if |user| is "
              "not "
              "phi instruction");
@@ -293,7 +292,7 @@
             assert(use_parent);
             if (blocks.count(use_parent->id())) return;
 
-            if (use->opcode() == SpvOpPhi) {
+            if (use->opcode() == spv::Op::OpPhi) {
               // If the use is a Phi instruction and the incoming block is
               // coming from the loop, then that's consistent with LCSSA form.
               if (exit_bb.count(use_parent)) {
@@ -355,7 +354,7 @@
     // TODO(1841): Handle id overflow.
     BasicBlock& exit = *insert_pt.InsertBefore(std::unique_ptr<BasicBlock>(
         new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
-            context_, SpvOpLabel, 0, context_->TakeNextId(), {})))));
+            context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})))));
     exit.SetParent(function);
 
     // Redirect in loop predecessors to |exit| block.
@@ -494,7 +493,7 @@
   // Create a new exit block/label for the new loop.
   // TODO(1841): Handle id overflow.
   std::unique_ptr<Instruction> new_label{new Instruction(
-      context_, SpvOp::SpvOpLabel, 0, context_->TakeNextId(), {})};
+      context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})};
   std::unique_ptr<BasicBlock> new_exit_bb{new BasicBlock(std::move(new_label))};
   new_exit_bb->SetParent(loop_->GetMergeBlock()->GetParent());
 
@@ -680,9 +679,9 @@
     const BasicBlock* bb = cfg.block(id);
     size_t bb_size = 0;
     bb->ForEachInst([&bb_size](const Instruction* insn) {
-      if (insn->opcode() == SpvOpLabel) return;
+      if (insn->opcode() == spv::Op::OpLabel) return;
       if (insn->IsNop()) return;
-      if (insn->opcode() == SpvOpPhi) return;
+      if (insn->opcode() == spv::Op::OpPhi) return;
       bb_size++;
     });
     block_sizes_[bb->id()] = bb_size;
diff --git a/third_party/SPIRV-Tools/source/opt/mem_pass.cpp b/third_party/SPIRV-Tools/source/opt/mem_pass.cpp
index ca4889b..5f59291 100644
--- a/third_party/SPIRV-Tools/source/opt/mem_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/mem_pass.cpp
@@ -28,26 +28,23 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
-
-const uint32_t kCopyObjectOperandInIdx = 0;
-const uint32_t kTypePointerStorageClassInIdx = 0;
-const uint32_t kTypePointerTypeIdInIdx = 1;
-
+constexpr uint32_t kCopyObjectOperandInIdx = 0;
+constexpr uint32_t kTypePointerStorageClassInIdx = 0;
+constexpr uint32_t kTypePointerTypeIdInIdx = 1;
 }  // namespace
 
 bool MemPass::IsBaseTargetType(const Instruction* typeInst) const {
   switch (typeInst->opcode()) {
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeBool:
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypePointer:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypePointer:
       return true;
     default:
       break;
@@ -57,14 +54,14 @@
 
 bool MemPass::IsTargetType(const Instruction* typeInst) const {
   if (IsBaseTargetType(typeInst)) return true;
-  if (typeInst->opcode() == SpvOpTypeArray) {
+  if (typeInst->opcode() == spv::Op::OpTypeArray) {
     if (!IsTargetType(
             get_def_use_mgr()->GetDef(typeInst->GetSingleWordOperand(1)))) {
       return false;
     }
     return true;
   }
-  if (typeInst->opcode() != SpvOpTypeStruct) return false;
+  if (typeInst->opcode() != spv::Op::OpTypeStruct) return false;
   // All struct members must be math type
   return typeInst->WhileEachInId([this](const uint32_t* tid) {
     Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid);
@@ -73,23 +70,24 @@
   });
 }
 
-bool MemPass::IsNonPtrAccessChain(const SpvOp opcode) const {
-  return opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain;
+bool MemPass::IsNonPtrAccessChain(const spv::Op opcode) const {
+  return opcode == spv::Op::OpAccessChain ||
+         opcode == spv::Op::OpInBoundsAccessChain;
 }
 
 bool MemPass::IsPtr(uint32_t ptrId) {
   uint32_t varId = ptrId;
   Instruction* ptrInst = get_def_use_mgr()->GetDef(varId);
-  while (ptrInst->opcode() == SpvOpCopyObject) {
+  while (ptrInst->opcode() == spv::Op::OpCopyObject) {
     varId = ptrInst->GetSingleWordInOperand(kCopyObjectOperandInIdx);
     ptrInst = get_def_use_mgr()->GetDef(varId);
   }
-  const SpvOp op = ptrInst->opcode();
-  if (op == SpvOpVariable || IsNonPtrAccessChain(op)) return true;
+  const spv::Op op = ptrInst->opcode();
+  if (op == spv::Op::OpVariable || IsNonPtrAccessChain(op)) return true;
   const uint32_t varTypeId = ptrInst->type_id();
   if (varTypeId == 0) return false;
   const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
-  return varTypeInst->opcode() == SpvOpTypePointer;
+  return varTypeInst->opcode() == spv::Op::OpTypePointer;
 }
 
 Instruction* MemPass::GetPtr(uint32_t ptrId, uint32_t* varId) {
@@ -97,24 +95,24 @@
   Instruction* ptrInst = get_def_use_mgr()->GetDef(*varId);
   Instruction* varInst;
 
-  if (ptrInst->opcode() == SpvOpConstantNull) {
+  if (ptrInst->opcode() == spv::Op::OpConstantNull) {
     *varId = 0;
     return ptrInst;
   }
 
-  if (ptrInst->opcode() != SpvOpVariable &&
-      ptrInst->opcode() != SpvOpFunctionParameter) {
+  if (ptrInst->opcode() != spv::Op::OpVariable &&
+      ptrInst->opcode() != spv::Op::OpFunctionParameter) {
     varInst = ptrInst->GetBaseAddress();
   } else {
     varInst = ptrInst;
   }
-  if (varInst->opcode() == SpvOpVariable) {
+  if (varInst->opcode() == spv::Op::OpVariable) {
     *varId = varInst->result_id();
   } else {
     *varId = 0;
   }
 
-  while (ptrInst->opcode() == SpvOpCopyObject) {
+  while (ptrInst->opcode() == spv::Op::OpCopyObject) {
     uint32_t temp = ptrInst->GetSingleWordInOperand(0);
     ptrInst = get_def_use_mgr()->GetDef(temp);
   }
@@ -123,8 +121,9 @@
 }
 
 Instruction* MemPass::GetPtr(Instruction* ip, uint32_t* varId) {
-  assert(ip->opcode() == SpvOpStore || ip->opcode() == SpvOpLoad ||
-         ip->opcode() == SpvOpImageTexelPointer || ip->IsAtomicWithLoad());
+  assert(ip->opcode() == spv::Op::OpStore || ip->opcode() == spv::Op::OpLoad ||
+         ip->opcode() == spv::Op::OpImageTexelPointer ||
+         ip->IsAtomicWithLoad());
 
   // All of these opcode place the pointer in position 0.
   const uint32_t ptrId = ip->GetSingleWordInOperand(0);
@@ -133,8 +132,8 @@
 
 bool MemPass::HasOnlyNamesAndDecorates(uint32_t id) const {
   return get_def_use_mgr()->WhileEachUser(id, [this](Instruction* user) {
-    SpvOp op = user->opcode();
-    if (op != SpvOpName && !IsNonTypeDecorate(op)) {
+    spv::Op op = user->opcode();
+    if (op != spv::Op::OpName && !IsNonTypeDecorate(op)) {
       return false;
     }
     return true;
@@ -147,14 +146,15 @@
 
 bool MemPass::HasLoads(uint32_t varId) const {
   return !get_def_use_mgr()->WhileEachUser(varId, [this](Instruction* user) {
-    SpvOp op = user->opcode();
+    spv::Op op = user->opcode();
     // TODO(): The following is slightly conservative. Could be
     // better handling of non-store/name.
-    if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
+    if (IsNonPtrAccessChain(op) || op == spv::Op::OpCopyObject) {
       if (HasLoads(user->result_id())) {
         return false;
       }
-    } else if (op != SpvOpStore && op != SpvOpName && !IsNonTypeDecorate(op)) {
+    } else if (op != spv::Op::OpStore && op != spv::Op::OpName &&
+               !IsNonTypeDecorate(op)) {
       return false;
     }
     return true;
@@ -164,12 +164,12 @@
 bool MemPass::IsLiveVar(uint32_t varId) const {
   const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
   // assume live if not a variable eg. function parameter
-  if (varInst->opcode() != SpvOpVariable) return true;
+  if (varInst->opcode() != spv::Op::OpVariable) return true;
   // non-function scope vars are live
   const uint32_t varTypeId = varInst->type_id();
   const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
-  if (varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) !=
-      SpvStorageClassFunction)
+  if (spv::StorageClass(varTypeInst->GetSingleWordInOperand(
+          kTypePointerStorageClassInIdx)) != spv::StorageClass::Function)
     return true;
   // test if variable is loaded from
   return HasLoads(varId);
@@ -177,10 +177,10 @@
 
 void MemPass::AddStores(uint32_t ptr_id, std::queue<Instruction*>* insts) {
   get_def_use_mgr()->ForEachUser(ptr_id, [this, insts](Instruction* user) {
-    SpvOp op = user->opcode();
+    spv::Op op = user->opcode();
     if (IsNonPtrAccessChain(op)) {
       AddStores(user->result_id(), insts);
-    } else if (op == SpvOpStore) {
+    } else if (op == spv::Op::OpStore) {
       insts->push(user);
     }
   });
@@ -193,7 +193,7 @@
   while (!deadInsts.empty()) {
     Instruction* di = deadInsts.front();
     // Don't delete labels
-    if (di->opcode() == SpvOpLabel) {
+    if (di->opcode() == spv::Op::OpLabel) {
       deadInsts.pop();
       continue;
     }
@@ -202,7 +202,7 @@
     di->ForEachInId([&ids](uint32_t* iid) { ids.insert(*iid); });
     uint32_t varId = 0;
     // Remember variable if dead load
-    if (di->opcode() == SpvOpLoad) (void)GetPtr(di, &varId);
+    if (di->opcode() == spv::Op::OpLoad) (void)GetPtr(di, &varId);
     if (call_back) {
       call_back(di);
     }
@@ -230,9 +230,9 @@
         dbg_op == CommonDebugInfoDebugValue) {
       return true;
     }
-    SpvOp op = user->opcode();
-    if (op != SpvOpStore && op != SpvOpLoad && op != SpvOpName &&
-        !IsNonTypeDecorate(op)) {
+    spv::Op op = user->opcode();
+    if (op != spv::Op::OpStore && op != spv::Op::OpLoad &&
+        op != spv::Op::OpName && !IsNonTypeDecorate(op)) {
       return false;
     }
     return true;
@@ -248,7 +248,7 @@
   }
 
   std::unique_ptr<Instruction> undef_inst(
-      new Instruction(context(), SpvOpUndef, type_id, undefId, {}));
+      new Instruction(context(), spv::Op::OpUndef, type_id, undefId, {}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*undef_inst);
   get_module()->AddGlobalValue(std::move(undef_inst));
   type2undefs_[type_id] = undefId;
@@ -264,11 +264,11 @@
     return false;
   if (seen_target_vars_.find(varId) != seen_target_vars_.end()) return true;
   const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
-  if (varInst->opcode() != SpvOpVariable) return false;
+  if (varInst->opcode() != spv::Op::OpVariable) return false;
   const uint32_t varTypeId = varInst->type_id();
   const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
-  if (varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) !=
-      SpvStorageClassFunction) {
+  if (spv::StorageClass(varTypeInst->GetSingleWordInOperand(
+          kTypePointerStorageClassInIdx)) != spv::StorageClass::Function) {
     seen_non_target_vars_.insert(varId);
     return false;
   }
@@ -489,8 +489,8 @@
   for (auto& blk : *func) {
     for (auto& inst : blk) {
       switch (inst.opcode()) {
-        case SpvOpStore:
-        case SpvOpLoad: {
+        case spv::Op::OpStore:
+        case spv::Op::OpLoad: {
           uint32_t varId;
           (void)GetPtr(&inst, &varId);
           if (!IsTargetVar(varId)) break;
diff --git a/third_party/SPIRV-Tools/source/opt/mem_pass.h b/third_party/SPIRV-Tools/source/opt/mem_pass.h
index 5a77670..aef9e5f 100644
--- a/third_party/SPIRV-Tools/source/opt/mem_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/mem_pass.h
@@ -80,7 +80,7 @@
   bool IsTargetType(const Instruction* typeInst) const;
 
   // Returns true if |opcode| is a non-ptr access chain op
-  bool IsNonPtrAccessChain(const SpvOp opcode) const;
+  bool IsNonPtrAccessChain(const spv::Op opcode) const;
 
   // Given the id |ptrId|, return true if the top-most non-CopyObj is
   // a variable, a non-ptr access chain or a parameter of pointer type.
@@ -117,8 +117,8 @@
   bool CFGCleanup(Function* func);
 
   // Return true if |op| is supported decorate.
-  inline bool IsNonTypeDecorate(uint32_t op) const {
-    return (op == SpvOpDecorate || op == SpvOpDecorateId);
+  inline bool IsNonTypeDecorate(spv::Op op) const {
+    return (op == spv::Op::OpDecorate || op == spv::Op::OpDecorateId);
   }
 
   // Return the id of an undef value with type |type_id|.  Create and insert an
diff --git a/third_party/SPIRV-Tools/source/opt/merge_return_pass.cpp b/third_party/SPIRV-Tools/source/opt/merge_return_pass.cpp
index 7710dea..c262ea0 100644
--- a/third_party/SPIRV-Tools/source/opt/merge_return_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/merge_return_pass.cpp
@@ -30,7 +30,7 @@
 
 Pass::Status MergeReturnPass::Process() {
   bool is_shader =
-      context()->get_feature_mgr()->HasCapability(SpvCapabilityShader);
+      context()->get_feature_mgr()->HasCapability(spv::Capability::Shader);
 
   bool failed = false;
   ProcessFunction pfn = [&failed, is_shader, this](Function* function) {
@@ -74,16 +74,16 @@
 
 void MergeReturnPass::GenerateState(BasicBlock* block) {
   if (Instruction* mergeInst = block->GetMergeInst()) {
-    if (mergeInst->opcode() == SpvOpLoopMerge) {
+    if (mergeInst->opcode() == spv::Op::OpLoopMerge) {
       // If new loop, break to this loop merge block
       state_.emplace_back(mergeInst, mergeInst);
     } else {
       auto branchInst = mergeInst->NextNode();
-      if (branchInst->opcode() == SpvOpSwitch) {
+      if (branchInst->opcode() == spv::Op::OpSwitch) {
         // If switch inside of loop, break to innermost loop merge block.
         // Otherwise need to break to this switch merge block.
         auto lastMergeInst = state_.back().BreakMergeInst();
-        if (lastMergeInst && lastMergeInst->opcode() == SpvOpLoopMerge)
+        if (lastMergeInst && lastMergeInst->opcode() == spv::Op::OpLoopMerge)
           state_.emplace_back(lastMergeInst, mergeInst);
         else
           state_.emplace_back(mergeInst, mergeInst);
@@ -174,7 +174,7 @@
 void MergeReturnPass::CreateReturnBlock() {
   // Create a label for the new return block
   std::unique_ptr<Instruction> return_label(
-      new Instruction(context(), SpvOpLabel, 0u, TakeNextId(), {}));
+      new Instruction(context(), spv::Op::OpLabel, 0u, TakeNextId(), {}));
 
   // Create the new basic block
   std::unique_ptr<BasicBlock> return_block(
@@ -195,37 +195,41 @@
     // Load and return the final return value
     uint32_t loadId = TakeNextId();
     block->AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpLoad, function_->type_id(), loadId,
+        context(), spv::Op::OpLoad, function_->type_id(), loadId,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {return_value_->result_id()}}}));
     Instruction* var_inst = block->terminator();
     context()->AnalyzeDefUse(var_inst);
     context()->set_instr_block(var_inst, block);
     context()->get_decoration_mgr()->CloneDecorations(
-        return_value_->result_id(), loadId, {SpvDecorationRelaxedPrecision});
+        return_value_->result_id(), loadId,
+        {spv::Decoration::RelaxedPrecision});
 
     block->AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpReturnValue, 0, 0,
+        context(), spv::Op::OpReturnValue, 0, 0,
         std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {loadId}}}));
     context()->AnalyzeDefUse(block->terminator());
     context()->set_instr_block(block->terminator(), block);
   } else {
-    block->AddInstruction(MakeUnique<Instruction>(context(), SpvOpReturn));
+    block->AddInstruction(
+        MakeUnique<Instruction>(context(), spv::Op::OpReturn));
     context()->AnalyzeDefUse(block->terminator());
     context()->set_instr_block(block->terminator(), block);
   }
 }
 
 void MergeReturnPass::ProcessStructuredBlock(BasicBlock* block) {
-  SpvOp tail_opcode = block->tail()->opcode();
-  if (tail_opcode == SpvOpReturn || tail_opcode == SpvOpReturnValue) {
+  spv::Op tail_opcode = block->tail()->opcode();
+  if (tail_opcode == spv::Op::OpReturn ||
+      tail_opcode == spv::Op::OpReturnValue) {
     if (!return_flag_) {
       AddReturnFlag();
     }
   }
 
-  if (tail_opcode == SpvOpReturn || tail_opcode == SpvOpReturnValue ||
-      tail_opcode == SpvOpUnreachable) {
+  if (tail_opcode == spv::Op::OpReturn ||
+      tail_opcode == spv::Op::OpReturnValue ||
+      tail_opcode == spv::Op::OpUnreachable) {
     assert(CurrentState().InBreakable() &&
            "Should be in the placeholder construct.");
     BranchToBlock(block, CurrentState().BreakMergeId());
@@ -234,8 +238,8 @@
 }
 
 void MergeReturnPass::BranchToBlock(BasicBlock* block, uint32_t target) {
-  if (block->tail()->opcode() == SpvOpReturn ||
-      block->tail()->opcode() == SpvOpReturnValue) {
+  if (block->tail()->opcode() == spv::Op::OpReturn ||
+      block->tail()->opcode() == spv::Op::OpReturnValue) {
     RecordReturned(block);
     RecordReturnValue(block);
   }
@@ -247,7 +251,7 @@
   UpdatePhiNodes(block, target_block);
 
   Instruction* return_inst = block->terminator();
-  return_inst->SetOpcode(SpvOpBranch);
+  return_inst->SetOpcode(spv::Op::OpBranch);
   return_inst->ReplaceOperands({{SPV_OPERAND_TYPE_ID, {target}}});
   context()->get_def_use_mgr()->AnalyzeInstDefUse(return_inst);
   new_edges_[target_block].insert(block->id());
@@ -276,7 +280,7 @@
         &inst,
         [&users_to_update, &dom_tree, &inst, inst_bb, this](Instruction* user) {
           BasicBlock* user_bb = nullptr;
-          if (user->opcode() != SpvOpPhi) {
+          if (user->opcode() != spv::Op::OpPhi) {
             user_bb = context()->get_instr_block(user);
           } else {
             // For OpPhi, the use should be considered to be in the predecessor.
@@ -325,15 +329,16 @@
     // instruction.  If not, the Spir-V will be invalid.
     Instruction* inst_type = get_def_use_mgr()->GetDef(inst.type_id());
     bool regenerateInstruction = false;
-    if (inst_type->opcode() == SpvOpTypePointer) {
+    if (inst_type->opcode() == spv::Op::OpTypePointer) {
       if (!context()->get_feature_mgr()->HasCapability(
-              SpvCapabilityVariablePointers)) {
+              spv::Capability::VariablePointers)) {
         regenerateInstruction = true;
       }
 
-      uint32_t storage_class = inst_type->GetSingleWordInOperand(0);
-      if (storage_class != SpvStorageClassWorkgroup &&
-          storage_class != SpvStorageClassStorageBuffer) {
+      auto storage_class =
+          spv::StorageClass(inst_type->GetSingleWordInOperand(0));
+      if (storage_class != spv::StorageClass::Workgroup &&
+          storage_class != spv::StorageClass::StorageBuffer) {
         regenerateInstruction = true;
       }
     }
@@ -343,7 +348,7 @@
       uint32_t new_id = TakeNextId();
       regen_inst->SetResultId(new_id);
       Instruction* insert_pos = &*merge_block->begin();
-      while (insert_pos->opcode() == SpvOpPhi) {
+      while (insert_pos->opcode() == spv::Op::OpPhi) {
         insert_pos = insert_pos->NextNode();
       }
       new_phi = insert_pos->InsertBefore(std::move(regen_inst));
@@ -459,7 +464,7 @@
 
   // Leave the phi instructions behind.
   auto iter = block->begin();
-  while (iter->opcode() == SpvOpPhi) {
+  while (iter->opcode() == spv::Op::OpPhi) {
     ++iter;
   }
 
@@ -478,7 +483,7 @@
 
   // If |block| was a continue target for a loop |old_body| is now the correct
   // continue target.
-  if (break_merge_inst->opcode() == SpvOpLoopMerge &&
+  if (break_merge_inst->opcode() == spv::Op::OpLoopMerge &&
       break_merge_inst->GetSingleWordInOperand(1) == block->id()) {
     break_merge_inst->SetInOperand(1, {old_body->id()});
     context()->UpdateDefUse(break_merge_inst);
@@ -531,8 +536,8 @@
 }
 
 void MergeReturnPass::RecordReturned(BasicBlock* block) {
-  if (block->tail()->opcode() != SpvOpReturn &&
-      block->tail()->opcode() != SpvOpReturnValue)
+  if (block->tail()->opcode() != spv::Op::OpReturn &&
+      block->tail()->opcode() != spv::Op::OpReturnValue)
     return;
 
   assert(return_flag_ && "Did not generate the return flag variable.");
@@ -550,7 +555,7 @@
   }
 
   std::unique_ptr<Instruction> return_store(new Instruction(
-      context(), SpvOpStore, 0, 0,
+      context(), spv::Op::OpStore, 0, 0,
       std::initializer_list<Operand>{
           {SPV_OPERAND_TYPE_ID, {return_flag_->result_id()}},
           {SPV_OPERAND_TYPE_ID, {constant_true_->result_id()}}}));
@@ -563,7 +568,7 @@
 
 void MergeReturnPass::RecordReturnValue(BasicBlock* block) {
   auto terminator = *block->tail();
-  if (terminator.opcode() != SpvOpReturnValue) {
+  if (terminator.opcode() != spv::Op::OpReturnValue) {
     return;
   }
 
@@ -571,7 +576,7 @@
          "Did not generate the variable to hold the return value.");
 
   std::unique_ptr<Instruction> value_store(new Instruction(
-      context(), SpvOpStore, 0, 0,
+      context(), spv::Op::OpStore, 0, 0,
       std::initializer_list<Operand>{
           {SPV_OPERAND_TYPE_ID, {return_value_->result_id()}},
           {SPV_OPERAND_TYPE_ID, {terminator.GetSingleWordInOperand(0u)}}}));
@@ -586,17 +591,19 @@
   if (return_value_) return;
 
   uint32_t return_type_id = function_->type_id();
-  if (get_def_use_mgr()->GetDef(return_type_id)->opcode() == SpvOpTypeVoid)
+  if (get_def_use_mgr()->GetDef(return_type_id)->opcode() ==
+      spv::Op::OpTypeVoid)
     return;
 
   uint32_t return_ptr_type = context()->get_type_mgr()->FindPointerToType(
-      return_type_id, SpvStorageClassFunction);
+      return_type_id, spv::StorageClass::Function);
 
   uint32_t var_id = TakeNextId();
-  std::unique_ptr<Instruction> returnValue(new Instruction(
-      context(), SpvOpVariable, return_ptr_type, var_id,
-      std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
+  std::unique_ptr<Instruction> returnValue(
+      new Instruction(context(), spv::Op::OpVariable, return_ptr_type, var_id,
+                      std::initializer_list<Operand>{
+                          {SPV_OPERAND_TYPE_STORAGE_CLASS,
+                           {uint32_t(spv::StorageClass::Function)}}}));
 
   auto insert_iter = function_->begin()->begin();
   insert_iter.InsertBefore(std::move(returnValue));
@@ -606,7 +613,7 @@
   context()->set_instr_block(return_value_, entry_block);
 
   context()->get_decoration_mgr()->CloneDecorations(
-      function_->result_id(), var_id, {SpvDecorationRelaxedPrecision});
+      function_->result_id(), var_id, {spv::Decoration::RelaxedPrecision});
 }
 
 void MergeReturnPass::AddReturnFlag() {
@@ -625,14 +632,14 @@
       const_mgr->GetDefiningInstruction(false_const)->result_id();
 
   uint32_t bool_ptr_id =
-      type_mgr->FindPointerToType(bool_id, SpvStorageClassFunction);
+      type_mgr->FindPointerToType(bool_id, spv::StorageClass::Function);
 
   uint32_t var_id = TakeNextId();
   std::unique_ptr<Instruction> returnFlag(new Instruction(
-      context(), SpvOpVariable, bool_ptr_id, var_id,
-      std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
-          {SPV_OPERAND_TYPE_ID, {const_false_id}}}));
+      context(), spv::Op::OpVariable, bool_ptr_id, var_id,
+      std::initializer_list<Operand>{{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                      {uint32_t(spv::StorageClass::Function)}},
+                                     {SPV_OPERAND_TYPE_ID, {const_false_id}}}));
 
   auto insert_iter = function_->begin()->begin();
 
@@ -648,8 +655,8 @@
   std::vector<BasicBlock*> return_blocks;
   for (auto& block : *function) {
     Instruction& terminator = *block.tail();
-    if (terminator.opcode() == SpvOpReturn ||
-        terminator.opcode() == SpvOpReturnValue) {
+    if (terminator.opcode() == spv::Op::OpReturn ||
+        terminator.opcode() == spv::Op::OpReturnValue) {
       return_blocks.push_back(&block);
     }
   }
@@ -670,7 +677,7 @@
   // Create new return.
   std::vector<Operand> phi_ops;
   for (auto block : return_blocks) {
-    if (block->tail()->opcode() == SpvOpReturnValue) {
+    if (block->tail()->opcode() == spv::Op::OpReturnValue) {
       phi_ops.push_back(
           {SPV_OPERAND_TYPE_ID, {block->tail()->GetSingleWordInOperand(0u)}});
       phi_ops.push_back({SPV_OPERAND_TYPE_ID, {block->id()}});
@@ -682,12 +689,12 @@
     uint32_t phi_result_id = TakeNextId();
     uint32_t phi_type_id = function->type_id();
     std::unique_ptr<Instruction> phi_inst(new Instruction(
-        context(), SpvOpPhi, phi_type_id, phi_result_id, phi_ops));
+        context(), spv::Op::OpPhi, phi_type_id, phi_result_id, phi_ops));
     ret_block_iter->AddInstruction(std::move(phi_inst));
     BasicBlock::iterator phiIter = ret_block_iter->tail();
 
     std::unique_ptr<Instruction> return_inst(
-        new Instruction(context(), SpvOpReturnValue, 0u, 0u,
+        new Instruction(context(), spv::Op::OpReturnValue, 0u, 0u,
                         {{SPV_OPERAND_TYPE_ID, {phi_result_id}}}));
     ret_block_iter->AddInstruction(std::move(return_inst));
     BasicBlock::iterator ret = ret_block_iter->tail();
@@ -697,14 +704,14 @@
     get_def_use_mgr()->AnalyzeInstDef(&*ret);
   } else {
     std::unique_ptr<Instruction> return_inst(
-        new Instruction(context(), SpvOpReturn));
+        new Instruction(context(), spv::Op::OpReturn));
     ret_block_iter->AddInstruction(std::move(return_inst));
   }
 
   // Replace returns with branches
   for (auto block : return_blocks) {
     context()->ForgetUses(block->terminator());
-    block->tail()->SetOpcode(SpvOpBranch);
+    block->tail()->SetOpcode(spv::Op::OpBranch);
     block->tail()->ReplaceOperands({{SPV_OPERAND_TYPE_ID, {return_id}}});
     get_def_use_mgr()->AnalyzeInstUse(block->terminator());
     get_def_use_mgr()->AnalyzeInstUse(block->GetLabelInst());
@@ -789,7 +796,7 @@
 
 BasicBlock* MergeReturnPass::CreateContinueTarget(uint32_t header_label_id) {
   std::unique_ptr<Instruction> label(
-      new Instruction(context(), SpvOpLabel, 0u, TakeNextId(), {}));
+      new Instruction(context(), spv::Op::OpLabel, 0u, TakeNextId(), {}));
 
   // Create the new basic block
   std::unique_ptr<BasicBlock> block(new BasicBlock(std::move(label)));
@@ -824,7 +831,7 @@
   // block to make sure the OpVariable instructions remain in the entry block.
   BasicBlock* start_block = &*function_->begin();
   auto split_pos = start_block->begin();
-  while (split_pos->opcode() == SpvOpVariable) {
+  while (split_pos->opcode() == spv::Op::OpVariable) {
     ++split_pos;
   }
 
@@ -865,7 +872,7 @@
     if (struct_cfg_analysis->IsContinueBlock(bb.id())) {
       // |bb| must be an empty block ending with a branch to the header.
       Instruction* inst = &*bb.begin();
-      if (inst->opcode() != SpvOpBranch) {
+      if (inst->opcode() != spv::Op::OpBranch) {
         return true;
       }
 
@@ -875,7 +882,7 @@
       }
     } else if (struct_cfg_analysis->IsMergeBlock(bb.id())) {
       // |bb| must be an empty block ending with OpUnreachable.
-      if (bb.begin()->opcode() != SpvOpUnreachable) {
+      if (bb.begin()->opcode() != spv::Op::OpUnreachable) {
         return true;
       }
     } else {
diff --git a/third_party/SPIRV-Tools/source/opt/module.cpp b/third_party/SPIRV-Tools/source/opt/module.cpp
index c98af8f..a9710c6 100644
--- a/third_party/SPIRV-Tools/source/opt/module.cpp
+++ b/third_party/SPIRV-Tools/source/opt/module.cpp
@@ -69,14 +69,14 @@
   return const_insts;
 }
 
-uint32_t Module::GetGlobalValue(SpvOp opcode) const {
+uint32_t Module::GetGlobalValue(spv::Op opcode) const {
   for (auto& inst : types_values_) {
     if (inst.opcode() == opcode) return inst.result_id();
   }
   return 0;
 }
 
-void Module::AddGlobalValue(SpvOp opcode, uint32_t result_id,
+void Module::AddGlobalValue(spv::Op opcode, uint32_t result_id,
                             uint32_t type_id) {
   std::unique_ptr<Instruction> newGlobal(
       new Instruction(context(), opcode, type_id, result_id, {}));
@@ -159,7 +159,6 @@
     if (between_merge_and_branch && i->IsLineInst()) {
       return;
     }
-    between_merge_and_branch = false;
     if (last_line_inst != nullptr) {
       // If the current instruction is OpLine or DebugLine and it is the same
       // as the last line instruction that is still effective (can be applied
@@ -181,28 +180,30 @@
                                      ->get_feature_mgr()
                                      ->GetExtInstImportId_Shader100DebugInfo();
         if (shader_set_id != 0) {
-          binary->push_back((5 << 16) | static_cast<uint16_t>(SpvOpExtInst));
+          binary->push_back((5 << 16) |
+                            static_cast<uint16_t>(spv::Op::OpExtInst));
           binary->push_back(context()->get_type_mgr()->GetVoidTypeId());
           binary->push_back(context()->TakeNextId());
           binary->push_back(shader_set_id);
           binary->push_back(NonSemanticShaderDebugInfo100DebugNoLine);
         } else {
-          binary->push_back((1 << 16) | static_cast<uint16_t>(SpvOpNoLine));
+          binary->push_back((1 << 16) |
+                            static_cast<uint16_t>(spv::Op::OpNoLine));
         }
         last_line_inst = nullptr;
       }
     }
 
-    if (opcode == SpvOpLabel) {
+    if (opcode == spv::Op::OpLabel) {
       between_label_and_phi_var = true;
-    } else if (opcode != SpvOpVariable && opcode != SpvOpPhi &&
+    } else if (opcode != spv::Op::OpVariable && opcode != spv::Op::OpPhi &&
                !spvtools::opt::IsOpLineInst(opcode)) {
       between_label_and_phi_var = false;
     }
 
     if (!(skip_nop && i->IsNop())) {
       const auto& scope = i->GetDebugScope();
-      if (scope != last_scope) {
+      if (scope != last_scope && !between_merge_and_branch) {
         // Can only emit nonsemantic instructions after all phi instructions
         // in a block so don't emit scope instructions before phi instructions
         // for NonSemantic.Shader.DebugInfo.100.
@@ -221,9 +222,11 @@
       i->ToBinaryWithoutAttachedDebugInsts(binary);
     }
     // Update the last line instruction.
+    between_merge_and_branch = false;
     if (spvOpcodeIsBlockTerminator(opcode) || i->IsNoLine()) {
       last_line_inst = nullptr;
-    } else if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
+    } else if (opcode == spv::Op::OpLoopMerge ||
+               opcode == spv::Op::OpSelectionMerge) {
       between_merge_and_branch = true;
       last_line_inst = nullptr;
     } else if (i->IsLine()) {
@@ -272,7 +275,7 @@
 std::ostream& operator<<(std::ostream& str, const Module& module) {
   module.ForEachInst([&str](const Instruction* inst) {
     str << *inst;
-    if (inst->opcode() != SpvOpFunctionEnd) {
+    if (inst->opcode() != spv::Op::OpFunctionEnd) {
       str << std::endl;
     }
   });
diff --git a/third_party/SPIRV-Tools/source/opt/module.h b/third_party/SPIRV-Tools/source/opt/module.h
index 7a6be46..ed2f345 100644
--- a/third_party/SPIRV-Tools/source/opt/module.h
+++ b/third_party/SPIRV-Tools/source/opt/module.h
@@ -136,10 +136,10 @@
   std::vector<const Instruction*> GetConstants() const;
 
   // Return result id of global value with |opcode|, 0 if not present.
-  uint32_t GetGlobalValue(SpvOp opcode) const;
+  uint32_t GetGlobalValue(spv::Op opcode) const;
 
   // Add global value with |opcode|, |result_id| and |type_id|
-  void AddGlobalValue(SpvOp opcode, uint32_t result_id, uint32_t type_id);
+  void AddGlobalValue(spv::Op opcode, uint32_t result_id, uint32_t type_id);
 
   inline uint32_t id_bound() const { return header_.bound; }
 
diff --git a/third_party/SPIRV-Tools/source/opt/optimizer.cpp b/third_party/SPIRV-Tools/source/opt/optimizer.cpp
index 381589b..4cf3292 100644
--- a/third_party/SPIRV-Tools/source/opt/optimizer.cpp
+++ b/third_party/SPIRV-Tools/source/opt/optimizer.cpp
@@ -60,6 +60,7 @@
 
   spv_target_env target_env;      // Target environment.
   opt::PassManager pass_manager;  // Internal implementation pass manager.
+  std::unordered_set<uint32_t> live_locs;  // Arg to debug dead output passes
 };
 
 Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {
@@ -524,7 +525,7 @@
   } else if (pass_name == "remove-dont-inline") {
     RegisterPass(CreateRemoveDontInlinePass());
   } else if (pass_name == "eliminate-dead-input-components") {
-    RegisterPass(CreateEliminateDeadInputComponentsPass());
+    RegisterPass(CreateEliminateDeadInputComponentsSafePass());
   } else if (pass_name == "fix-func-call-param") {
     RegisterPass(CreateFixFuncCallArgumentsPass());
   } else if (pass_name == "convert-to-sampled-image") {
@@ -1016,9 +1017,35 @@
 
 Optimizer::PassToken CreateEliminateDeadInputComponentsPass() {
   return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::EliminateDeadInputComponentsPass>(
+          /* output_instead */ false, /* vertex_shader_only */ false));
+}
+
+Optimizer::PassToken CreateEliminateDeadOutputComponentsPass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::EliminateDeadInputComponentsPass>(
+          /* output_instead */ true, /* vertex_shader_only */ false));
+}
+
+Optimizer::PassToken CreateEliminateDeadInputComponentsSafePass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(
       MakeUnique<opt::EliminateDeadInputComponentsPass>());
 }
 
+Optimizer::PassToken CreateAnalyzeLiveInputPass(
+    std::unordered_set<uint32_t>* live_locs,
+    std::unordered_set<uint32_t>* live_builtins) {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::AnalyzeLiveInputPass>(live_locs, live_builtins));
+}
+
+Optimizer::PassToken CreateEliminateDeadOutputStoresPass(
+    std::unordered_set<uint32_t>* live_locs,
+    std::unordered_set<uint32_t>* live_builtins) {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::EliminateDeadOutputStoresPass>(live_locs, live_builtins));
+}
+
 Optimizer::PassToken CreateConvertToSampledImagePass(
     const std::vector<opt::DescriptorSetAndBinding>&
         descriptor_set_binding_pairs) {
diff --git a/third_party/SPIRV-Tools/source/opt/pass.cpp b/third_party/SPIRV-Tools/source/opt/pass.cpp
index 017aad1..75c3740 100644
--- a/third_party/SPIRV-Tools/source/opt/pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/pass.cpp
@@ -21,11 +21,8 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
-
-const uint32_t kTypePointerTypeIdInIdx = 1;
-
+constexpr uint32_t kTypePointerTypeIdInIdx = 1;
 }  // namespace
 
 Pass::Pass() : consumer_(nullptr), context_(nullptr), already_run_(false) {}
@@ -56,11 +53,11 @@
 
 Instruction* Pass::GetBaseType(uint32_t ty_id) {
   Instruction* ty_inst = get_def_use_mgr()->GetDef(ty_id);
-  if (ty_inst->opcode() == SpvOpTypeMatrix) {
+  if (ty_inst->opcode() == spv::Op::OpTypeMatrix) {
     uint32_t vty_id = ty_inst->GetSingleWordInOperand(0);
     ty_inst = get_def_use_mgr()->GetDef(vty_id);
   }
-  if (ty_inst->opcode() == SpvOpTypeVector) {
+  if (ty_inst->opcode() == spv::Op::OpTypeVector) {
     uint32_t cty_id = ty_inst->GetSingleWordInOperand(0);
     ty_inst = get_def_use_mgr()->GetDef(cty_id);
   }
@@ -69,12 +66,12 @@
 
 bool Pass::IsFloat(uint32_t ty_id, uint32_t width) {
   Instruction* ty_inst = GetBaseType(ty_id);
-  if (ty_inst->opcode() != SpvOpTypeFloat) return false;
+  if (ty_inst->opcode() != spv::Op::OpTypeFloat) return false;
   return ty_inst->GetSingleWordInOperand(0) == width;
 }
 
 uint32_t Pass::GetNullId(uint32_t type_id) {
-  if (IsFloat(type_id, 16)) context()->AddCapability(SpvCapabilityFloat16);
+  if (IsFloat(type_id, 16)) context()->AddCapability(spv::Capability::Float16);
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
   const analysis::Type* type = type_mgr->GetType(type_id);
diff --git a/third_party/SPIRV-Tools/source/opt/pass_manager.cpp b/third_party/SPIRV-Tools/source/opt/pass_manager.cpp
index a73ff7c..d3c47e7 100644
--- a/third_party/SPIRV-Tools/source/opt/pass_manager.cpp
+++ b/third_party/SPIRV-Tools/source/opt/pass_manager.cpp
@@ -39,7 +39,7 @@
       t.SetMessageConsumer(consumer());
       std::string disassembly;
       std::string pass_name = (pass ? pass->name() : "");
-      if (!t.Disassemble(binary, &disassembly, 0)) {
+      if (!t.Disassemble(binary, &disassembly)) {
         std::string msg = "Disassembly failed before pass ";
         msg += pass_name + "\n";
         spv_position_t null_pos{0, 0, 0};
diff --git a/third_party/SPIRV-Tools/source/opt/passes.h b/third_party/SPIRV-Tools/source/opt/passes.h
index 21354c7..5344dcf 100644
--- a/third_party/SPIRV-Tools/source/opt/passes.h
+++ b/third_party/SPIRV-Tools/source/opt/passes.h
@@ -19,6 +19,7 @@
 
 #include "source/opt/aggressive_dead_code_elim_pass.h"
 #include "source/opt/amd_ext_to_khr.h"
+#include "source/opt/analyze_live_input_pass.h"
 #include "source/opt/block_merge_pass.h"
 #include "source/opt/ccp_pass.h"
 #include "source/opt/cfg_cleanup_pass.h"
@@ -36,6 +37,7 @@
 #include "source/opt/eliminate_dead_functions_pass.h"
 #include "source/opt/eliminate_dead_input_components_pass.h"
 #include "source/opt/eliminate_dead_members_pass.h"
+#include "source/opt/eliminate_dead_output_stores_pass.h"
 #include "source/opt/empty_pass.h"
 #include "source/opt/fix_func_call_arguments.h"
 #include "source/opt/fix_storage_class.h"
diff --git a/third_party/SPIRV-Tools/source/opt/private_to_local_pass.cpp b/third_party/SPIRV-Tools/source/opt/private_to_local_pass.cpp
index 80fb4c5..4904e05 100644
--- a/third_party/SPIRV-Tools/source/opt/private_to_local_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/private_to_local_pass.cpp
@@ -24,10 +24,8 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-const uint32_t kVariableStorageClassInIdx = 0;
-const uint32_t kSpvTypePointerTypeIdInIdx = 1;
-
+constexpr uint32_t kVariableStorageClassInIdx = 0;
+constexpr uint32_t kSpvTypePointerTypeIdInIdx = 1;
 }  // namespace
 
 Pass::Status PrivateToLocalPass::Process() {
@@ -35,18 +33,18 @@
 
   // Private variables require the shader capability.  If this is not a shader,
   // there is no work to do.
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
     return Status::SuccessWithoutChange;
 
   std::vector<std::pair<Instruction*, Function*>> variables_to_move;
   std::unordered_set<uint32_t> localized_variables;
   for (auto& inst : context()->types_values()) {
-    if (inst.opcode() != SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       continue;
     }
 
-    if (inst.GetSingleWordInOperand(kVariableStorageClassInIdx) !=
-        SpvStorageClassPrivate) {
+    if (spv::StorageClass(inst.GetSingleWordInOperand(
+            kVariableStorageClassInIdx)) != spv::StorageClass::Private) {
       continue;
     }
 
@@ -123,7 +121,8 @@
   context()->ForgetUses(variable);
 
   // Update the storage class of the variable.
-  variable->SetInOperand(kVariableStorageClassInIdx, {SpvStorageClassFunction});
+  variable->SetInOperand(kVariableStorageClassInIdx,
+                         {uint32_t(spv::StorageClass::Function)});
 
   // Update the type as well.
   uint32_t new_type_id = GetNewType(variable->type_id());
@@ -147,7 +146,7 @@
   uint32_t pointee_type_id =
       old_type_inst->GetSingleWordInOperand(kSpvTypePointerTypeIdInIdx);
   uint32_t new_type_id =
-      type_mgr->FindPointerToType(pointee_type_id, SpvStorageClassFunction);
+      type_mgr->FindPointerToType(pointee_type_id, spv::StorageClass::Function);
   if (new_type_id != 0) {
     context()->UpdateDefUse(context()->get_def_use_mgr()->GetDef(new_type_id));
   }
@@ -161,17 +160,17 @@
     return true;
   }
   switch (inst->opcode()) {
-    case SpvOpLoad:
-    case SpvOpStore:
-    case SpvOpImageTexelPointer:  // Treat like a load
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
+    case spv::Op::OpImageTexelPointer:  // Treat like a load
       return true;
-    case SpvOpAccessChain:
+    case spv::Op::OpAccessChain:
       return context()->get_def_use_mgr()->WhileEachUser(
           inst, [this](const Instruction* user) {
             if (!IsValidUse(user)) return false;
             return true;
           });
-    case SpvOpName:
+    case spv::Op::OpName:
       return true;
     default:
       return spvOpcodeIsDecoration(inst->opcode());
@@ -188,13 +187,13 @@
     return true;
   }
   switch (inst->opcode()) {
-    case SpvOpLoad:
-    case SpvOpStore:
-    case SpvOpImageTexelPointer:  // Treat like a load
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
+    case spv::Op::OpImageTexelPointer:  // Treat like a load
       // The type is fine because it is the type pointed to, and that does not
       // change.
       break;
-    case SpvOpAccessChain: {
+    case spv::Op::OpAccessChain: {
       context()->ForgetUses(inst);
       uint32_t new_type_id = GetNewType(inst->type_id());
       if (new_type_id == 0) {
@@ -208,8 +207,8 @@
         return false;
       }
     } break;
-    case SpvOpName:
-    case SpvOpEntryPoint:  // entry points will be updated separately.
+    case spv::Op::OpName:
+    case spv::Op::OpEntryPoint:  // entry points will be updated separately.
       break;
     default:
       assert(spvOpcodeIsDecoration(inst->opcode()) &&
diff --git a/third_party/SPIRV-Tools/source/opt/propagator.cpp b/third_party/SPIRV-Tools/source/opt/propagator.cpp
index 6a1f1aa..9cd6174 100644
--- a/third_party/SPIRV-Tools/source/opt/propagator.cpp
+++ b/third_party/SPIRV-Tools/source/opt/propagator.cpp
@@ -134,7 +134,7 @@
   // defined at an instruction D that should be simulated again, then the output
   // of D might affect |instr|, so we should simulate |instr| again.
   bool has_operands_to_simulate = false;
-  if (instr->opcode() == SpvOpPhi) {
+  if (instr->opcode() == spv::Op::OpPhi) {
     // For Phi instructions, an operand causes the Phi to be simulated again if
     // the operand comes from an edge that has not yet been traversed or if its
     // definition should be simulated again.
@@ -189,7 +189,7 @@
   // statement in it.
   if (!BlockHasBeenSimulated(block)) {
     block->ForEachInst([this, &changed](Instruction* instr) {
-      if (instr->opcode() != SpvOpPhi) {
+      if (instr->opcode() != spv::Op::OpPhi) {
         changed |= Simulate(instr);
       }
     });
diff --git a/third_party/SPIRV-Tools/source/opt/propagator.h b/third_party/SPIRV-Tools/source/opt/propagator.h
index ac7c0e7..71212c9 100644
--- a/third_party/SPIRV-Tools/source/opt/propagator.h
+++ b/third_party/SPIRV-Tools/source/opt/propagator.h
@@ -153,10 +153,10 @@
 //   std::map<uint32_t, uint32_t> values;
 //   const auto visit_fn = [&ctx, &values](Instruction* instr,
 //                                         BasicBlock** dest_bb) {
-//     if (instr->opcode() == SpvOpStore) {
+//     if (instr->opcode() == spv::Op::OpStore) {
 //       uint32_t rhs_id = instr->GetSingleWordOperand(1);
 //       Instruction* rhs_def = ctx->get_def_use_mgr()->GetDef(rhs_id);
-//       if (rhs_def->opcode() == SpvOpConstant) {
+//       if (rhs_def->opcode() == spv::Op::OpConstant) {
 //         uint32_t val = rhs_def->GetSingleWordOperand(2);
 //         values[rhs_id] = val;
 //         return SSAPropagator::kInteresting;
diff --git a/third_party/SPIRV-Tools/source/opt/reduce_load_size.cpp b/third_party/SPIRV-Tools/source/opt/reduce_load_size.cpp
index 56491b2..73a90f0 100644
--- a/third_party/SPIRV-Tools/source/opt/reduce_load_size.cpp
+++ b/third_party/SPIRV-Tools/source/opt/reduce_load_size.cpp
@@ -22,23 +22,20 @@
 #include "source/opt/ir_context.h"
 #include "source/util/bit_vector.h"
 
-namespace {
-
-const uint32_t kExtractCompositeIdInIdx = 0;
-const uint32_t kVariableStorageClassInIdx = 0;
-const uint32_t kLoadPointerInIdx = 0;
-
-}  // namespace
-
 namespace spvtools {
 namespace opt {
+namespace {
+constexpr uint32_t kExtractCompositeIdInIdx = 0;
+constexpr uint32_t kVariableStorageClassInIdx = 0;
+constexpr uint32_t kLoadPointerInIdx = 0;
+}  // namespace
 
 Pass::Status ReduceLoadSize::Process() {
   bool modified = false;
 
   for (auto& func : *get_module()) {
     func.ForEachInst([&modified, this](Instruction* inst) {
-      if (inst->opcode() == SpvOpCompositeExtract) {
+      if (inst->opcode() == spv::Op::OpCompositeExtract) {
         if (ShouldReplaceExtract(inst)) {
           modified |= ReplaceExtract(inst);
         }
@@ -50,7 +47,7 @@
 }
 
 bool ReduceLoadSize::ReplaceExtract(Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeExtract &&
+  assert(inst->opcode() == spv::Op::OpCompositeExtract &&
          "Wrong opcode.  Should be OpCompositeExtract.");
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
@@ -60,7 +57,7 @@
       inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
   Instruction* composite_inst = def_use_mgr->GetDef(composite_id);
 
-  if (composite_inst->opcode() != SpvOpLoad) {
+  if (composite_inst->opcode() != spv::Op::OpLoad) {
     return false;
   }
 
@@ -71,16 +68,16 @@
   }
 
   Instruction* var = composite_inst->GetBaseAddress();
-  if (var == nullptr || var->opcode() != SpvOpVariable) {
+  if (var == nullptr || var->opcode() != spv::Op::OpVariable) {
     return false;
   }
 
-  SpvStorageClass storage_class = static_cast<SpvStorageClass>(
+  spv::StorageClass storage_class = static_cast<spv::StorageClass>(
       var->GetSingleWordInOperand(kVariableStorageClassInIdx));
   switch (storage_class) {
-    case SpvStorageClassUniform:
-    case SpvStorageClassUniformConstant:
-    case SpvStorageClassInput:
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::UniformConstant:
+    case spv::StorageClass::Input:
       break;
     default:
       return false;
@@ -124,7 +121,7 @@
   Instruction* op_inst = def_use_mgr->GetDef(
       inst->GetSingleWordInOperand(kExtractCompositeIdInIdx));
 
-  if (op_inst->opcode() != SpvOpLoad) {
+  if (op_inst->opcode() != spv::Op::OpLoad) {
     return false;
   }
 
@@ -139,7 +136,7 @@
   all_elements_used =
       !def_use_mgr->WhileEachUser(op_inst, [&elements_used](Instruction* use) {
         if (use->IsCommonDebugInstr()) return true;
-        if (use->opcode() != SpvOpCompositeExtract ||
+        if (use->opcode() != spv::Op::OpCompositeExtract ||
             use->NumInOperands() == 1) {
           return false;
         }
diff --git a/third_party/SPIRV-Tools/source/opt/reflect.h b/third_party/SPIRV-Tools/source/opt/reflect.h
index c2ffb0b..1c34600 100644
--- a/third_party/SPIRV-Tools/source/opt/reflect.h
+++ b/third_party/SPIRV-Tools/source/opt/reflect.h
@@ -24,41 +24,48 @@
 // following functions tend to be outdated and should be updated when SPIR-V
 // version bumps.
 
-inline bool IsDebug1Inst(SpvOp opcode) {
-  return (opcode >= SpvOpSourceContinued && opcode <= SpvOpSourceExtension) ||
-         opcode == SpvOpString;
+inline bool IsDebug1Inst(spv::Op opcode) {
+  return (opcode >= spv::Op::OpSourceContinued &&
+          opcode <= spv::Op::OpSourceExtension) ||
+         opcode == spv::Op::OpString;
 }
-inline bool IsDebug2Inst(SpvOp opcode) {
-  return opcode == SpvOpName || opcode == SpvOpMemberName;
+inline bool IsDebug2Inst(spv::Op opcode) {
+  return opcode == spv::Op::OpName || opcode == spv::Op::OpMemberName;
 }
-inline bool IsDebug3Inst(SpvOp opcode) {
-  return opcode == SpvOpModuleProcessed;
+inline bool IsDebug3Inst(spv::Op opcode) {
+  return opcode == spv::Op::OpModuleProcessed;
 }
-inline bool IsOpLineInst(SpvOp opcode) {
-  return opcode == SpvOpLine || opcode == SpvOpNoLine;
+inline bool IsOpLineInst(spv::Op opcode) {
+  return opcode == spv::Op::OpLine || opcode == spv::Op::OpNoLine;
 }
-inline bool IsAnnotationInst(SpvOp opcode) {
-  return (opcode >= SpvOpDecorate && opcode <= SpvOpGroupMemberDecorate) ||
-         opcode == SpvOpDecorateId || opcode == SpvOpDecorateStringGOOGLE ||
-         opcode == SpvOpMemberDecorateStringGOOGLE;
+inline bool IsAnnotationInst(spv::Op opcode) {
+  return (opcode >= spv::Op::OpDecorate &&
+          opcode <= spv::Op::OpGroupMemberDecorate) ||
+         opcode == spv::Op::OpDecorateId ||
+         opcode == spv::Op::OpDecorateStringGOOGLE ||
+         opcode == spv::Op::OpMemberDecorateStringGOOGLE;
 }
-inline bool IsTypeInst(SpvOp opcode) {
-  return (opcode >= SpvOpTypeVoid && opcode <= SpvOpTypeForwardPointer) ||
-         opcode == SpvOpTypePipeStorage || opcode == SpvOpTypeNamedBarrier ||
-         opcode == SpvOpTypeAccelerationStructureNV ||
-         opcode == SpvOpTypeAccelerationStructureKHR ||
-         opcode == SpvOpTypeRayQueryKHR ||
-         opcode == SpvOpTypeCooperativeMatrixNV;
+inline bool IsTypeInst(spv::Op opcode) {
+  return (opcode >= spv::Op::OpTypeVoid &&
+          opcode <= spv::Op::OpTypeForwardPointer) ||
+         opcode == spv::Op::OpTypePipeStorage ||
+         opcode == spv::Op::OpTypeNamedBarrier ||
+         opcode == spv::Op::OpTypeAccelerationStructureNV ||
+         opcode == spv::Op::OpTypeAccelerationStructureKHR ||
+         opcode == spv::Op::OpTypeRayQueryKHR ||
+         opcode == spv::Op::OpTypeCooperativeMatrixNV;
 }
-inline bool IsConstantInst(SpvOp opcode) {
-  return (opcode >= SpvOpConstantTrue && opcode <= SpvOpSpecConstantOp) ||
-         opcode == SpvOpConstantFunctionPointerINTEL;
+inline bool IsConstantInst(spv::Op opcode) {
+  return (opcode >= spv::Op::OpConstantTrue &&
+          opcode <= spv::Op::OpSpecConstantOp) ||
+         opcode == spv::Op::OpConstantFunctionPointerINTEL;
 }
-inline bool IsCompileTimeConstantInst(SpvOp opcode) {
-  return opcode >= SpvOpConstantTrue && opcode <= SpvOpConstantNull;
+inline bool IsCompileTimeConstantInst(spv::Op opcode) {
+  return opcode >= spv::Op::OpConstantTrue && opcode <= spv::Op::OpConstantNull;
 }
-inline bool IsSpecConstantInst(SpvOp opcode) {
-  return opcode >= SpvOpSpecConstantTrue && opcode <= SpvOpSpecConstantOp;
+inline bool IsSpecConstantInst(spv::Op opcode) {
+  return opcode >= spv::Op::OpSpecConstantTrue &&
+         opcode <= spv::Op::OpSpecConstantOp;
 }
 
 }  // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/register_pressure.cpp b/third_party/SPIRV-Tools/source/opt/register_pressure.cpp
index 1ad3373..34a8ba3 100644
--- a/third_party/SPIRV-Tools/source/opt/register_pressure.cpp
+++ b/third_party/SPIRV-Tools/source/opt/register_pressure.cpp
@@ -26,7 +26,6 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
 // Predicate for the FilterIterator to only consider instructions that are not
 // phi instructions defined in the basic block |bb|.
@@ -36,7 +35,7 @@
       : context_(context), bb_(bb) {}
 
   bool operator()(Instruction* insn) const {
-    return !(insn->opcode() == SpvOpPhi &&
+    return !(insn->opcode() == spv::Op::OpPhi &&
              context_->get_instr_block(insn) == bb_);
   }
 
@@ -49,9 +48,9 @@
 // physical register.
 bool CreatesRegisterUsage(Instruction* insn) {
   if (!insn->HasResultId()) return false;
-  if (insn->opcode() == SpvOpUndef) return false;
+  if (insn->opcode() == spv::Op::OpUndef) return false;
   if (IsConstantInst(insn->opcode())) return false;
-  if (insn->opcode() == SpvOpLabel) return false;
+  if (insn->opcode() == spv::Op::OpLabel) return false;
   return true;
 }
 
@@ -147,7 +146,7 @@
 
     live_inout->live_in_ = live_inout->live_out_;
     for (Instruction& insn : make_range(bb->rbegin(), bb->rend())) {
-      if (insn.opcode() == SpvOpPhi) {
+      if (insn.opcode() == spv::Op::OpPhi) {
         live_inout->live_in_.insert(&insn);
         break;
       }
@@ -224,7 +223,7 @@
       for (Instruction& insn : make_range(bb.rbegin(), bb.rend())) {
         // If it is a phi instruction, the register pressure will not change
         // anymore.
-        if (insn.opcode() == SpvOpPhi) {
+        if (insn.opcode() == spv::Op::OpPhi) {
           break;
         }
 
@@ -271,7 +270,7 @@
   RegisterLiveness::RegisterClass reg_class{type, false};
 
   insn->context()->get_decoration_mgr()->WhileEachDecoration(
-      insn->result_id(), SpvDecorationUniform,
+      insn->result_id(), uint32_t(spv::Decoration::Uniform),
       [&reg_class](const Instruction&) {
         reg_class.is_uniform_ = true;
         return false;
@@ -325,7 +324,7 @@
         loop_reg_pressure->used_registers_, live_inout->used_registers_);
 
     for (Instruction& insn : *bb) {
-      if (insn.opcode() == SpvOpPhi || !CreatesRegisterUsage(&insn) ||
+      if (insn.opcode() == spv::Op::OpPhi || !CreatesRegisterUsage(&insn) ||
           seen_insn.count(insn.result_id())) {
         continue;
       }
@@ -386,7 +385,7 @@
       [&l1, &l2](Instruction* insn) {
         BasicBlock* bb = insn->context()->get_instr_block(insn);
         return insn->HasResultId() &&
-               !(insn->opcode() == SpvOpPhi &&
+               !(insn->opcode() == spv::Op::OpPhi &&
                  (bb == l1.GetHeaderBlock() || bb == l2.GetHeaderBlock()));
       });
 
@@ -403,7 +402,7 @@
                      live_inout_info->live_out_.size());
 
     for (Instruction& insn : *bb) {
-      if (insn.opcode() == SpvOpPhi || !CreatesRegisterUsage(&insn) ||
+      if (insn.opcode() == spv::Op::OpPhi || !CreatesRegisterUsage(&insn) ||
           seen_insn.count(insn.result_id())) {
         continue;
       }
@@ -434,7 +433,7 @@
                      live_inout_info->live_out_.size());
 
     for (Instruction& insn : *bb) {
-      if (insn.opcode() == SpvOpPhi || !CreatesRegisterUsage(&insn) ||
+      if (insn.opcode() == spv::Op::OpPhi || !CreatesRegisterUsage(&insn) ||
           seen_insn.count(insn.result_id())) {
         continue;
       }
@@ -532,7 +531,7 @@
 
     std::unordered_set<uint32_t> die_in_block;
     for (Instruction& insn : make_range(bb->rbegin(), bb->rend())) {
-      if (insn.opcode() == SpvOpPhi) {
+      if (insn.opcode() == spv::Op::OpPhi) {
         break;
       }
 
diff --git a/third_party/SPIRV-Tools/source/opt/relax_float_ops_pass.cpp b/third_party/SPIRV-Tools/source/opt/relax_float_ops_pass.cpp
index 3fcf879..df925a2 100644
--- a/third_party/SPIRV-Tools/source/opt/relax_float_ops_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/relax_float_ops_pass.cpp
@@ -25,7 +25,7 @@
   return target_ops_core_f_rslt_.count(inst->opcode()) != 0 ||
          target_ops_core_f_opnd_.count(inst->opcode()) != 0 ||
          sample_ops_.count(inst->opcode()) != 0 ||
-         (inst->opcode() == SpvOpExtInst &&
+         (inst->opcode() == spv::Op::OpExtInst &&
           inst->GetSingleWordInOperand(0) ==
               context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
           target_ops_450_.count(inst->GetSingleWordInOperand(1)) != 0);
@@ -46,8 +46,9 @@
 
 bool RelaxFloatOpsPass::IsRelaxed(uint32_t r_id) {
   for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false))
-    if (r_inst->opcode() == SpvOpDecorate &&
-        r_inst->GetSingleWordInOperand(1) == SpvDecorationRelaxedPrecision)
+    if (r_inst->opcode() == spv::Op::OpDecorate &&
+        spv::Decoration(r_inst->GetSingleWordInOperand(1)) ==
+            spv::Decoration::RelaxedPrecision)
       return true;
   return false;
 }
@@ -58,7 +59,8 @@
   if (!IsFloat32(r_inst)) return false;
   if (IsRelaxed(r_id)) return false;
   if (!IsRelaxable(r_inst)) return false;
-  get_decoration_mgr()->AddDecoration(r_id, SpvDecorationRelaxedPrecision);
+  get_decoration_mgr()->AddDecoration(
+      r_id, uint32_t(spv::Decoration::RelaxedPrecision));
   return true;
 }
 
@@ -87,48 +89,48 @@
 
 void RelaxFloatOpsPass::Initialize() {
   target_ops_core_f_rslt_ = {
-      SpvOpLoad,
-      SpvOpPhi,
-      SpvOpVectorExtractDynamic,
-      SpvOpVectorInsertDynamic,
-      SpvOpVectorShuffle,
-      SpvOpCompositeExtract,
-      SpvOpCompositeConstruct,
-      SpvOpCompositeInsert,
-      SpvOpCopyObject,
-      SpvOpTranspose,
-      SpvOpConvertSToF,
-      SpvOpConvertUToF,
-      SpvOpFConvert,
-      // SpvOpQuantizeToF16,
-      SpvOpFNegate,
-      SpvOpFAdd,
-      SpvOpFSub,
-      SpvOpFMul,
-      SpvOpFDiv,
-      SpvOpFMod,
-      SpvOpVectorTimesScalar,
-      SpvOpMatrixTimesScalar,
-      SpvOpVectorTimesMatrix,
-      SpvOpMatrixTimesVector,
-      SpvOpMatrixTimesMatrix,
-      SpvOpOuterProduct,
-      SpvOpDot,
-      SpvOpSelect,
+      spv::Op::OpLoad,
+      spv::Op::OpPhi,
+      spv::Op::OpVectorExtractDynamic,
+      spv::Op::OpVectorInsertDynamic,
+      spv::Op::OpVectorShuffle,
+      spv::Op::OpCompositeExtract,
+      spv::Op::OpCompositeConstruct,
+      spv::Op::OpCompositeInsert,
+      spv::Op::OpCopyObject,
+      spv::Op::OpTranspose,
+      spv::Op::OpConvertSToF,
+      spv::Op::OpConvertUToF,
+      spv::Op::OpFConvert,
+      // spv::Op::OpQuantizeToF16,
+      spv::Op::OpFNegate,
+      spv::Op::OpFAdd,
+      spv::Op::OpFSub,
+      spv::Op::OpFMul,
+      spv::Op::OpFDiv,
+      spv::Op::OpFMod,
+      spv::Op::OpVectorTimesScalar,
+      spv::Op::OpMatrixTimesScalar,
+      spv::Op::OpVectorTimesMatrix,
+      spv::Op::OpMatrixTimesVector,
+      spv::Op::OpMatrixTimesMatrix,
+      spv::Op::OpOuterProduct,
+      spv::Op::OpDot,
+      spv::Op::OpSelect,
   };
   target_ops_core_f_opnd_ = {
-      SpvOpFOrdEqual,
-      SpvOpFUnordEqual,
-      SpvOpFOrdNotEqual,
-      SpvOpFUnordNotEqual,
-      SpvOpFOrdLessThan,
-      SpvOpFUnordLessThan,
-      SpvOpFOrdGreaterThan,
-      SpvOpFUnordGreaterThan,
-      SpvOpFOrdLessThanEqual,
-      SpvOpFUnordLessThanEqual,
-      SpvOpFOrdGreaterThanEqual,
-      SpvOpFUnordGreaterThanEqual,
+      spv::Op::OpFOrdEqual,
+      spv::Op::OpFUnordEqual,
+      spv::Op::OpFOrdNotEqual,
+      spv::Op::OpFUnordNotEqual,
+      spv::Op::OpFOrdLessThan,
+      spv::Op::OpFUnordLessThan,
+      spv::Op::OpFOrdGreaterThan,
+      spv::Op::OpFUnordGreaterThan,
+      spv::Op::OpFOrdLessThanEqual,
+      spv::Op::OpFUnordLessThanEqual,
+      spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThanEqual,
   };
   target_ops_450_ = {
       GLSLstd450Round, GLSLstd450RoundEven, GLSLstd450Trunc, GLSLstd450FAbs,
@@ -147,31 +149,31 @@
       GLSLstd450Ldexp, GLSLstd450Length, GLSLstd450Distance, GLSLstd450Cross,
       GLSLstd450Normalize, GLSLstd450FaceForward, GLSLstd450Reflect,
       GLSLstd450Refract, GLSLstd450NMin, GLSLstd450NMax, GLSLstd450NClamp};
-  sample_ops_ = {SpvOpImageSampleImplicitLod,
-                 SpvOpImageSampleExplicitLod,
-                 SpvOpImageSampleDrefImplicitLod,
-                 SpvOpImageSampleDrefExplicitLod,
-                 SpvOpImageSampleProjImplicitLod,
-                 SpvOpImageSampleProjExplicitLod,
-                 SpvOpImageSampleProjDrefImplicitLod,
-                 SpvOpImageSampleProjDrefExplicitLod,
-                 SpvOpImageFetch,
-                 SpvOpImageGather,
-                 SpvOpImageDrefGather,
-                 SpvOpImageRead,
-                 SpvOpImageSparseSampleImplicitLod,
-                 SpvOpImageSparseSampleExplicitLod,
-                 SpvOpImageSparseSampleDrefImplicitLod,
-                 SpvOpImageSparseSampleDrefExplicitLod,
-                 SpvOpImageSparseSampleProjImplicitLod,
-                 SpvOpImageSparseSampleProjExplicitLod,
-                 SpvOpImageSparseSampleProjDrefImplicitLod,
-                 SpvOpImageSparseSampleProjDrefExplicitLod,
-                 SpvOpImageSparseFetch,
-                 SpvOpImageSparseGather,
-                 SpvOpImageSparseDrefGather,
-                 SpvOpImageSparseTexelsResident,
-                 SpvOpImageSparseRead};
+  sample_ops_ = {spv::Op::OpImageSampleImplicitLod,
+                 spv::Op::OpImageSampleExplicitLod,
+                 spv::Op::OpImageSampleDrefImplicitLod,
+                 spv::Op::OpImageSampleDrefExplicitLod,
+                 spv::Op::OpImageSampleProjImplicitLod,
+                 spv::Op::OpImageSampleProjExplicitLod,
+                 spv::Op::OpImageSampleProjDrefImplicitLod,
+                 spv::Op::OpImageSampleProjDrefExplicitLod,
+                 spv::Op::OpImageFetch,
+                 spv::Op::OpImageGather,
+                 spv::Op::OpImageDrefGather,
+                 spv::Op::OpImageRead,
+                 spv::Op::OpImageSparseSampleImplicitLod,
+                 spv::Op::OpImageSparseSampleExplicitLod,
+                 spv::Op::OpImageSparseSampleDrefImplicitLod,
+                 spv::Op::OpImageSparseSampleDrefExplicitLod,
+                 spv::Op::OpImageSparseSampleProjImplicitLod,
+                 spv::Op::OpImageSparseSampleProjExplicitLod,
+                 spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+                 spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+                 spv::Op::OpImageSparseFetch,
+                 spv::Op::OpImageSparseGather,
+                 spv::Op::OpImageSparseDrefGather,
+                 spv::Op::OpImageSparseTexelsResident,
+                 spv::Op::OpImageSparseRead};
 }
 
 }  // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/relax_float_ops_pass.h b/third_party/SPIRV-Tools/source/opt/relax_float_ops_pass.h
index 5ee3d73..9e4606f 100644
--- a/third_party/SPIRV-Tools/source/opt/relax_float_ops_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/relax_float_ops_pass.h
@@ -61,17 +61,23 @@
   // Initialize state for converting to half
   void Initialize();
 
+  struct hasher {
+    size_t operator()(const spv::Op& op) const noexcept {
+      return std::hash<uint32_t>()(uint32_t(op));
+    }
+  };
+
   // Set of float result core operations to be processed
-  std::unordered_set<uint32_t> target_ops_core_f_rslt_;
+  std::unordered_set<spv::Op, hasher> target_ops_core_f_rslt_;
 
   // Set of float operand core operations to be processed
-  std::unordered_set<uint32_t> target_ops_core_f_opnd_;
+  std::unordered_set<spv::Op, hasher> target_ops_core_f_opnd_;
 
   // Set of 450 extension operations to be processed
   std::unordered_set<uint32_t> target_ops_450_;
 
   // Set of sample operations
-  std::unordered_set<uint32_t> sample_ops_;
+  std::unordered_set<spv::Op, hasher> sample_ops_;
 };
 
 }  // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/remove_dontinline_pass.cpp b/third_party/SPIRV-Tools/source/opt/remove_dontinline_pass.cpp
index 4dd1cd4..3750bc1 100644
--- a/third_party/SPIRV-Tools/source/opt/remove_dontinline_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/remove_dontinline_pass.cpp
@@ -37,10 +37,11 @@
   uint32_t function_control =
       function_inst->GetSingleWordInOperand(kFunctionControlInOperandIdx);
 
-  if ((function_control & SpvFunctionControlDontInlineMask) == 0) {
+  if ((function_control & uint32_t(spv::FunctionControlMask::DontInline)) ==
+      0) {
     return false;
   }
-  function_control &= ~SpvFunctionControlDontInlineMask;
+  function_control &= ~uint32_t(spv::FunctionControlMask::DontInline);
   function_inst->SetInOperand(kFunctionControlInOperandIdx, {function_control});
   return true;
 }
diff --git a/third_party/SPIRV-Tools/source/opt/remove_duplicates_pass.cpp b/third_party/SPIRV-Tools/source/opt/remove_duplicates_pass.cpp
index 1ed8e2a..90c3acf 100644
--- a/third_party/SPIRV-Tools/source/opt/remove_duplicates_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/remove_duplicates_pass.cpp
@@ -70,7 +70,7 @@
     return modified;
   }
 
-  std::unordered_map<std::string, SpvId> ext_inst_imports;
+  std::unordered_map<std::string, spv::Id> ext_inst_imports;
   for (auto* i = &*context()->ext_inst_import_begin(); i;) {
     auto res = ext_inst_imports.emplace(i->GetInOperand(0u).AsString(),
                                         i->result_id());
@@ -101,7 +101,8 @@
   std::vector<analysis::ForwardPointer> visited_forward_pointers;
   std::vector<Instruction*> to_delete;
   for (auto* i = &*context()->types_values_begin(); i; i = i->NextNode()) {
-    const bool is_i_forward_pointer = i->opcode() == SpvOpTypeForwardPointer;
+    const bool is_i_forward_pointer =
+        i->opcode() == spv::Op::OpTypeForwardPointer;
 
     // We only care about types.
     if (!spvOpcodeGeneratesType(i->opcode()) && !is_i_forward_pointer) {
@@ -110,7 +111,7 @@
 
     if (!is_i_forward_pointer) {
       // Is the current type equal to one of the types we have already visited?
-      SpvId id_to_keep = 0u;
+      spv::Id id_to_keep = 0u;
       analysis::Type* i_type = type_manager.GetType(i->result_id());
       assert(i_type);
       // TODO(dneto0): Use a trie to avoid quadratic behaviour? Extract the
@@ -137,7 +138,7 @@
     } else {
       analysis::ForwardPointer i_type(
           i->GetSingleWordInOperand(0u),
-          (SpvStorageClass)i->GetSingleWordInOperand(1u));
+          (spv::StorageClass)i->GetSingleWordInOperand(1u));
       i_type.SetTargetPointer(
           type_manager.GetType(i_type.target_id())->AsPointer());
 
diff --git a/third_party/SPIRV-Tools/source/opt/remove_unused_interface_variables_pass.cpp b/third_party/SPIRV-Tools/source/opt/remove_unused_interface_variables_pass.cpp
index 31e87bd..d4df1b2 100644
--- a/third_party/SPIRV-Tools/source/opt/remove_unused_interface_variables_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/remove_unused_interface_variables_pass.cpp
@@ -31,13 +31,14 @@
         instruction.ForEachInId([&](const uint32_t* id) {
           if (used_variables_.count(*id)) return;
           auto* var = parent_.get_def_use_mgr()->GetDef(*id);
-          if (!var || var->opcode() != SpvOpVariable) return;
-          auto storage_class = var->GetSingleWordInOperand(0);
-          if (storage_class != SpvStorageClassFunction &&
+          if (!var || var->opcode() != spv::Op::OpVariable) return;
+          auto storage_class =
+              spv::StorageClass(var->GetSingleWordInOperand(0));
+          if (storage_class != spv::StorageClass::Function &&
               (parent_.get_module()->version() >=
                    SPV_SPIRV_VERSION_WORD(1, 4) ||
-               storage_class == SpvStorageClassInput ||
-               storage_class == SpvStorageClassOutput))
+               storage_class == spv::StorageClass::Input ||
+               storage_class == spv::StorageClass::Output))
             used_variables_.insert(*id);
         });
     return false;
@@ -90,4 +91,4 @@
   return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
 }
 }  // namespace opt
-}  // namespace spvtools
\ No newline at end of file
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/opt/replace_desc_array_access_using_var_index.cpp b/third_party/SPIRV-Tools/source/opt/replace_desc_array_access_using_var_index.cpp
index e97593e..93c77d3 100644
--- a/third_party/SPIRV-Tools/source/opt/replace_desc_array_access_using_var_index.cpp
+++ b/third_party/SPIRV-Tools/source/opt/replace_desc_array_access_using_var_index.cpp
@@ -21,11 +21,10 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-const uint32_t kOpAccessChainInOperandIndexes = 1;
-const uint32_t kOpTypePointerInOperandType = 1;
-const uint32_t kOpTypeArrayInOperandType = 0;
-const uint32_t kOpTypeStructInOperandMember = 0;
+constexpr uint32_t kOpAccessChainInOperandIndexes = 1;
+constexpr uint32_t kOpTypePointerInOperandType = 1;
+constexpr uint32_t kOpTypeArrayInOperandType = 0;
+constexpr uint32_t kOpTypeStructInOperandMember = 0;
 IRContext::Analysis kAnalysisDefUseAndInstrToBlockMapping =
     IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping;
 
@@ -54,8 +53,8 @@
   std::vector<Instruction*> work_list;
   get_def_use_mgr()->ForEachUser(var, [&work_list](Instruction* use) {
     switch (use->opcode()) {
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
         work_list.push_back(use);
         break;
       default:
@@ -132,8 +131,8 @@
     Instruction* operand = get_def_use_mgr()->GetDef(*idp);
     if (context()->get_instr_block(operand) != nullptr &&
         (HasImageOrImagePtrType(operand) ||
-         operand->opcode() == SpvOpAccessChain ||
-         operand->opcode() == SpvOpInBoundsAccessChain)) {
+         operand->opcode() == spv::Op::OpAccessChain ||
+         operand->opcode() == spv::Op::OpInBoundsAccessChain)) {
       work_list.push(operand);
     }
   };
@@ -158,22 +157,22 @@
 
 bool ReplaceDescArrayAccessUsingVarIndex::IsImageOrImagePtrType(
     const Instruction* type_inst) const {
-  if (type_inst->opcode() == SpvOpTypeImage ||
-      type_inst->opcode() == SpvOpTypeSampler ||
-      type_inst->opcode() == SpvOpTypeSampledImage) {
+  if (type_inst->opcode() == spv::Op::OpTypeImage ||
+      type_inst->opcode() == spv::Op::OpTypeSampler ||
+      type_inst->opcode() == spv::Op::OpTypeSampledImage) {
     return true;
   }
-  if (type_inst->opcode() == SpvOpTypePointer) {
+  if (type_inst->opcode() == spv::Op::OpTypePointer) {
     Instruction* pointee_type_inst = get_def_use_mgr()->GetDef(
         type_inst->GetSingleWordInOperand(kOpTypePointerInOperandType));
     return IsImageOrImagePtrType(pointee_type_inst);
   }
-  if (type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeArray) {
     Instruction* element_type_inst = get_def_use_mgr()->GetDef(
         type_inst->GetSingleWordInOperand(kOpTypeArrayInOperandType));
     return IsImageOrImagePtrType(element_type_inst);
   }
-  if (type_inst->opcode() != SpvOpTypeStruct) return false;
+  if (type_inst->opcode() != spv::Op::OpTypeStruct) return false;
   for (uint32_t in_operand_idx = kOpTypeStructInOperandMember;
        in_operand_idx < type_inst->NumInOperands(); ++in_operand_idx) {
     Instruction* member_type_inst = get_def_use_mgr()->GetDef(
@@ -186,16 +185,16 @@
 bool ReplaceDescArrayAccessUsingVarIndex::IsConcreteType(
     uint32_t type_id) const {
   Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
-  if (type_inst->opcode() == SpvOpTypeInt ||
-      type_inst->opcode() == SpvOpTypeFloat) {
+  if (type_inst->opcode() == spv::Op::OpTypeInt ||
+      type_inst->opcode() == spv::Op::OpTypeFloat) {
     return true;
   }
-  if (type_inst->opcode() == SpvOpTypeVector ||
-      type_inst->opcode() == SpvOpTypeMatrix ||
-      type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeVector ||
+      type_inst->opcode() == spv::Op::OpTypeMatrix ||
+      type_inst->opcode() == spv::Op::OpTypeArray) {
     return IsConcreteType(type_inst->GetSingleWordInOperand(0));
   }
-  if (type_inst->opcode() == SpvOpTypeStruct) {
+  if (type_inst->opcode() == spv::Op::OpTypeStruct) {
     for (uint32_t i = 0; i < type_inst->NumInOperands(); ++i) {
       if (!IsConcreteType(type_inst->GetSingleWordInOperand(i))) return false;
     }
@@ -322,8 +321,8 @@
 }
 
 BasicBlock* ReplaceDescArrayAccessUsingVarIndex::CreateNewBlock() const {
-  auto* new_block = new BasicBlock(std::unique_ptr<Instruction>(
-      new Instruction(context(), SpvOpLabel, 0, context()->TakeNextId(), {})));
+  auto* new_block = new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
+      context(), spv::Op::OpLabel, 0, context()->TakeNextId(), {})));
   get_def_use_mgr()->AnalyzeInstDefUse(new_block->GetLabelInst());
   context()->set_instr_block(new_block->GetLabelInst(), new_block);
   return new_block;
@@ -422,7 +421,7 @@
     uint32_t old_incoming_block_id, uint32_t new_incoming_block_id) const {
   context()->ReplaceAllUsesWithPredicate(
       old_incoming_block_id, new_incoming_block_id,
-      [](Instruction* use) { return use->opcode() == SpvOpPhi; });
+      [](Instruction* use) { return use->opcode() == spv::Op::OpPhi; });
 }
 
 }  // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/replace_invalid_opc.cpp b/third_party/SPIRV-Tools/source/opt/replace_invalid_opc.cpp
index 1dcd06f..2140973 100644
--- a/third_party/SPIRV-Tools/source/opt/replace_invalid_opc.cpp
+++ b/third_party/SPIRV-Tools/source/opt/replace_invalid_opc.cpp
@@ -23,16 +23,16 @@
 Pass::Status ReplaceInvalidOpcodePass::Process() {
   bool modified = false;
 
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityLinkage)) {
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Linkage)) {
     return Status::SuccessWithoutChange;
   }
 
-  SpvExecutionModel execution_model = GetExecutionModel();
-  if (execution_model == SpvExecutionModelKernel) {
+  spv::ExecutionModel execution_model = GetExecutionModel();
+  if (execution_model == spv::ExecutionModel::Kernel) {
     // We do not handle kernels.
     return Status::SuccessWithoutChange;
   }
-  if (execution_model == SpvExecutionModelMax) {
+  if (execution_model == spv::ExecutionModel::Max) {
     // Mixed execution models for the entry points.  This case is not currently
     // handled.
     return Status::SuccessWithoutChange;
@@ -44,19 +44,19 @@
   return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
 }
 
-SpvExecutionModel ReplaceInvalidOpcodePass::GetExecutionModel() {
-  SpvExecutionModel result = SpvExecutionModelMax;
+spv::ExecutionModel ReplaceInvalidOpcodePass::GetExecutionModel() {
+  spv::ExecutionModel result = spv::ExecutionModel::Max;
   bool first = true;
   for (Instruction& entry_point : get_module()->entry_points()) {
     if (first) {
-      result =
-          static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
+      result = static_cast<spv::ExecutionModel>(
+          entry_point.GetSingleWordInOperand(0));
       first = false;
     } else {
-      SpvExecutionModel current_model =
-          static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
+      spv::ExecutionModel current_model = static_cast<spv::ExecutionModel>(
+          entry_point.GetSingleWordInOperand(0));
       if (current_model != result) {
-        result = SpvExecutionModelMax;
+        result = spv::ExecutionModel::Max;
         break;
       }
     }
@@ -65,13 +65,13 @@
 }
 
 bool ReplaceInvalidOpcodePass::RewriteFunction(Function* function,
-                                               SpvExecutionModel model) {
+                                               spv::ExecutionModel model) {
   bool modified = false;
   Instruction* last_line_dbg_inst = nullptr;
   function->ForEachInst(
       [model, &modified, &last_line_dbg_inst, this](Instruction* inst) {
         // Track the debug information so we can have a meaningful message.
-        if (inst->opcode() == SpvOpLabel || inst->IsNoLine()) {
+        if (inst->opcode() == spv::Op::OpLabel || inst->IsNoLine()) {
           last_line_dbg_inst = nullptr;
           return;
         } else if (inst->IsLine()) {
@@ -80,15 +80,15 @@
         }
 
         bool replace = false;
-        if (model != SpvExecutionModelFragment &&
+        if (model != spv::ExecutionModel::Fragment &&
             IsFragmentShaderOnlyInstruction(inst)) {
           replace = true;
         }
 
-        if (model != SpvExecutionModelTessellationControl &&
-            model != SpvExecutionModelGLCompute) {
-          if (inst->opcode() == SpvOpControlBarrier) {
-            assert(model != SpvExecutionModelKernel &&
+        if (model != spv::ExecutionModel::TessellationControl &&
+            model != spv::ExecutionModel::GLCompute) {
+          if (inst->opcode() == spv::Op::OpControlBarrier) {
+            assert(model != spv::ExecutionModel::Kernel &&
                    "Expecting to be working on a shader module.");
             replace = true;
           }
@@ -101,7 +101,7 @@
           } else {
             // Get the name of the source file.
             uint32_t file_name_id = 0;
-            if (last_line_dbg_inst->opcode() == SpvOpLine) {
+            if (last_line_dbg_inst->opcode() == spv::Op::OpLine) {
               file_name_id = last_line_dbg_inst->GetSingleWordInOperand(0);
             } else {  // Shader100::DebugLine
               uint32_t debug_source_id =
@@ -131,26 +131,26 @@
 bool ReplaceInvalidOpcodePass::IsFragmentShaderOnlyInstruction(
     Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpDPdx:
-    case SpvOpDPdy:
-    case SpvOpFwidth:
-    case SpvOpDPdxFine:
-    case SpvOpDPdyFine:
-    case SpvOpFwidthFine:
-    case SpvOpDPdxCoarse:
-    case SpvOpDPdyCoarse:
-    case SpvOpFwidthCoarse:
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageQueryLod:
+    case spv::Op::OpDPdx:
+    case spv::Op::OpDPdy:
+    case spv::Op::OpFwidth:
+    case spv::Op::OpDPdxFine:
+    case spv::Op::OpDPdyFine:
+    case spv::Op::OpFwidthFine:
+    case spv::Op::OpDPdxCoarse:
+    case spv::Op::OpDPdyCoarse:
+    case spv::Op::OpFwidthCoarse:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageQueryLod:
       // TODO: Teach |ReplaceInstruction| to handle block terminators.  Then
       // uncomment the OpKill case.
-      // case SpvOpKill:
-      // case SpvOpTerminateInstruction:
+      // case spv::Op::OpKill:
+      // case spv::Op::OpTerminateInstruction:
       return true;
     default:
       return false;
@@ -183,7 +183,7 @@
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
 
   Instruction* type = context()->get_def_use_mgr()->GetDef(type_id);
-  if (type->opcode() == SpvOpTypeVector) {
+  if (type->opcode() == spv::Op::OpTypeVector) {
     uint32_t component_const =
         GetSpecialConstant(type->GetSingleWordInOperand(0));
     std::vector<uint32_t> ids;
@@ -192,7 +192,8 @@
     }
     special_const = const_mgr->GetConstant(type_mgr->GetType(type_id), ids);
   } else {
-    assert(type->opcode() == SpvOpTypeInt || type->opcode() == SpvOpTypeFloat);
+    assert(type->opcode() == spv::Op::OpTypeInt ||
+           type->opcode() == spv::Op::OpTypeFloat);
     std::vector<uint32_t> literal_words;
     for (uint32_t i = 0; i < type->GetSingleWordInOperand(0); i += 32) {
       literal_words.push_back(0xDEADBEEF);
@@ -204,7 +205,7 @@
   return const_mgr->GetDefiningInstruction(special_const)->result_id();
 }
 
-std::string ReplaceInvalidOpcodePass::BuildWarningMessage(SpvOp opcode) {
+std::string ReplaceInvalidOpcodePass::BuildWarningMessage(spv::Op opcode) {
   spv_opcode_desc opcode_info;
   context()->grammar().lookupOpcode(opcode, &opcode_info);
   std::string message = "Removing ";
diff --git a/third_party/SPIRV-Tools/source/opt/replace_invalid_opc.h b/third_party/SPIRV-Tools/source/opt/replace_invalid_opc.h
index 426bcac..3f0d16b 100644
--- a/third_party/SPIRV-Tools/source/opt/replace_invalid_opc.h
+++ b/third_party/SPIRV-Tools/source/opt/replace_invalid_opc.h
@@ -34,13 +34,13 @@
  private:
   // Returns the execution model that is used by every entry point in the
   // module. If more than one execution model is used in the module, then the
-  // return value is SpvExecutionModelMax.
-  SpvExecutionModel GetExecutionModel();
+  // return value is spv::ExecutionModel::Max.
+  spv::ExecutionModel GetExecutionModel();
 
   // Replaces all instructions in |function| that are invalid with execution
   // model |mode|, but valid for another shader model, with a special constant
   // value.  See |GetSpecialConstant|.
-  bool RewriteFunction(Function* function, SpvExecutionModel mode);
+  bool RewriteFunction(Function* function, spv::ExecutionModel mode);
 
   // Returns true if |inst| is valid for fragment shaders only.
   bool IsFragmentShaderOnlyInstruction(Instruction* inst);
@@ -58,7 +58,7 @@
   // width of the type has been reached. For a vector, each element of the
   // constant will be constructed the same way.
   uint32_t GetSpecialConstant(uint32_t type_id);
-  std::string BuildWarningMessage(SpvOp opcode);
+  std::string BuildWarningMessage(spv::Op opcode);
 };
 
 }  // namespace opt
diff --git a/third_party/SPIRV-Tools/source/opt/scalar_analysis.cpp b/third_party/SPIRV-Tools/source/opt/scalar_analysis.cpp
index 2b0a824..0c8babe 100644
--- a/third_party/SPIRV-Tools/source/opt/scalar_analysis.cpp
+++ b/third_party/SPIRV-Tools/source/opt/scalar_analysis.cpp
@@ -97,7 +97,7 @@
 
 SENode* ScalarEvolutionAnalysis::AnalyzeMultiplyOp(
     const Instruction* multiply) {
-  assert(multiply->opcode() == SpvOp::SpvOpIMul &&
+  assert(multiply->opcode() == spv::Op::OpIMul &&
          "Multiply node did not come from a multiply instruction");
   analysis::DefUseManager* def_use = context_->get_def_use_mgr();
 
@@ -168,21 +168,21 @@
 
   SENode* output = nullptr;
   switch (inst->opcode()) {
-    case SpvOp::SpvOpPhi: {
+    case spv::Op::OpPhi: {
       output = AnalyzePhiInstruction(inst);
       break;
     }
-    case SpvOp::SpvOpConstant:
-    case SpvOp::SpvOpConstantNull: {
+    case spv::Op::OpConstant:
+    case spv::Op::OpConstantNull: {
       output = AnalyzeConstant(inst);
       break;
     }
-    case SpvOp::SpvOpISub:
-    case SpvOp::SpvOpIAdd: {
+    case spv::Op::OpISub:
+    case spv::Op::OpIAdd: {
       output = AnalyzeAddOp(inst);
       break;
     }
-    case SpvOp::SpvOpIMul: {
+    case spv::Op::OpIMul: {
       output = AnalyzeMultiplyOp(inst);
       break;
     }
@@ -196,9 +196,9 @@
 }
 
 SENode* ScalarEvolutionAnalysis::AnalyzeConstant(const Instruction* inst) {
-  if (inst->opcode() == SpvOp::SpvOpConstantNull) return CreateConstant(0);
+  if (inst->opcode() == spv::Op::OpConstantNull) return CreateConstant(0);
 
-  assert(inst->opcode() == SpvOp::SpvOpConstant);
+  assert(inst->opcode() == spv::Op::OpConstant);
   assert(inst->NumInOperands() == 1);
   int64_t value = 0;
 
@@ -226,8 +226,8 @@
 // Handles both addition and subtraction. If the |sub| flag is set then the
 // addition will be op1+(-op2) otherwise op1+op2.
 SENode* ScalarEvolutionAnalysis::AnalyzeAddOp(const Instruction* inst) {
-  assert((inst->opcode() == SpvOp::SpvOpIAdd ||
-          inst->opcode() == SpvOp::SpvOpISub) &&
+  assert((inst->opcode() == spv::Op::OpIAdd ||
+          inst->opcode() == spv::Op::OpISub) &&
          "Add node must be created from a OpIAdd or OpISub instruction");
 
   analysis::DefUseManager* def_use = context_->get_def_use_mgr();
@@ -239,7 +239,7 @@
       AnalyzeInstruction(def_use->GetDef(inst->GetSingleWordInOperand(1)));
 
   // To handle subtraction we wrap the second operand in a unary negation node.
-  if (inst->opcode() == SpvOp::SpvOpISub) {
+  if (inst->opcode() == spv::Op::OpISub) {
     op2 = CreateNegation(op2);
   }
 
@@ -573,7 +573,7 @@
 };
 
 template <typename T>
-static void PushToString(T id, std::u32string* str) {
+void PushToString(T id, std::u32string* str) {
   PushToStringImpl<T, sizeof(T)>{}(id, str);
 }
 
@@ -928,8 +928,8 @@
 
 // Remove |node| from the |mul| chain (of the form A * ... * |node| * ... * Z),
 // if |node| is not in the chain, returns the original chain.
-static SENode* RemoveOneNodeFromMultiplyChain(SEMultiplyNode* mul,
-                                              const SENode* node) {
+SENode* RemoveOneNodeFromMultiplyChain(SEMultiplyNode* mul,
+                                       const SENode* node) {
   SENode* lhs = mul->GetChildren()[0];
   SENode* rhs = mul->GetChildren()[1];
   if (lhs == node) {
diff --git a/third_party/SPIRV-Tools/source/opt/scalar_replacement_pass.cpp b/third_party/SPIRV-Tools/source/opt/scalar_replacement_pass.cpp
index e27c828..6045158 100644
--- a/third_party/SPIRV-Tools/source/opt/scalar_replacement_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/scalar_replacement_pass.cpp
@@ -26,12 +26,13 @@
 #include "source/util/make_unique.h"
 #include "types.h"
 
-static const uint32_t kDebugValueOperandValueIndex = 5;
-static const uint32_t kDebugValueOperandExpressionIndex = 6;
-static const uint32_t kDebugDeclareOperandVariableIndex = 5;
-
 namespace spvtools {
 namespace opt {
+namespace {
+constexpr uint32_t kDebugValueOperandValueIndex = 5;
+constexpr uint32_t kDebugValueOperandExpressionIndex = 6;
+constexpr uint32_t kDebugDeclareOperandVariableIndex = 5;
+}  // namespace
 
 Pass::Status ScalarReplacementPass::Process() {
   Status status = Status::SuccessWithoutChange;
@@ -56,7 +57,7 @@
   for (auto iter = entry.begin(); iter != entry.end(); ++iter) {
     // Function storage class OpVariables must appear as the first instructions
     // of the entry block.
-    if (iter->opcode() != SpvOpVariable) break;
+    if (iter->opcode() != spv::Op::OpVariable) break;
 
     Instruction* varInst = &*iter;
     if (CanReplaceVariable(varInst)) {
@@ -105,29 +106,29 @@
         }
         if (!IsAnnotationInst(user->opcode())) {
           switch (user->opcode()) {
-            case SpvOpLoad:
+            case spv::Op::OpLoad:
               if (ReplaceWholeLoad(user, replacements)) {
                 dead.push_back(user);
               } else {
                 return false;
               }
               break;
-            case SpvOpStore:
+            case spv::Op::OpStore:
               if (ReplaceWholeStore(user, replacements)) {
                 dead.push_back(user);
               } else {
                 return false;
               }
               break;
-            case SpvOpAccessChain:
-            case SpvOpInBoundsAccessChain:
+            case spv::Op::OpAccessChain:
+            case spv::Op::OpInBoundsAccessChain:
               if (ReplaceAccessChain(user, replacements))
                 dead.push_back(user);
               else
                 return false;
               break;
-            case SpvOpName:
-            case SpvOpMemberName:
+            case spv::Op::OpName:
+            case spv::Op::OpMemberName:
               break;
             default:
               assert(false && "Unexpected opcode");
@@ -155,7 +156,7 @@
 
   // Attempt to further scalarize.
   for (auto var : replacements) {
-    if (var->opcode() == SpvOpVariable) {
+    if (var->opcode() == spv::Op::OpVariable) {
       if (get_def_use_mgr()->NumUsers(var) == 0) {
         context()->KillInst(var);
       } else if (CanReplaceVariable(var)) {
@@ -179,7 +180,7 @@
   int32_t idx = 0;
   for (const auto* var : replacements) {
     Instruction* insert_before = var->NextNode();
-    while (insert_before->opcode() == SpvOpVariable)
+    while (insert_before->opcode() == spv::Op::OpVariable)
       insert_before = insert_before->NextNode();
     assert(insert_before != nullptr && "unexpected end of list");
     Instruction* added_dbg_value =
@@ -236,7 +237,7 @@
   BasicBlock::iterator where(load);
   for (auto var : replacements) {
     // Create a load of each replacement variable.
-    if (var->opcode() != SpvOpVariable) {
+    if (var->opcode() != spv::Op::OpVariable) {
       loads.push_back(var);
       continue;
     }
@@ -247,7 +248,7 @@
       return false;
     }
     std::unique_ptr<Instruction> newLoad(
-        new Instruction(context(), SpvOpLoad, type->result_id(), loadId,
+        new Instruction(context(), spv::Op::OpLoad, type->result_id(), loadId,
                         std::initializer_list<Operand>{
                             {SPV_OPERAND_TYPE_ID, {var->result_id()}}}));
     // Copy memory access attributes which start at index 1. Index 0 is the
@@ -269,8 +270,9 @@
     return false;
   }
   where = load;
-  std::unique_ptr<Instruction> compositeConstruct(new Instruction(
-      context(), SpvOpCompositeConstruct, load->type_id(), compositeId, {}));
+  std::unique_ptr<Instruction> compositeConstruct(
+      new Instruction(context(), spv::Op::OpCompositeConstruct, load->type_id(),
+                      compositeId, {}));
   for (auto l : loads) {
     Operand op(SPV_OPERAND_TYPE_ID,
                std::initializer_list<uint32_t>{l->result_id()});
@@ -294,7 +296,7 @@
   uint32_t elementIndex = 0;
   for (auto var : replacements) {
     // Create the extract.
-    if (var->opcode() != SpvOpVariable) {
+    if (var->opcode() != spv::Op::OpVariable) {
       elementIndex++;
       continue;
     }
@@ -305,7 +307,7 @@
       return false;
     }
     std::unique_ptr<Instruction> extract(new Instruction(
-        context(), SpvOpCompositeExtract, type->result_id(), extractId,
+        context(), spv::Op::OpCompositeExtract, type->result_id(), extractId,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {storeInput}},
             {SPV_OPERAND_TYPE_LITERAL_INTEGER, {elementIndex++}}}));
@@ -316,7 +318,7 @@
 
     // Create the store.
     std::unique_ptr<Instruction> newStore(
-        new Instruction(context(), SpvOpStore, 0, 0,
+        new Instruction(context(), spv::Op::OpStore, 0, 0,
                         std::initializer_list<Operand>{
                             {SPV_OPERAND_TYPE_ID, {var->result_id()}},
                             {SPV_OPERAND_TYPE_ID, {extractId}}}));
@@ -390,7 +392,7 @@
 
   uint32_t elem = 0;
   switch (type->opcode()) {
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       type->ForEachInOperand(
           [this, inst, &elem, replacements, &components_used](uint32_t* id) {
             if (!components_used || components_used->count(elem)) {
@@ -401,7 +403,7 @@
             elem++;
           });
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       for (uint32_t i = 0; i != GetArrayLength(type); ++i) {
         if (!components_used || components_used->count(i)) {
           CreateVariable(type->GetSingleWordInOperand(0u), inst, i,
@@ -413,8 +415,8 @@
       }
       break;
 
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       for (uint32_t i = 0; i != GetNumElements(type); ++i) {
         CreateVariable(type->GetSingleWordInOperand(0u), inst, i, replacements);
       }
@@ -440,20 +442,20 @@
   // no type or member decorations that are necessary to transfer.
   for (auto inst :
        get_decoration_mgr()->GetDecorationsFor(source->result_id(), false)) {
-    assert(inst->opcode() == SpvOpDecorate);
-    uint32_t decoration = inst->GetSingleWordInOperand(1u);
-    if (decoration == SpvDecorationInvariant ||
-        decoration == SpvDecorationRestrict) {
+    assert(inst->opcode() == spv::Op::OpDecorate);
+    auto decoration = spv::Decoration(inst->GetSingleWordInOperand(1u));
+    if (decoration == spv::Decoration::Invariant ||
+        decoration == spv::Decoration::Restrict) {
       for (auto var : *replacements) {
         if (var == nullptr) {
           continue;
         }
 
-        std::unique_ptr<Instruction> annotation(
-            new Instruction(context(), SpvOpDecorate, 0, 0,
-                            std::initializer_list<Operand>{
-                                {SPV_OPERAND_TYPE_ID, {var->result_id()}},
-                                {SPV_OPERAND_TYPE_DECORATION, {decoration}}}));
+        std::unique_ptr<Instruction> annotation(new Instruction(
+            context(), spv::Op::OpDecorate, 0, 0,
+            std::initializer_list<Operand>{
+                {SPV_OPERAND_TYPE_ID, {var->result_id()}},
+                {SPV_OPERAND_TYPE_DECORATION, {uint32_t(decoration)}}}));
         for (uint32_t i = 2; i < inst->NumInOperands(); ++i) {
           Operand copy(inst->GetInOperand(i));
           annotation->AddOperand(std::move(copy));
@@ -475,10 +477,11 @@
     replacements->push_back(nullptr);
   }
 
-  std::unique_ptr<Instruction> variable(new Instruction(
-      context(), SpvOpVariable, ptrId, id,
-      std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
+  std::unique_ptr<Instruction> variable(
+      new Instruction(context(), spv::Op::OpVariable, ptrId, id,
+                      std::initializer_list<Operand>{
+                          {SPV_OPERAND_TYPE_STORAGE_CLASS,
+                           {uint32_t(spv::StorageClass::Function)}}}));
 
   BasicBlock* block = context()->get_instr_block(varInst);
   block->begin().InsertBefore(std::move(variable));
@@ -494,7 +497,7 @@
   for (auto dec_inst :
        get_decoration_mgr()->GetDecorationsFor(typeInst->result_id(), false)) {
     uint32_t decoration;
-    if (dec_inst->opcode() != SpvOpMemberDecorate) {
+    if (dec_inst->opcode() != spv::Op::OpMemberDecorate) {
       continue;
     }
 
@@ -503,10 +506,10 @@
     }
 
     decoration = dec_inst->GetSingleWordInOperand(2u);
-    switch (decoration) {
-      case SpvDecorationRelaxedPrecision: {
+    switch (spv::Decoration(decoration)) {
+      case spv::Decoration::RelaxedPrecision: {
         std::unique_ptr<Instruction> new_dec_inst(
-            new Instruction(context(), SpvOpDecorate, 0, 0, {}));
+            new Instruction(context(), spv::Op::OpDecorate, 0, 0, {}));
         new_dec_inst->AddOperand(Operand(SPV_OPERAND_TYPE_ID, {id}));
         for (uint32_t i = 2; i < dec_inst->NumInOperandWords(); ++i) {
           new_dec_inst->AddOperand(Operand(dec_inst->GetInOperand(i)));
@@ -531,8 +534,8 @@
   analysis::Type* pointeeTy;
   std::unique_ptr<analysis::Pointer> pointerTy;
   std::tie(pointeeTy, pointerTy) =
-      context()->get_type_mgr()->GetTypeAndPointerType(id,
-                                                       SpvStorageClassFunction);
+      context()->get_type_mgr()->GetTypeAndPointerType(
+          id, spv::StorageClass::Function);
   uint32_t ptrId = 0;
   if (pointeeTy->IsUniqueType()) {
     // Non-ambiguous type, just ask the type manager for an id.
@@ -544,8 +547,9 @@
   // Ambiguous type. We must perform a linear search to try and find the right
   // type.
   for (auto global : context()->types_values()) {
-    if (global.opcode() == SpvOpTypePointer &&
-        global.GetSingleWordInOperand(0u) == SpvStorageClassFunction &&
+    if (global.opcode() == spv::Op::OpTypePointer &&
+        spv::StorageClass(global.GetSingleWordInOperand(0u)) ==
+            spv::StorageClass::Function &&
         global.GetSingleWordInOperand(1u) == id) {
       if (get_decoration_mgr()->GetDecorationsFor(id, false).empty()) {
         // Only reuse a decoration-less pointer of the correct type.
@@ -562,10 +566,10 @@
 
   ptrId = TakeNextId();
   context()->AddType(MakeUnique<Instruction>(
-      context(), SpvOpTypePointer, 0, ptrId,
-      std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
-          {SPV_OPERAND_TYPE_ID, {id}}}));
+      context(), spv::Op::OpTypePointer, 0, ptrId,
+      std::initializer_list<Operand>{{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                      {uint32_t(spv::StorageClass::Function)}},
+                                     {SPV_OPERAND_TYPE_ID, {id}}}));
   Instruction* ptr = &*--context()->types_values_end();
   get_def_use_mgr()->AnalyzeInstDefUse(ptr);
   pointee_to_pointer_[id] = ptrId;
@@ -578,7 +582,7 @@
 void ScalarReplacementPass::GetOrCreateInitialValue(Instruction* source,
                                                     uint32_t index,
                                                     Instruction* newVar) {
-  assert(source->opcode() == SpvOpVariable);
+  assert(source->opcode() == spv::Op::OpVariable);
   if (source->NumInOperands() < 2) return;
 
   uint32_t initId = source->GetSingleWordInOperand(1u);
@@ -586,14 +590,14 @@
   Instruction* init = get_def_use_mgr()->GetDef(initId);
   uint32_t newInitId = 0;
   // TODO(dnovillo): Refactor this with constant propagation.
-  if (init->opcode() == SpvOpConstantNull) {
+  if (init->opcode() == spv::Op::OpConstantNull) {
     // Initialize to appropriate NULL.
     auto iter = type_to_null_.find(storageId);
     if (iter == type_to_null_.end()) {
       newInitId = TakeNextId();
       type_to_null_[storageId] = newInitId;
       context()->AddGlobalValue(
-          MakeUnique<Instruction>(context(), SpvOpConstantNull, storageId,
+          MakeUnique<Instruction>(context(), spv::Op::OpConstantNull, storageId,
                                   newInitId, std::initializer_list<Operand>{}));
       Instruction* newNull = &*--context()->types_values_end();
       get_def_use_mgr()->AnalyzeInstDefUse(newNull);
@@ -604,18 +608,19 @@
     // Create a new constant extract.
     newInitId = TakeNextId();
     context()->AddGlobalValue(MakeUnique<Instruction>(
-        context(), SpvOpSpecConstantOp, storageId, newInitId,
+        context(), spv::Op::OpSpecConstantOp, storageId, newInitId,
         std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER, {SpvOpCompositeExtract}},
+            {SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER,
+             {uint32_t(spv::Op::OpCompositeExtract)}},
             {SPV_OPERAND_TYPE_ID, {init->result_id()}},
             {SPV_OPERAND_TYPE_LITERAL_INTEGER, {index}}}));
     Instruction* newSpecConst = &*--context()->types_values_end();
     get_def_use_mgr()->AnalyzeInstDefUse(newSpecConst);
-  } else if (init->opcode() == SpvOpConstantComposite) {
+  } else if (init->opcode() == spv::Op::OpConstantComposite) {
     // Get the appropriate index constant.
     newInitId = init->GetSingleWordInOperand(index);
     Instruction* element = get_def_use_mgr()->GetDef(newInitId);
-    if (element->opcode() == SpvOpUndef) {
+    if (element->opcode() == spv::Op::OpUndef) {
       // Undef is not a valid initializer for a variable.
       newInitId = 0;
     }
@@ -630,7 +635,7 @@
 
 uint64_t ScalarReplacementPass::GetArrayLength(
     const Instruction* arrayType) const {
-  assert(arrayType->opcode() == SpvOpTypeArray);
+  assert(arrayType->opcode() == spv::Op::OpTypeArray);
   const Instruction* length =
       get_def_use_mgr()->GetDef(arrayType->GetSingleWordInOperand(1u));
   return context()
@@ -640,8 +645,8 @@
 }
 
 uint64_t ScalarReplacementPass::GetNumElements(const Instruction* type) const {
-  assert(type->opcode() == SpvOpTypeVector ||
-         type->opcode() == SpvOpTypeMatrix);
+  assert(type->opcode() == spv::Op::OpTypeVector ||
+         type->opcode() == spv::Op::OpTypeMatrix);
   const Operand& op = type->GetInOperand(1u);
   assert(op.words.size() <= 2);
   uint64_t len = 0;
@@ -659,7 +664,7 @@
 
 Instruction* ScalarReplacementPass::GetStorageType(
     const Instruction* inst) const {
-  assert(inst->opcode() == SpvOpVariable);
+  assert(inst->opcode() == spv::Op::OpVariable);
 
   uint32_t ptrTypeId = inst->type_id();
   uint32_t typeId =
@@ -669,10 +674,11 @@
 
 bool ScalarReplacementPass::CanReplaceVariable(
     const Instruction* varInst) const {
-  assert(varInst->opcode() == SpvOpVariable);
+  assert(varInst->opcode() == spv::Op::OpVariable);
 
   // Can only replace function scope variables.
-  if (varInst->GetSingleWordInOperand(0u) != SpvStorageClassFunction) {
+  if (spv::StorageClass(varInst->GetSingleWordInOperand(0u)) !=
+      spv::StorageClass::Function) {
     return false;
   }
 
@@ -702,14 +708,14 @@
   }
 
   switch (typeInst->opcode()) {
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       // Don't bother with empty structs or very large structs.
       if (typeInst->NumInOperands() == 0 ||
           IsLargerThanSizeLimit(typeInst->NumInOperands())) {
         return false;
       }
       return true;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       if (IsSpecConstant(typeInst->GetSingleWordInOperand(1u))) {
         return false;
       }
@@ -721,12 +727,12 @@
       // re-enabled.
       //// Specifically including matrix and vector in an attempt to reduce the
       //// number of vector registers required.
-      // case SpvOpTypeMatrix:
-      // case SpvOpTypeVector:
+      // case spv::Op::OpTypeMatrix:
+      // case spv::Op::OpTypeVector:
       //  if (IsLargerThanSizeLimit(GetNumElements(typeInst))) return false;
       //  return true;
 
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
     default:
       return false;
   }
@@ -737,26 +743,26 @@
   for (auto inst :
        get_decoration_mgr()->GetDecorationsFor(typeInst->result_id(), false)) {
     uint32_t decoration;
-    if (inst->opcode() == SpvOpDecorate) {
+    if (inst->opcode() == spv::Op::OpDecorate) {
       decoration = inst->GetSingleWordInOperand(1u);
     } else {
-      assert(inst->opcode() == SpvOpMemberDecorate);
+      assert(inst->opcode() == spv::Op::OpMemberDecorate);
       decoration = inst->GetSingleWordInOperand(2u);
     }
 
-    switch (decoration) {
-      case SpvDecorationRowMajor:
-      case SpvDecorationColMajor:
-      case SpvDecorationArrayStride:
-      case SpvDecorationMatrixStride:
-      case SpvDecorationCPacked:
-      case SpvDecorationInvariant:
-      case SpvDecorationRestrict:
-      case SpvDecorationOffset:
-      case SpvDecorationAlignment:
-      case SpvDecorationAlignmentId:
-      case SpvDecorationMaxByteOffset:
-      case SpvDecorationRelaxedPrecision:
+    switch (spv::Decoration(decoration)) {
+      case spv::Decoration::RowMajor:
+      case spv::Decoration::ColMajor:
+      case spv::Decoration::ArrayStride:
+      case spv::Decoration::MatrixStride:
+      case spv::Decoration::CPacked:
+      case spv::Decoration::Invariant:
+      case spv::Decoration::Restrict:
+      case spv::Decoration::Offset:
+      case spv::Decoration::Alignment:
+      case spv::Decoration::AlignmentId:
+      case spv::Decoration::MaxByteOffset:
+      case spv::Decoration::RelaxedPrecision:
         break;
       default:
         return false;
@@ -769,14 +775,14 @@
 bool ScalarReplacementPass::CheckAnnotations(const Instruction* varInst) const {
   for (auto inst :
        get_decoration_mgr()->GetDecorationsFor(varInst->result_id(), false)) {
-    assert(inst->opcode() == SpvOpDecorate);
-    uint32_t decoration = inst->GetSingleWordInOperand(1u);
+    assert(inst->opcode() == spv::Op::OpDecorate);
+    auto decoration = spv::Decoration(inst->GetSingleWordInOperand(1u));
     switch (decoration) {
-      case SpvDecorationInvariant:
-      case SpvDecorationRestrict:
-      case SpvDecorationAlignment:
-      case SpvDecorationAlignmentId:
-      case SpvDecorationMaxByteOffset:
+      case spv::Decoration::Invariant:
+      case spv::Decoration::Restrict:
+      case spv::Decoration::Alignment:
+      case spv::Decoration::AlignmentId:
+      case spv::Decoration::MaxByteOffset:
         break;
       default:
         return false;
@@ -816,8 +822,8 @@
     // Annotations are check as a group separately.
     if (!IsAnnotationInst(user->opcode())) {
       switch (user->opcode()) {
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain:
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain:
           if (index == 2u && user->NumInOperands() > 1) {
             uint32_t id = user->GetSingleWordInOperand(1u);
             const Instruction* opInst = get_def_use_mgr()->GetDef(id);
@@ -835,16 +841,16 @@
             ok = false;
           }
           break;
-        case SpvOpLoad:
+        case spv::Op::OpLoad:
           if (!CheckLoad(user, index)) ok = false;
           stats->num_full_accesses++;
           break;
-        case SpvOpStore:
+        case spv::Op::OpStore:
           if (!CheckStore(user, index)) ok = false;
           stats->num_full_accesses++;
           break;
-        case SpvOpName:
-        case SpvOpMemberName:
+        case spv::Op::OpName:
+        case spv::Op::OpMemberName:
           break;
         default:
           ok = false;
@@ -861,24 +867,24 @@
   get_def_use_mgr()->ForEachUse(
       inst, [this, &ok](const Instruction* user, uint32_t index) {
         switch (user->opcode()) {
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain:
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain:
             if (index != 2u) {
               ok = false;
             } else {
               if (!CheckUsesRelaxed(user)) ok = false;
             }
             break;
-          case SpvOpLoad:
+          case spv::Op::OpLoad:
             if (!CheckLoad(user, index)) ok = false;
             break;
-          case SpvOpStore:
+          case spv::Op::OpStore:
             if (!CheckStore(user, index)) ok = false;
             break;
-          case SpvOpImageTexelPointer:
+          case spv::Op::OpImageTexelPointer:
             if (!CheckImageTexelPointer(index)) ok = false;
             break;
-          case SpvOpExtInst:
+          case spv::Op::OpExtInst:
             if (user->GetCommonDebugOpcode() != CommonDebugInfoDebugDeclare ||
                 !CheckDebugDeclare(index))
               ok = false;
@@ -900,7 +906,8 @@
                                       uint32_t index) const {
   if (index != 2u) return false;
   if (inst->NumInOperands() >= 2 &&
-      inst->GetSingleWordInOperand(1u) & SpvMemoryAccessVolatileMask)
+      inst->GetSingleWordInOperand(1u) &
+          uint32_t(spv::MemoryAccessMask::Volatile))
     return false;
   return true;
 }
@@ -909,7 +916,8 @@
                                        uint32_t index) const {
   if (index != 0u) return false;
   if (inst->NumInOperands() >= 3 &&
-      inst->GetSingleWordInOperand(2u) & SpvMemoryAccessVolatileMask)
+      inst->GetSingleWordInOperand(2u) &
+          uint32_t(spv::MemoryAccessMask::Volatile))
     return false;
   return true;
 }
@@ -936,11 +944,11 @@
   def_use_mgr->WhileEachUser(inst, [&result, def_use_mgr,
                                     this](Instruction* use) {
     switch (use->opcode()) {
-      case SpvOpLoad: {
+      case spv::Op::OpLoad: {
         // Look for extract from the load.
         std::vector<uint32_t> t;
         if (def_use_mgr->WhileEachUser(use, [&t](Instruction* use2) {
-              if (use2->opcode() != SpvOpCompositeExtract ||
+              if (use2->opcode() != spv::Op::OpCompositeExtract ||
                   use2->NumInOperands() <= 1) {
                 return false;
               }
@@ -954,13 +962,13 @@
           return false;
         }
       }
-      case SpvOpName:
-      case SpvOpMemberName:
-      case SpvOpStore:
+      case spv::Op::OpName:
+      case spv::Op::OpMemberName:
+      case spv::Op::OpStore:
         // No components are used.
         return true;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain: {
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain: {
         // Add the first index it if is a constant.
         // TODO: Could be improved by checking if the address is used in a load.
         analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
@@ -988,16 +996,16 @@
 
 uint64_t ScalarReplacementPass::GetMaxLegalIndex(
     const Instruction* var_inst) const {
-  assert(var_inst->opcode() == SpvOpVariable &&
+  assert(var_inst->opcode() == spv::Op::OpVariable &&
          "|var_inst| must be a variable instruction.");
   Instruction* type = GetStorageType(var_inst);
   switch (type->opcode()) {
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       return type->NumInOperands();
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       return GetArrayLength(type);
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       return GetNumElements(type);
     default:
       return 0;
diff --git a/third_party/SPIRV-Tools/source/opt/scalar_replacement_pass.h b/third_party/SPIRV-Tools/source/opt/scalar_replacement_pass.h
index 6a66dfb..0bcd2a4 100644
--- a/third_party/SPIRV-Tools/source/opt/scalar_replacement_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/scalar_replacement_pass.h
@@ -33,7 +33,7 @@
 // Documented in optimizer.hpp
 class ScalarReplacementPass : public MemPass {
  private:
-  static const uint32_t kDefaultLimit = 100;
+  static constexpr uint32_t kDefaultLimit = 100;
 
  public:
   ScalarReplacementPass(uint32_t limit = kDefaultLimit)
@@ -104,10 +104,10 @@
   // Returns true if the uses of |inst| are acceptable for scalarization.
   //
   // Recursively checks all the uses of |inst|. For |inst| specifically, only
-  // allows SpvOpAccessChain, SpvOpInBoundsAccessChain, SpvOpLoad and
-  // SpvOpStore. Access chains must have the first index be a compile-time
-  // constant. Subsequent uses of access chains (including other access chains)
-  // are checked in a more relaxed manner.
+  // allows spv::Op::OpAccessChain, spv::Op::OpInBoundsAccessChain,
+  // spv::Op::OpLoad and spv::Op::OpStore. Access chains must have the first
+  // index be a compile-time constant. Subsequent uses of access chains
+  // (including other access chains) are checked in a more relaxed manner.
   bool CheckUses(const Instruction* inst) const;
 
   // Helper function for the above |CheckUses|.
diff --git a/third_party/SPIRV-Tools/source/opt/set_spec_constant_default_value_pass.cpp b/third_party/SPIRV-Tools/source/opt/set_spec_constant_default_value_pass.cpp
index 4def2b0..5125bd1 100644
--- a/third_party/SPIRV-Tools/source/opt/set_spec_constant_default_value_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/set_spec_constant_default_value_pass.cpp
@@ -30,7 +30,6 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
 using utils::EncodeNumberStatus;
 using utils::NumberType;
@@ -139,9 +138,9 @@
 // decoration.
 bool CanHaveSpecIdDecoration(const Instruction& inst) {
   switch (inst.opcode()) {
-    case SpvOp::SpvOpSpecConstant:
-    case SpvOp::SpvOpSpecConstantFalse:
-    case SpvOp::SpvOpSpecConstantTrue:
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpSpecConstantTrue:
       return true;
     default:
       return false;
@@ -165,7 +164,7 @@
   if (def_use_mgr->WhileEachUser(&decoration_group_defining_inst,
                                  [&group_decorate_inst](Instruction* user) {
                                    if (user->opcode() ==
-                                       SpvOp::SpvOpGroupDecorate) {
+                                       spv::Op::OpGroupDecorate) {
                                      group_decorate_inst = user;
                                      return false;
                                    }
@@ -217,16 +216,16 @@
 
 Pass::Status SetSpecConstantDefaultValuePass::Process() {
   // The operand index of decoration target in an OpDecorate instruction.
-  const uint32_t kTargetIdOperandIndex = 0;
+  constexpr uint32_t kTargetIdOperandIndex = 0;
   // The operand index of the decoration literal in an OpDecorate instruction.
-  const uint32_t kDecorationOperandIndex = 1;
+  constexpr uint32_t kDecorationOperandIndex = 1;
   // The operand index of Spec id literal value in an OpDecorate SpecId
   // instruction.
-  const uint32_t kSpecIdLiteralOperandIndex = 2;
+  constexpr uint32_t kSpecIdLiteralOperandIndex = 2;
   // The number of operands in an OpDecorate SpecId instruction.
-  const uint32_t kOpDecorateSpecIdNumOperands = 3;
+  constexpr uint32_t kOpDecorateSpecIdNumOperands = 3;
   // The in-operand index of the default value in a OpSpecConstant instruction.
-  const uint32_t kOpSpecConstantLiteralInOperandIndex = 0;
+  constexpr uint32_t kOpSpecConstantLiteralInOperandIndex = 0;
 
   bool modified = false;
   // Scan through all the annotation instructions to find 'OpDecorate SpecId'
@@ -240,10 +239,10 @@
   // default value of the target spec constant.
   for (Instruction& inst : context()->annotations()) {
     // Only process 'OpDecorate SpecId' instructions
-    if (inst.opcode() != SpvOp::SpvOpDecorate) continue;
+    if (inst.opcode() != spv::Op::OpDecorate) continue;
     if (inst.NumOperands() != kOpDecorateSpecIdNumOperands) continue;
     if (inst.GetSingleWordInOperand(kDecorationOperandIndex) !=
-        uint32_t(SpvDecoration::SpvDecorationSpecId)) {
+        uint32_t(spv::Decoration::SpecId)) {
       continue;
     }
 
@@ -255,7 +254,7 @@
     // target_id might be a decoration group id.
     Instruction* spec_inst = nullptr;
     if (Instruction* target_inst = get_def_use_mgr()->GetDef(target_id)) {
-      if (target_inst->opcode() == SpvOp::SpvOpDecorationGroup) {
+      if (target_inst->opcode() == spv::Op::OpDecorationGroup) {
         spec_inst =
             GetSpecIdTargetFromDecorationGroup(*target_inst, get_def_use_mgr());
       } else {
@@ -301,7 +300,7 @@
     // Update the operand bit patterns of the spec constant defining
     // instruction.
     switch (spec_inst->opcode()) {
-      case SpvOp::SpvOpSpecConstant:
+      case spv::Op::OpSpecConstant:
         // If the new value is the same with the original value, no
         // need to do anything. Otherwise update the operand words.
         if (spec_inst->GetInOperand(kOpSpecConstantLiteralInOperandIndex)
@@ -311,19 +310,19 @@
           modified = true;
         }
         break;
-      case SpvOp::SpvOpSpecConstantTrue:
+      case spv::Op::OpSpecConstantTrue:
         // If the new value is also 'true', no need to change anything.
         // Otherwise, set the opcode to OpSpecConstantFalse;
         if (!static_cast<bool>(bit_pattern.front())) {
-          spec_inst->SetOpcode(SpvOp::SpvOpSpecConstantFalse);
+          spec_inst->SetOpcode(spv::Op::OpSpecConstantFalse);
           modified = true;
         }
         break;
-      case SpvOp::SpvOpSpecConstantFalse:
+      case spv::Op::OpSpecConstantFalse:
         // If the new value is also 'false', no need to change anything.
         // Otherwise, set the opcode to OpSpecConstantTrue;
         if (static_cast<bool>(bit_pattern.front())) {
-          spec_inst->SetOpcode(SpvOp::SpvOpSpecConstantTrue);
+          spec_inst->SetOpcode(spv::Op::OpSpecConstantTrue);
           modified = true;
         }
         break;
diff --git a/third_party/SPIRV-Tools/source/opt/simplification_pass.cpp b/third_party/SPIRV-Tools/source/opt/simplification_pass.cpp
index 43ec15f..dbda397 100644
--- a/third_party/SPIRV-Tools/source/opt/simplification_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/simplification_pass.cpp
@@ -69,12 +69,12 @@
        &folder, &inst_seen, this](BasicBlock* bb) {
         for (Instruction* inst = &*bb->begin(); inst; inst = inst->NextNode()) {
           inst_seen.insert(inst);
-          if (inst->opcode() == SpvOpPhi) {
+          if (inst->opcode() == spv::Op::OpPhi) {
             process_phis.insert(inst);
           }
 
           bool is_foldable_copy =
-              inst->opcode() == SpvOpCopyObject &&
+              inst->opcode() == spv::Op::OpCopyObject &&
               context()->get_decoration_mgr()->HaveSubsetOfDecorations(
                   inst->result_id(), inst->GetSingleWordInOperand(0));
 
@@ -91,7 +91,7 @@
 
             AddNewOperands(inst, &inst_seen, &work_list);
 
-            if (inst->opcode() == SpvOpCopyObject) {
+            if (inst->opcode() == spv::Op::OpCopyObject) {
               context()->ReplaceAllUsesWithPredicate(
                   inst->result_id(), inst->GetSingleWordInOperand(0),
                   [](Instruction* user) {
@@ -104,7 +104,7 @@
                   });
               inst_to_kill.insert(inst);
               in_work_list.insert(inst);
-            } else if (inst->opcode() == SpvOpNop) {
+            } else if (inst->opcode() == spv::Op::OpNop) {
               inst_to_kill.insert(inst);
               in_work_list.insert(inst);
             }
@@ -121,7 +121,7 @@
     inst_seen.insert(inst);
 
     bool is_foldable_copy =
-        inst->opcode() == SpvOpCopyObject &&
+        inst->opcode() == spv::Op::OpCopyObject &&
         context()->get_decoration_mgr()->HaveSubsetOfDecorations(
             inst->result_id(), inst->GetSingleWordInOperand(0));
 
@@ -130,7 +130,7 @@
       context()->AnalyzeUses(inst);
       get_def_use_mgr()->ForEachUser(
           inst, [&work_list, &in_work_list](Instruction* use) {
-            if (!use->IsDecoration() && use->opcode() != SpvOpName &&
+            if (!use->IsDecoration() && use->opcode() != spv::Op::OpName &&
                 in_work_list.insert(use).second) {
               work_list.push_back(use);
             }
@@ -138,7 +138,7 @@
 
       AddNewOperands(inst, &inst_seen, &work_list);
 
-      if (inst->opcode() == SpvOpCopyObject) {
+      if (inst->opcode() == spv::Op::OpCopyObject) {
         context()->ReplaceAllUsesWithPredicate(
             inst->result_id(), inst->GetSingleWordInOperand(0),
             [](Instruction* user) {
@@ -150,7 +150,7 @@
             });
         inst_to_kill.insert(inst);
         in_work_list.insert(inst);
-      } else if (inst->opcode() == SpvOpNop) {
+      } else if (inst->opcode() == spv::Op::OpNop) {
         inst_to_kill.insert(inst);
         in_work_list.insert(inst);
       }
diff --git a/third_party/SPIRV-Tools/source/opt/spread_volatile_semantics.cpp b/third_party/SPIRV-Tools/source/opt/spread_volatile_semantics.cpp
index b61fd0f..3037274 100644
--- a/third_party/SPIRV-Tools/source/opt/spread_volatile_semantics.cpp
+++ b/third_party/SPIRV-Tools/source/opt/spread_volatile_semantics.cpp
@@ -21,32 +21,32 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-const uint32_t kOpDecorateInOperandBuiltinDecoration = 2u;
-const uint32_t kOpLoadInOperandMemoryOperands = 1u;
-const uint32_t kOpEntryPointInOperandEntryPoint = 1u;
-const uint32_t kOpEntryPointInOperandInterface = 3u;
+constexpr uint32_t kOpDecorateInOperandBuiltinDecoration = 2u;
+constexpr uint32_t kOpLoadInOperandMemoryOperands = 1u;
+constexpr uint32_t kOpEntryPointInOperandEntryPoint = 1u;
+constexpr uint32_t kOpEntryPointInOperandInterface = 3u;
 
 bool HasBuiltinDecoration(analysis::DecorationManager* decoration_manager,
                           uint32_t var_id, uint32_t built_in) {
   return decoration_manager->FindDecoration(
-      var_id, SpvDecorationBuiltIn, [built_in](const Instruction& inst) {
+      var_id, uint32_t(spv::Decoration::BuiltIn),
+      [built_in](const Instruction& inst) {
         return built_in == inst.GetSingleWordInOperand(
                                kOpDecorateInOperandBuiltinDecoration);
       });
 }
 
-bool IsBuiltInForRayTracingVolatileSemantics(uint32_t built_in) {
+bool IsBuiltInForRayTracingVolatileSemantics(spv::BuiltIn built_in) {
   switch (built_in) {
-    case SpvBuiltInSMIDNV:
-    case SpvBuiltInWarpIDNV:
-    case SpvBuiltInSubgroupSize:
-    case SpvBuiltInSubgroupLocalInvocationId:
-    case SpvBuiltInSubgroupEqMask:
-    case SpvBuiltInSubgroupGeMask:
-    case SpvBuiltInSubgroupGtMask:
-    case SpvBuiltInSubgroupLeMask:
-    case SpvBuiltInSubgroupLtMask:
+    case spv::BuiltIn::SMIDNV:
+    case spv::BuiltIn::WarpIDNV:
+    case spv::BuiltIn::SubgroupSize:
+    case spv::BuiltIn::SubgroupLocalInvocationId:
+    case spv::BuiltIn::SubgroupEqMask:
+    case spv::BuiltIn::SubgroupGeMask:
+    case spv::BuiltIn::SubgroupGtMask:
+    case spv::BuiltIn::SubgroupLeMask:
+    case spv::BuiltIn::SubgroupLtMask:
       return true;
     default:
       return false;
@@ -56,16 +56,17 @@
 bool HasBuiltinForRayTracingVolatileSemantics(
     analysis::DecorationManager* decoration_manager, uint32_t var_id) {
   return decoration_manager->FindDecoration(
-      var_id, SpvDecorationBuiltIn, [](const Instruction& inst) {
-        uint32_t built_in =
-            inst.GetSingleWordInOperand(kOpDecorateInOperandBuiltinDecoration);
+      var_id, uint32_t(spv::Decoration::BuiltIn), [](const Instruction& inst) {
+        spv::BuiltIn built_in = spv::BuiltIn(
+            inst.GetSingleWordInOperand(kOpDecorateInOperandBuiltinDecoration));
         return IsBuiltInForRayTracingVolatileSemantics(built_in);
       });
 }
 
 bool HasVolatileDecoration(analysis::DecorationManager* decoration_manager,
                            uint32_t var_id) {
-  return decoration_manager->HasDecoration(var_id, SpvDecorationVolatile);
+  return decoration_manager->HasDecoration(var_id,
+                                           uint32_t(spv::Decoration::Volatile));
 }
 
 }  // namespace
@@ -76,7 +77,7 @@
   }
   const bool is_vk_memory_model_enabled =
       context()->get_feature_mgr()->HasCapability(
-          SpvCapabilityVulkanMemoryModel);
+          spv::Capability::VulkanMemoryModel);
   CollectTargetsForVolatileSemantics(is_vk_memory_model_enabled);
 
   // If VulkanMemoryModel capability is not enabled, we have to set Volatile
@@ -128,15 +129,16 @@
         }
         uint32_t memory_operands =
             load->GetSingleWordInOperand(kOpLoadInOperandMemoryOperands);
-        return (memory_operands & SpvMemoryAccessVolatileMask) != 0;
+        return (memory_operands & uint32_t(spv::MemoryAccessMask::Volatile)) !=
+               0;
       },
       funcs);
 }
 
 bool SpreadVolatileSemantics::HasInterfaceInConflictOfVolatileSemantics() {
   for (Instruction& entry_point : get_module()->entry_points()) {
-    SpvExecutionModel execution_model =
-        static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
+    spv::ExecutionModel execution_model =
+        static_cast<spv::ExecutionModel>(entry_point.GetSingleWordInOperand(0));
     for (uint32_t operand_index = kOpEntryPointInOperandInterface;
          operand_index < entry_point.NumInOperands(); ++operand_index) {
       uint32_t var_id = entry_point.GetSingleWordInOperand(operand_index);
@@ -170,8 +172,8 @@
 void SpreadVolatileSemantics::CollectTargetsForVolatileSemantics(
     const bool is_vk_memory_model_enabled) {
   for (Instruction& entry_point : get_module()->entry_points()) {
-    SpvExecutionModel execution_model =
-        static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
+    spv::ExecutionModel execution_model =
+        static_cast<spv::ExecutionModel>(entry_point.GetSingleWordInOperand(0));
     for (uint32_t operand_index = kOpEntryPointInOperandInterface;
          operand_index < entry_point.NumInOperands(); ++operand_index) {
       uint32_t var_id = entry_point.GetSingleWordInOperand(operand_index);
@@ -194,9 +196,10 @@
     return;
   }
   get_decoration_mgr()->AddDecoration(
-      SpvOpDecorate, {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {var_id}},
-                      {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                       {SpvDecorationVolatile}}});
+      spv::Op::OpDecorate,
+      {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {var_id}},
+       {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
+        {uint32_t(spv::Decoration::Volatile)}}});
 }
 
 bool SpreadVolatileSemantics::VisitLoadsOfPointersToVariableInEntries(
@@ -217,17 +220,17 @@
             return true;
           }
 
-          if (user->opcode() == SpvOpAccessChain ||
-              user->opcode() == SpvOpInBoundsAccessChain ||
-              user->opcode() == SpvOpPtrAccessChain ||
-              user->opcode() == SpvOpInBoundsPtrAccessChain ||
-              user->opcode() == SpvOpCopyObject) {
+          if (user->opcode() == spv::Op::OpAccessChain ||
+              user->opcode() == spv::Op::OpInBoundsAccessChain ||
+              user->opcode() == spv::Op::OpPtrAccessChain ||
+              user->opcode() == spv::Op::OpInBoundsPtrAccessChain ||
+              user->opcode() == spv::Op::OpCopyObject) {
             if (ptr_id == user->GetSingleWordInOperand(0))
               worklist.push_back(user->result_id());
             return true;
           }
 
-          if (user->opcode() != SpvOpLoad) {
+          if (user->opcode() != spv::Op::OpLoad) {
             return true;
           }
 
@@ -250,12 +253,12 @@
         [](Instruction* load) {
           if (load->NumInOperands() <= kOpLoadInOperandMemoryOperands) {
             load->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS,
-                              {SpvMemoryAccessVolatileMask}});
+                              {uint32_t(spv::MemoryAccessMask::Volatile)}});
             return true;
           }
           uint32_t memory_operands =
               load->GetSingleWordInOperand(kOpLoadInOperandMemoryOperands);
-          memory_operands |= SpvMemoryAccessVolatileMask;
+          memory_operands |= uint32_t(spv::MemoryAccessMask::Volatile);
           load->SetInOperand(kOpLoadInOperandMemoryOperands, {memory_operands});
           return true;
         },
@@ -264,29 +267,29 @@
 }
 
 bool SpreadVolatileSemantics::IsTargetForVolatileSemantics(
-    uint32_t var_id, SpvExecutionModel execution_model) {
+    uint32_t var_id, spv::ExecutionModel execution_model) {
   analysis::DecorationManager* decoration_manager =
       context()->get_decoration_mgr();
-  if (execution_model == SpvExecutionModelFragment) {
+  if (execution_model == spv::ExecutionModel::Fragment) {
     return get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 6) &&
            HasBuiltinDecoration(decoration_manager, var_id,
-                                SpvBuiltInHelperInvocation);
+                                uint32_t(spv::BuiltIn::HelperInvocation));
   }
 
-  if (execution_model == SpvExecutionModelIntersectionKHR ||
-      execution_model == SpvExecutionModelIntersectionNV) {
+  if (execution_model == spv::ExecutionModel::IntersectionKHR ||
+      execution_model == spv::ExecutionModel::IntersectionNV) {
     if (HasBuiltinDecoration(decoration_manager, var_id,
-                             SpvBuiltInRayTmaxKHR)) {
+                             uint32_t(spv::BuiltIn::RayTmaxKHR))) {
       return true;
     }
   }
 
   switch (execution_model) {
-    case SpvExecutionModelRayGenerationKHR:
-    case SpvExecutionModelClosestHitKHR:
-    case SpvExecutionModelMissKHR:
-    case SpvExecutionModelCallableKHR:
-    case SpvExecutionModelIntersectionKHR:
+    case spv::ExecutionModel::RayGenerationKHR:
+    case spv::ExecutionModel::ClosestHitKHR:
+    case spv::ExecutionModel::MissKHR:
+    case spv::ExecutionModel::CallableKHR:
+    case spv::ExecutionModel::IntersectionKHR:
       return HasBuiltinForRayTracingVolatileSemantics(decoration_manager,
                                                       var_id);
     default:
diff --git a/third_party/SPIRV-Tools/source/opt/spread_volatile_semantics.h b/third_party/SPIRV-Tools/source/opt/spread_volatile_semantics.h
index 014858d..4cbb526 100644
--- a/third_party/SPIRV-Tools/source/opt/spread_volatile_semantics.h
+++ b/third_party/SPIRV-Tools/source/opt/spread_volatile_semantics.h
@@ -39,7 +39,8 @@
   // have an execution model.
   bool HasNoExecutionModel() {
     return get_module()->entry_points().empty() &&
-           context()->get_feature_mgr()->HasCapability(SpvCapabilityLinkage);
+           context()->get_feature_mgr()->HasCapability(
+               spv::Capability::Linkage);
   }
 
   // Iterates interface variables and spreads the Volatile semantics if it has
@@ -52,7 +53,7 @@
   // VUID-StandaloneSpirv-VulkanMemoryModel-04678 or
   // VUID-StandaloneSpirv-VulkanMemoryModel-04679.
   bool IsTargetForVolatileSemantics(uint32_t var_id,
-                                    SpvExecutionModel execution_model);
+                                    spv::ExecutionModel execution_model);
 
   // Collects interface variables that need the volatile semantics.
   // |is_vk_memory_model_enabled| is true if VulkanMemoryModel capability is
diff --git a/third_party/SPIRV-Tools/source/opt/ssa_rewrite_pass.cpp b/third_party/SPIRV-Tools/source/opt/ssa_rewrite_pass.cpp
index 29ab612..b8e2290 100644
--- a/third_party/SPIRV-Tools/source/opt/ssa_rewrite_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/ssa_rewrite_pass.cpp
@@ -63,11 +63,9 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
-const uint32_t kStoreValIdInIdx = 1;
-const uint32_t kVariableInitIdInIdx = 1;
-const uint32_t kDebugDeclareOperandVariableIdx = 5;
+constexpr uint32_t kStoreValIdInIdx = 1;
+constexpr uint32_t kVariableInitIdInIdx = 1;
 }  // namespace
 
 std::string SSARewriter::PhiCandidate::PrettyPrint(const CFG* cfg) const {
@@ -301,12 +299,12 @@
 
 void SSARewriter::ProcessStore(Instruction* inst, BasicBlock* bb) {
   auto opcode = inst->opcode();
-  assert((opcode == SpvOpStore || opcode == SpvOpVariable) &&
+  assert((opcode == spv::Op::OpStore || opcode == spv::Op::OpVariable) &&
          "Expecting a store or a variable definition instruction.");
 
   uint32_t var_id = 0;
   uint32_t val_id = 0;
-  if (opcode == SpvOpStore) {
+  if (opcode == spv::Op::OpStore) {
     (void)pass_->GetPtr(inst, &var_id);
     val_id = inst->GetSingleWordInOperand(kStoreValIdInIdx);
   } else if (inst->NumInOperands() >= 2) {
@@ -315,8 +313,8 @@
   }
   if (pass_->IsTargetVar(var_id)) {
     WriteVariable(var_id, bb, val_id);
-    pass_->context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
-        inst, var_id, val_id, inst, &decls_invisible_to_value_assignment_);
+    pass_->context()->get_debug_info_mgr()->AddDebugValueForVariable(
+        inst, var_id, val_id, inst);
 
 #if SSA_REWRITE_DEBUGGING_LEVEL > 1
     std::cerr << "\tFound store '%" << var_id << " = %" << val_id << "': "
@@ -444,9 +442,9 @@
 
   for (auto& inst : *bb) {
     auto opcode = inst.opcode();
-    if (opcode == SpvOpStore || opcode == SpvOpVariable) {
+    if (opcode == spv::Op::OpStore || opcode == spv::Op::OpVariable) {
       ProcessStore(&inst, bb);
-    } else if (inst.opcode() == SpvOpLoad) {
+    } else if (inst.opcode() == spv::Op::OpLoad) {
       if (!ProcessLoad(&inst, bb)) {
         return false;
       }
@@ -546,7 +544,7 @@
     // Generate a new OpPhi instruction and insert it in its basic
     // block.
     std::unique_ptr<Instruction> phi_inst(
-        new Instruction(pass_->context(), SpvOpPhi, type_id,
+        new Instruction(pass_->context(), spv::Op::OpPhi, type_id,
                         phi_candidate->result_id(), phi_operands));
     generated_phis.push_back(phi_inst.get());
     pass_->get_def_use_mgr()->AnalyzeInstDef(&*phi_inst);
@@ -555,13 +553,13 @@
     insert_it = insert_it.InsertBefore(std::move(phi_inst));
     pass_->context()->get_decoration_mgr()->CloneDecorations(
         phi_candidate->var_id(), phi_candidate->result_id(),
-        {SpvDecorationRelaxedPrecision});
+        {spv::Decoration::RelaxedPrecision});
 
     // Add DebugValue for the new OpPhi instruction.
     insert_it->SetDebugScope(local_var->GetDebugScope());
-    pass_->context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
+    pass_->context()->get_debug_info_mgr()->AddDebugValueForVariable(
         &*insert_it, phi_candidate->var_id(), phi_candidate->result_id(),
-        &*insert_it, &decls_invisible_to_value_assignment_);
+        &*insert_it);
 
     modified = true;
   }
@@ -650,62 +648,6 @@
   }
 }
 
-Pass::Status SSARewriter::AddDebugValuesForInvisibleDebugDecls(Function* fp) {
-  // For the cases the value assignment is invisible to DebugDeclare e.g.,
-  // the argument passing for an inlined function.
-  //
-  // Before inlining foo(int x):
-  //   a = 3;
-  //   foo(3);
-  // After inlining:
-  //   a = 3;
-  //   foo and x disappeared but we want to specify "DebugValue: %x = %int_3".
-  //
-  // We want to specify the value for the variable using |defs_at_block_[bb]|,
-  // where |bb| is the basic block contains the decl.
-  DominatorAnalysis* dom_tree = pass_->context()->GetDominatorAnalysis(fp);
-  Pass::Status status = Pass::Status::SuccessWithoutChange;
-  for (auto* decl : decls_invisible_to_value_assignment_) {
-    uint32_t var_id =
-        decl->GetSingleWordOperand(kDebugDeclareOperandVariableIdx);
-    auto* var = pass_->get_def_use_mgr()->GetDef(var_id);
-    if (var->opcode() == SpvOpFunctionParameter) continue;
-
-    auto* bb = pass_->context()->get_instr_block(decl);
-    uint32_t value_id = GetValueAtBlock(var_id, bb);
-    Instruction* value = nullptr;
-    if (value_id) value = pass_->get_def_use_mgr()->GetDef(value_id);
-
-    // If |value| is defined before the function body, it dominates |decl|.
-    // If |value| dominates |decl|, we can set it as DebugValue.
-    if (value && (pass_->context()->get_instr_block(value) == nullptr ||
-                  dom_tree->Dominates(value, decl))) {
-      if (pass_->context()->get_debug_info_mgr()->AddDebugValueForDecl(
-              decl, value->result_id(), decl, value) == nullptr) {
-        return Pass::Status::Failure;
-      }
-    } else {
-      // If |value| in the same basic block does not dominate |decl|, we can
-      // assign the value in the immediate dominator.
-      value_id = GetValueAtBlock(var_id, dom_tree->ImmediateDominator(bb));
-      if (value_id) value = pass_->get_def_use_mgr()->GetDef(value_id);
-      if (value_id &&
-          pass_->context()->get_debug_info_mgr()->AddDebugValueForDecl(
-              decl, value_id, decl, value) == nullptr) {
-        return Pass::Status::Failure;
-      }
-    }
-
-    // DebugDeclares of target variables will be removed by
-    // SSARewritePass::Process().
-    if (!pass_->IsTargetVar(var_id)) {
-      pass_->context()->get_debug_info_mgr()->KillDebugDeclares(var_id);
-    }
-    status = Pass::Status::SuccessWithChange;
-  }
-  return status;
-}
-
 Pass::Status SSARewriter::RewriteFunctionIntoSSA(Function* fp) {
 #if SSA_REWRITE_DEBUGGING_LEVEL > 0
   std::cerr << "Function before SSA rewrite:\n"
@@ -735,12 +677,6 @@
   // Finally, apply all the replacements in the IR.
   bool modified = ApplyReplacements();
 
-  auto status = AddDebugValuesForInvisibleDebugDecls(fp);
-  if (status == Pass::Status::SuccessWithChange ||
-      status == Pass::Status::Failure) {
-    return status;
-  }
-
 #if SSA_REWRITE_DEBUGGING_LEVEL > 0
   std::cerr << "\n\n\nFunction after SSA rewrite:\n"
             << fp->PrettyPrint(0) << "\n";
diff --git a/third_party/SPIRV-Tools/source/opt/ssa_rewrite_pass.h b/third_party/SPIRV-Tools/source/opt/ssa_rewrite_pass.h
index 1f4cd24..2470f85 100644
--- a/third_party/SPIRV-Tools/source/opt/ssa_rewrite_pass.h
+++ b/third_party/SPIRV-Tools/source/opt/ssa_rewrite_pass.h
@@ -253,11 +253,6 @@
   // candidates.
   void FinalizePhiCandidates();
 
-  // Adds DebugValues for DebugDeclares in
-  // |decls_invisible_to_value_assignment_|. Returns whether the function was
-  // modified or not, and whether or not the conversion was successful.
-  Pass::Status AddDebugValuesForInvisibleDebugDecls(Function* fp);
-
   // Prints the table of Phi candidates to std::cerr.
   void PrintPhiCandidates() const;
 
@@ -295,10 +290,6 @@
 
   // Memory pass requesting the SSA rewriter.
   MemPass* pass_;
-
-  // Set of DebugDeclare instructions that are not added as DebugValue because
-  // they are invisible to the store or phi instructions.
-  std::unordered_set<Instruction*> decls_invisible_to_value_assignment_;
 };
 
 class SSARewritePass : public MemPass {
diff --git a/third_party/SPIRV-Tools/source/opt/strength_reduction_pass.cpp b/third_party/SPIRV-Tools/source/opt/strength_reduction_pass.cpp
index ab7c4eb..f2e8498 100644
--- a/third_party/SPIRV-Tools/source/opt/strength_reduction_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/strength_reduction_pass.cpp
@@ -28,6 +28,8 @@
 #include "source/opt/log.h"
 #include "source/opt/reflect.h"
 
+namespace spvtools {
+namespace opt {
 namespace {
 // Count the number of trailing zeros in the binary representation of
 // |constVal|.
@@ -53,9 +55,6 @@
 
 }  // namespace
 
-namespace spvtools {
-namespace opt {
-
 Pass::Status StrengthReductionPass::Process() {
   // Initialize the member variables on a per module basis.
   bool modified = false;
@@ -70,7 +69,7 @@
 
 bool StrengthReductionPass::ReplaceMultiplyByPowerOf2(
     BasicBlock::iterator* inst) {
-  assert((*inst)->opcode() == SpvOp::SpvOpIMul &&
+  assert((*inst)->opcode() == spv::Op::OpIMul &&
          "Only works for multiplication of integers.");
   bool modified = false;
 
@@ -84,7 +83,7 @@
   for (int i = 0; i < 2; i++) {
     uint32_t opId = (*inst)->GetSingleWordInOperand(i);
     Instruction* opInst = get_def_use_mgr()->GetDef(opId);
-    if (opInst->opcode() == SpvOp::SpvOpConstant) {
+    if (opInst->opcode() == spv::Op::OpConstant) {
       // We found a constant operand.
       uint32_t constVal = opInst->GetSingleWordOperand(2);
 
@@ -101,7 +100,7 @@
                              {shiftConstResultId});
         newOperands.push_back(shiftOperand);
         std::unique_ptr<Instruction> newInstruction(
-            new Instruction(context(), SpvOp::SpvOpShiftLeftLogical,
+            new Instruction(context(), spv::Op::OpShiftLeftLogical,
                             (*inst)->type_id(), newResultId, newOperands));
 
         // Insert the new instruction and update the data structures.
@@ -133,7 +132,7 @@
   for (auto iter = get_module()->types_values_begin();
        iter != get_module()->types_values_end(); ++iter) {
     switch (iter->opcode()) {
-      case SpvOp::SpvOpConstant:
+      case spv::Op::OpConstant:
         if (iter->type_id() == uint32_type_id_) {
           uint32_t value = iter->GetSingleWordOperand(2);
           if (value <= 32) constant_ids_[value] = iter->result_id();
@@ -159,9 +158,8 @@
     uint32_t resultId = TakeNextId();
     Operand constant(spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
                      {val});
-    std::unique_ptr<Instruction> newConstant(
-        new Instruction(context(), SpvOp::SpvOpConstant, uint32_type_id_,
-                        resultId, {constant}));
+    std::unique_ptr<Instruction> newConstant(new Instruction(
+        context(), spv::Op::OpConstant, uint32_type_id_, resultId, {constant}));
     get_module()->AddGlobalValue(std::move(newConstant));
 
     // Notify the DefUseManager about this constant.
@@ -184,7 +182,7 @@
     for (auto& bb : func) {
       for (auto inst = bb.begin(); inst != bb.end(); ++inst) {
         switch (inst->opcode()) {
-          case SpvOp::SpvOpIMul:
+          case spv::Op::OpIMul:
             if (ReplaceMultiplyByPowerOf2(&inst)) modified = true;
             break;
           default:
diff --git a/third_party/SPIRV-Tools/source/opt/strip_debug_info_pass.cpp b/third_party/SPIRV-Tools/source/opt/strip_debug_info_pass.cpp
index 6a0ebf2..f81bced 100644
--- a/third_party/SPIRV-Tools/source/opt/strip_debug_info_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/strip_debug_info_pass.cpp
@@ -37,13 +37,13 @@
   if (uses_non_semantic_info) {
     for (auto& inst : context()->module()->debugs1()) {
       switch (inst.opcode()) {
-        case SpvOpString: {
+        case spv::Op::OpString: {
           analysis::DefUseManager* def_use = context()->get_def_use_mgr();
 
           // see if this string is used anywhere by a non-semantic instruction
           bool no_nonsemantic_use =
               def_use->WhileEachUser(&inst, [def_use](Instruction* use) {
-                if (use->opcode() == SpvOpExtInst) {
+                if (use->opcode() == spv::Op::OpExtInst) {
                   auto ext_inst_set =
                       def_use->GetDef(use->GetSingleWordInOperand(0u));
                   const std::string extension_name =
@@ -83,7 +83,8 @@
   // when that instruction is killed, which will lead to a double kill.
   std::sort(to_kill.begin(), to_kill.end(),
             [](Instruction* lhs, Instruction* rhs) -> bool {
-              if (lhs->opcode() == SpvOpName && rhs->opcode() != SpvOpName)
+              if (lhs->opcode() == spv::Op::OpName &&
+                  rhs->opcode() != spv::Op::OpName)
                 return true;
               return false;
             });
diff --git a/third_party/SPIRV-Tools/source/opt/strip_nonsemantic_info_pass.cpp b/third_party/SPIRV-Tools/source/opt/strip_nonsemantic_info_pass.cpp
index cd1fbb6..8899690 100644
--- a/third_party/SPIRV-Tools/source/opt/strip_nonsemantic_info_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/strip_nonsemantic_info_pass.cpp
@@ -32,27 +32,31 @@
   bool other_uses_for_decorate_string = false;
   for (auto& inst : context()->module()->annotations()) {
     switch (inst.opcode()) {
-      case SpvOpDecorateStringGOOGLE:
-        if (inst.GetSingleWordInOperand(1) == SpvDecorationHlslSemanticGOOGLE ||
-            inst.GetSingleWordInOperand(1) == SpvDecorationUserTypeGOOGLE) {
+      case spv::Op::OpDecorateStringGOOGLE:
+        if (spv::Decoration(inst.GetSingleWordInOperand(1)) ==
+                spv::Decoration::HlslSemanticGOOGLE ||
+            spv::Decoration(inst.GetSingleWordInOperand(1)) ==
+                spv::Decoration::UserTypeGOOGLE) {
           to_remove.push_back(&inst);
         } else {
           other_uses_for_decorate_string = true;
         }
         break;
 
-      case SpvOpMemberDecorateStringGOOGLE:
-        if (inst.GetSingleWordInOperand(2) == SpvDecorationHlslSemanticGOOGLE ||
-            inst.GetSingleWordInOperand(2) == SpvDecorationUserTypeGOOGLE) {
+      case spv::Op::OpMemberDecorateStringGOOGLE:
+        if (spv::Decoration(inst.GetSingleWordInOperand(2)) ==
+                spv::Decoration::HlslSemanticGOOGLE ||
+            spv::Decoration(inst.GetSingleWordInOperand(2)) ==
+                spv::Decoration::UserTypeGOOGLE) {
           to_remove.push_back(&inst);
         } else {
           other_uses_for_decorate_string = true;
         }
         break;
 
-      case SpvOpDecorateId:
-        if (inst.GetSingleWordInOperand(1) ==
-            SpvDecorationHlslCounterBufferGOOGLE) {
+      case spv::Op::OpDecorateId:
+        if (spv::Decoration(inst.GetSingleWordInOperand(1)) ==
+            spv::Decoration::HlslCounterBufferGOOGLE) {
           to_remove.push_back(&inst);
         }
         break;
@@ -79,7 +83,7 @@
   // remove any extended inst imports that are non semantic
   std::unordered_set<uint32_t> non_semantic_sets;
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.")) {
@@ -93,7 +97,7 @@
   if (!non_semantic_sets.empty()) {
     context()->module()->ForEachInst(
         [&non_semantic_sets, &to_remove](Instruction* inst) {
-          if (inst->opcode() == SpvOpExtInst) {
+          if (inst->opcode() == spv::Op::OpExtInst) {
             if (non_semantic_sets.find(inst->GetSingleWordInOperand(0)) !=
                 non_semantic_sets.end()) {
               to_remove.push_back(inst);
diff --git a/third_party/SPIRV-Tools/source/opt/struct_cfg_analysis.cpp b/third_party/SPIRV-Tools/source/opt/struct_cfg_analysis.cpp
index 203db87..290b4bf 100644
--- a/third_party/SPIRV-Tools/source/opt/struct_cfg_analysis.cpp
+++ b/third_party/SPIRV-Tools/source/opt/struct_cfg_analysis.cpp
@@ -16,18 +16,17 @@
 
 #include "source/opt/ir_context.h"
 
-namespace {
-const uint32_t kMergeNodeIndex = 0;
-const uint32_t kContinueNodeIndex = 1;
-}  // namespace
-
 namespace spvtools {
 namespace opt {
+namespace {
+constexpr uint32_t kMergeNodeIndex = 0;
+constexpr uint32_t kContinueNodeIndex = 1;
+}  // namespace
 
 StructuredCFGAnalysis::StructuredCFGAnalysis(IRContext* ctx) : context_(ctx) {
   // If this is not a shader, there are no merge instructions, and not
   // structured CFG to analyze.
-  if (!context_->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
+  if (!context_->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
     return;
   }
 
@@ -82,7 +81,7 @@
           merge_inst->GetSingleWordInOperand(kMergeNodeIndex);
       new_state.cinfo.containing_construct = block->id();
 
-      if (merge_inst->opcode() == SpvOpLoopMerge) {
+      if (merge_inst->opcode() == spv::Op::OpLoopMerge) {
         new_state.cinfo.containing_loop = block->id();
         new_state.cinfo.containing_switch = 0;
         new_state.continue_node =
@@ -98,7 +97,7 @@
         new_state.cinfo.in_continue = state.back().cinfo.in_continue;
         new_state.continue_node = state.back().continue_node;
 
-        if (merge_inst->NextNode()->opcode() == SpvOpSwitch) {
+        if (merge_inst->NextNode()->opcode() == spv::Op::OpSwitch) {
           new_state.cinfo.containing_switch = block->id();
         } else {
           new_state.cinfo.containing_switch =
@@ -226,7 +225,7 @@
     for (auto& bb : func) {
       if (IsInContainingLoopsContinueConstruct(bb.id())) {
         for (const Instruction& inst : bb) {
-          if (inst.opcode() == SpvOpFunctionCall) {
+          if (inst.opcode() == spv::Op::OpFunctionCall) {
             funcs_to_process.push(inst.GetSingleWordInOperand(0));
           }
         }
diff --git a/third_party/SPIRV-Tools/source/opt/type_manager.cpp b/third_party/SPIRV-Tools/source/opt/type_manager.cpp
index a0006f5..7dc9c8f 100644
--- a/third_party/SPIRV-Tools/source/opt/type_manager.cpp
+++ b/third_party/SPIRV-Tools/source/opt/type_manager.cpp
@@ -29,10 +29,8 @@
 namespace opt {
 namespace analysis {
 namespace {
-
-const int kSpvTypePointerStorageClass = 1;
-const int kSpvTypePointerTypeIdInIdx = 2;
-
+constexpr int kSpvTypePointerStorageClass = 1;
+constexpr int kSpvTypePointerTypeIdInIdx = 2;
 }  // namespace
 
 TypeManager::TypeManager(const MessageConsumer& consumer, IRContext* c)
@@ -49,7 +47,7 @@
 }
 
 std::pair<Type*, std::unique_ptr<Pointer>> TypeManager::GetTypeAndPointerType(
-    uint32_t id, SpvStorageClass sc) const {
+    uint32_t id, spv::StorageClass sc) const {
   Type* type = GetType(id);
   if (type) {
     return std::make_pair(type, MakeUnique<Pointer>(type, sc));
@@ -220,10 +218,10 @@
 
   RegisterType(id, *type);
   switch (type->kind()) {
-#define DefineParameterlessCase(kind)                                     \
-  case Type::k##kind:                                                     \
-    typeInst = MakeUnique<Instruction>(context(), SpvOpType##kind, 0, id, \
-                                       std::initializer_list<Operand>{}); \
+#define DefineParameterlessCase(kind)                                         \
+  case Type::k##kind:                                                         \
+    typeInst = MakeUnique<Instruction>(context(), spv::Op::OpType##kind, 0,   \
+                                       id, std::initializer_list<Operand>{}); \
     break
     DefineParameterlessCase(Void);
     DefineParameterlessCase(Bool);
@@ -239,7 +237,7 @@
 #undef DefineParameterlessCase
     case Type::kInteger:
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeInt, 0, id,
+          context(), spv::Op::OpTypeInt, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {type->AsInteger()->width()}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -247,7 +245,7 @@
       break;
     case Type::kFloat:
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeFloat, 0, id,
+          context(), spv::Op::OpTypeFloat, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {type->AsFloat()->width()}}});
       break;
@@ -257,7 +255,7 @@
         return 0;
       }
       typeInst =
-          MakeUnique<Instruction>(context(), SpvOpTypeVector, 0, id,
+          MakeUnique<Instruction>(context(), spv::Op::OpTypeVector, 0, id,
                                   std::initializer_list<Operand>{
                                       {SPV_OPERAND_TYPE_ID, {subtype}},
                                       {SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -270,7 +268,7 @@
         return 0;
       }
       typeInst =
-          MakeUnique<Instruction>(context(), SpvOpTypeMatrix, 0, id,
+          MakeUnique<Instruction>(context(), spv::Op::OpTypeMatrix, 0, id,
                                   std::initializer_list<Operand>{
                                       {SPV_OPERAND_TYPE_ID, {subtype}},
                                       {SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -284,7 +282,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeImage, 0, id,
+          context(), spv::Op::OpTypeImage, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ID, {subtype}},
               {SPV_OPERAND_TYPE_DIMENSIONALITY,
@@ -308,7 +306,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeSampledImage, 0, id,
+          context(), spv::Op::OpTypeSampledImage, 0, id,
           std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {subtype}}});
       break;
     }
@@ -318,7 +316,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeArray, 0, id,
+          context(), spv::Op::OpTypeArray, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ID, {subtype}},
               {SPV_OPERAND_TYPE_ID, {type->AsArray()->LengthId()}}});
@@ -331,7 +329,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeRuntimeArray, 0, id,
+          context(), spv::Op::OpTypeRuntimeArray, 0, id,
           std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {subtype}}});
       break;
     }
@@ -346,7 +344,7 @@
         ops.push_back(Operand(SPV_OPERAND_TYPE_ID, {member_type_id}));
       }
       typeInst =
-          MakeUnique<Instruction>(context(), SpvOpTypeStruct, 0, id, ops);
+          MakeUnique<Instruction>(context(), spv::Op::OpTypeStruct, 0, id, ops);
       break;
     }
     case Type::kOpaque: {
@@ -354,7 +352,7 @@
       // Convert to null-terminated packed UTF-8 string.
       std::vector<uint32_t> words = spvtools::utils::MakeVector(opaque->name());
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeOpaque, 0, id,
+          context(), spv::Op::OpTypeOpaque, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_LITERAL_STRING, words}});
       break;
@@ -366,7 +364,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypePointer, 0, id,
+          context(), spv::Op::OpTypePointer, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_STORAGE_CLASS,
                {static_cast<uint32_t>(pointer->storage_class())}},
@@ -388,20 +386,20 @@
         }
         ops.push_back(Operand(SPV_OPERAND_TYPE_ID, {paramater_type_id}));
       }
-      typeInst =
-          MakeUnique<Instruction>(context(), SpvOpTypeFunction, 0, id, ops);
+      typeInst = MakeUnique<Instruction>(context(), spv::Op::OpTypeFunction, 0,
+                                         id, ops);
       break;
     }
     case Type::kPipe:
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypePipe, 0, id,
+          context(), spv::Op::OpTypePipe, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
                {static_cast<uint32_t>(type->AsPipe()->access_qualifier())}}});
       break;
     case Type::kForwardPointer:
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeForwardPointer, 0, 0,
+          context(), spv::Op::OpTypeForwardPointer, 0, 0,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ID, {type->AsForwardPointer()->target_id()}},
               {SPV_OPERAND_TYPE_STORAGE_CLASS,
@@ -416,7 +414,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeCooperativeMatrixNV, 0, id,
+          context(), spv::Op::OpTypeCooperativeMatrixNV, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ID, {component_type}},
               {SPV_OPERAND_TYPE_SCOPE_ID, {coop_mat->scope_id()}},
@@ -435,7 +433,7 @@
 }
 
 uint32_t TypeManager::FindPointerToType(uint32_t type_id,
-                                        SpvStorageClass storage_class) {
+                                        spv::StorageClass storage_class) {
   Type* pointeeTy = GetType(type_id);
   Pointer pointerTy(pointeeTy, storage_class);
   if (pointeeTy->IsUniqueType(true)) {
@@ -447,11 +445,11 @@
   Module::inst_iterator type_itr = context()->module()->types_values_begin();
   for (; type_itr != context()->module()->types_values_end(); ++type_itr) {
     const Instruction* type_inst = &*type_itr;
-    if (type_inst->opcode() == SpvOpTypePointer &&
+    if (type_inst->opcode() == spv::Op::OpTypePointer &&
         type_inst->GetSingleWordOperand(kSpvTypePointerTypeIdInIdx) ==
             type_id &&
-        type_inst->GetSingleWordOperand(kSpvTypePointerStorageClass) ==
-            storage_class)
+        spv::StorageClass(type_inst->GetSingleWordOperand(
+            kSpvTypePointerStorageClass)) == storage_class)
       return type_inst->result_id();
   }
 
@@ -459,7 +457,7 @@
   // TODO(1841): Handle id overflow.
   uint32_t resultId = context()->TakeNextId();
   std::unique_ptr<Instruction> type_inst(
-      new Instruction(context(), SpvOpTypePointer, 0, resultId,
+      new Instruction(context(), spv::Op::OpTypePointer, 0, resultId,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
                         {uint32_t(storage_class)}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {type_id}}}));
@@ -476,7 +474,7 @@
     for (auto pair : structTy->element_decorations()) {
       uint32_t element = pair.first;
       for (auto vec : pair.second) {
-        CreateDecoration(id, vec, element);
+        CreateDecoration(id, vec, /* is_member */ true, element);
       }
     }
   }
@@ -484,10 +482,10 @@
 
 void TypeManager::CreateDecoration(uint32_t target,
                                    const std::vector<uint32_t>& decoration,
-                                   uint32_t element) {
+                                   bool is_member, uint32_t element) {
   std::vector<Operand> ops;
   ops.push_back(Operand(SPV_OPERAND_TYPE_ID, {target}));
-  if (element != 0) {
+  if (is_member) {
     ops.push_back(Operand(SPV_OPERAND_TYPE_LITERAL_INTEGER, {element}));
   }
   ops.push_back(Operand(SPV_OPERAND_TYPE_DECORATION, {decoration[0]}));
@@ -495,8 +493,8 @@
     ops.push_back(Operand(SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration[i]}));
   }
   context()->AddAnnotationInst(MakeUnique<Instruction>(
-      context(), (element == 0 ? SpvOpDecorate : SpvOpMemberDecorate), 0, 0,
-      ops));
+      context(), (is_member ? spv::Op::OpMemberDecorate : spv::Op::OpDecorate),
+      0, 0, ops));
   Instruction* inst = &*--context()->annotation_end();
   context()->get_def_use_mgr()->AnalyzeInstUse(inst);
 }
@@ -665,46 +663,47 @@
 
   Type* type = nullptr;
   switch (inst.opcode()) {
-    case SpvOpTypeVoid:
+    case spv::Op::OpTypeVoid:
       type = new Void();
       break;
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       type = new Bool();
       break;
-    case SpvOpTypeInt:
+    case spv::Op::OpTypeInt:
       type = new Integer(inst.GetSingleWordInOperand(0),
                          inst.GetSingleWordInOperand(1));
       break;
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeFloat:
       type = new Float(inst.GetSingleWordInOperand(0));
       break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       type = new Vector(GetType(inst.GetSingleWordInOperand(0)),
                         inst.GetSingleWordInOperand(1));
       break;
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       type = new Matrix(GetType(inst.GetSingleWordInOperand(0)),
                         inst.GetSingleWordInOperand(1));
       break;
-    case SpvOpTypeImage: {
-      const SpvAccessQualifier access =
-          inst.NumInOperands() < 8
-              ? SpvAccessQualifierReadOnly
-              : static_cast<SpvAccessQualifier>(inst.GetSingleWordInOperand(7));
+    case spv::Op::OpTypeImage: {
+      const spv::AccessQualifier access =
+          inst.NumInOperands() < 8 ? spv::AccessQualifier::ReadOnly
+                                   : static_cast<spv::AccessQualifier>(
+                                         inst.GetSingleWordInOperand(7));
       type = new Image(
           GetType(inst.GetSingleWordInOperand(0)),
-          static_cast<SpvDim>(inst.GetSingleWordInOperand(1)),
+          static_cast<spv::Dim>(inst.GetSingleWordInOperand(1)),
           inst.GetSingleWordInOperand(2), inst.GetSingleWordInOperand(3) == 1,
           inst.GetSingleWordInOperand(4) == 1, inst.GetSingleWordInOperand(5),
-          static_cast<SpvImageFormat>(inst.GetSingleWordInOperand(6)), access);
+          static_cast<spv::ImageFormat>(inst.GetSingleWordInOperand(6)),
+          access);
     } break;
-    case SpvOpTypeSampler:
+    case spv::Op::OpTypeSampler:
       type = new Sampler();
       break;
-    case SpvOpTypeSampledImage:
+    case spv::Op::OpTypeSampledImage:
       type = new SampledImage(GetType(inst.GetSingleWordInOperand(0)));
       break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       const uint32_t length_id = inst.GetSingleWordInOperand(1);
       const Instruction* length_constant_inst = id_to_constant_inst_[length_id];
       assert(length_constant_inst);
@@ -717,11 +716,11 @@
       // Only OpSpecConstant has a SpecId.
       uint32_t spec_id = 0u;
       bool has_spec_id = false;
-      if (length_constant_inst->opcode() == SpvOpSpecConstant) {
+      if (length_constant_inst->opcode() == spv::Op::OpSpecConstant) {
         context()->get_decoration_mgr()->ForEachDecoration(
-            length_id, SpvDecorationSpecId,
+            length_id, uint32_t(spv::Decoration::SpecId),
             [&spec_id, &has_spec_id](const Instruction& decoration) {
-              assert(decoration.opcode() == SpvOpDecorate);
+              assert(decoration.opcode() == spv::Op::OpDecorate);
               spec_id = decoration.GetSingleWordOperand(2u);
               has_spec_id = true;
             });
@@ -730,7 +729,8 @@
       if (has_spec_id) {
         extra_words.push_back(spec_id);
       }
-      if ((opcode == SpvOpConstant) || (opcode == SpvOpSpecConstant)) {
+      if ((opcode == spv::Op::OpConstant) ||
+          (opcode == spv::Op::OpSpecConstant)) {
         // Always include the literal constant words.  In the spec constant
         // case, the constant might not be overridden, so it's still
         // significant.
@@ -754,7 +754,7 @@
         return type;
       }
     } break;
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       type = new RuntimeArray(GetType(inst.GetSingleWordInOperand(0)));
       if (id_to_incomplete_type_.count(inst.GetSingleWordInOperand(0))) {
         incomplete_types_.emplace_back(inst.result_id(), type);
@@ -762,7 +762,7 @@
         return type;
       }
       break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       std::vector<const Type*> element_types;
       bool incomplete_type = false;
       for (uint32_t i = 0; i < inst.NumInOperands(); ++i) {
@@ -780,14 +780,14 @@
         return type;
       }
     } break;
-    case SpvOpTypeOpaque: {
+    case spv::Op::OpTypeOpaque: {
       type = new Opaque(inst.GetInOperand(0).AsString());
     } break;
-    case SpvOpTypePointer: {
+    case spv::Op::OpTypePointer: {
       uint32_t pointee_type_id = inst.GetSingleWordInOperand(1);
       type = new Pointer(
           GetType(pointee_type_id),
-          static_cast<SpvStorageClass>(inst.GetSingleWordInOperand(0)));
+          static_cast<spv::StorageClass>(inst.GetSingleWordInOperand(0)));
 
       if (id_to_incomplete_type_.count(pointee_type_id)) {
         incomplete_types_.emplace_back(inst.result_id(), type);
@@ -797,7 +797,7 @@
       id_to_incomplete_type_.erase(inst.result_id());
 
     } break;
-    case SpvOpTypeFunction: {
+    case spv::Op::OpTypeFunction: {
       bool incomplete_type = false;
       uint32_t return_type_id = inst.GetSingleWordInOperand(0);
       if (id_to_incomplete_type_.count(return_type_id)) {
@@ -821,47 +821,47 @@
         return type;
       }
     } break;
-    case SpvOpTypeEvent:
+    case spv::Op::OpTypeEvent:
       type = new Event();
       break;
-    case SpvOpTypeDeviceEvent:
+    case spv::Op::OpTypeDeviceEvent:
       type = new DeviceEvent();
       break;
-    case SpvOpTypeReserveId:
+    case spv::Op::OpTypeReserveId:
       type = new ReserveId();
       break;
-    case SpvOpTypeQueue:
+    case spv::Op::OpTypeQueue:
       type = new Queue();
       break;
-    case SpvOpTypePipe:
+    case spv::Op::OpTypePipe:
       type = new Pipe(
-          static_cast<SpvAccessQualifier>(inst.GetSingleWordInOperand(0)));
+          static_cast<spv::AccessQualifier>(inst.GetSingleWordInOperand(0)));
       break;
-    case SpvOpTypeForwardPointer: {
+    case spv::Op::OpTypeForwardPointer: {
       // Handling of forward pointers is different from the other types.
       uint32_t target_id = inst.GetSingleWordInOperand(0);
-      type = new ForwardPointer(target_id, static_cast<SpvStorageClass>(
+      type = new ForwardPointer(target_id, static_cast<spv::StorageClass>(
                                                inst.GetSingleWordInOperand(1)));
       incomplete_types_.emplace_back(target_id, type);
       id_to_incomplete_type_[target_id] = type;
       return type;
     }
-    case SpvOpTypePipeStorage:
+    case spv::Op::OpTypePipeStorage:
       type = new PipeStorage();
       break;
-    case SpvOpTypeNamedBarrier:
+    case spv::Op::OpTypeNamedBarrier:
       type = new NamedBarrier();
       break;
-    case SpvOpTypeAccelerationStructureNV:
+    case spv::Op::OpTypeAccelerationStructureNV:
       type = new AccelerationStructureNV();
       break;
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       type = new CooperativeMatrixNV(GetType(inst.GetSingleWordInOperand(0)),
                                      inst.GetSingleWordInOperand(1),
                                      inst.GetSingleWordInOperand(2),
                                      inst.GetSingleWordInOperand(3));
       break;
-    case SpvOpTypeRayQueryKHR:
+    case spv::Op::OpTypeRayQueryKHR:
       type = new RayQueryKHR();
       break;
     default:
@@ -886,11 +886,11 @@
 }
 
 void TypeManager::AttachDecoration(const Instruction& inst, Type* type) {
-  const SpvOp opcode = inst.opcode();
+  const spv::Op opcode = inst.opcode();
   if (!IsAnnotationInst(opcode)) return;
 
   switch (opcode) {
-    case SpvOpDecorate: {
+    case spv::Op::OpDecorate: {
       const auto count = inst.NumOperands();
       std::vector<uint32_t> data;
       for (uint32_t i = 1; i < count; ++i) {
@@ -898,7 +898,7 @@
       }
       type->AddDecoration(std::move(data));
     } break;
-    case SpvOpMemberDecorate: {
+    case spv::Op::OpMemberDecorate: {
       const auto count = inst.NumOperands();
       const uint32_t index = inst.GetSingleWordOperand(1);
       std::vector<uint32_t> data;
diff --git a/third_party/SPIRV-Tools/source/opt/type_manager.h b/third_party/SPIRV-Tools/source/opt/type_manager.h
index 72e37f4..c49e193 100644
--- a/third_party/SPIRV-Tools/source/opt/type_manager.h
+++ b/third_party/SPIRV-Tools/source/opt/type_manager.h
@@ -99,7 +99,7 @@
   //
   // |id| must be a registered type.
   std::pair<Type*, std::unique_ptr<Pointer>> GetTypeAndPointerType(
-      uint32_t id, SpvStorageClass sc) const;
+      uint32_t id, spv::StorageClass sc) const;
 
   // Returns an id for a declaration representing |type|.  Returns 0 if the type
   // does not exists, and could not be generated.
@@ -112,7 +112,7 @@
   // Find pointer to type and storage in module, return its resultId.  If it is
   // not found, a new type is created, and its id is returned.  Returns 0 if the
   // type could not be created.
-  uint32_t FindPointerToType(uint32_t type_id, SpvStorageClass storage_class);
+  uint32_t FindPointerToType(uint32_t type_id, spv::StorageClass storage_class);
 
   // Registers |id| to |type|.
   //
@@ -139,6 +139,11 @@
   const Type* GetMemberType(const Type* parent_type,
                             const std::vector<uint32_t>& access_chain);
 
+  // Attaches the decoration encoded in |inst| to |type|. Does nothing if the
+  // given instruction is not a decoration instruction. Assumes the target is
+  // |type| (e.g. should be called in loop of |type|'s decorations).
+  void AttachDecoration(const Instruction& inst, Type* type);
+
   Type* GetUIntType() {
     Integer int_type(32, false);
     return GetRegisteredType(&int_type);
@@ -243,19 +248,15 @@
 
   // Create the annotation instruction.
   //
-  // If |element| is zero, an OpDecorate is created, other an OpMemberDecorate
-  // is created. The annotation is registered with the DefUseManager and the
-  // DecorationManager.
+  // If |is_member| is false, an OpDecorate of |decoration| on |id| is created,
+  // otherwise an OpMemberDecorate is created at |element|. The annotation is
+  // registered with the DefUseManager and the DecorationManager.
   void CreateDecoration(uint32_t id, const std::vector<uint32_t>& decoration,
-                        uint32_t element = 0);
+                        bool is_member = false, uint32_t element = 0);
 
   // Creates and returns a type from the given SPIR-V |inst|. Returns nullptr if
   // the given instruction is not for defining a type.
   Type* RecordIfTypeDefinition(const Instruction& inst);
-  // Attaches the decoration encoded in |inst| to |type|. Does nothing if the
-  // given instruction is not a decoration instruction. Assumes the target is
-  // |type| (e.g. should be called in loop of |type|'s decorations).
-  void AttachDecoration(const Instruction& inst, Type* type);
 
   // Returns an equivalent pointer to |type| built in terms of pointers owned by
   // |type_pool_|. For example, if |type| is a vec3 of bool, it will be rebuilt
diff --git a/third_party/SPIRV-Tools/source/opt/types.cpp b/third_party/SPIRV-Tools/source/opt/types.cpp
index 056aceb..12ff139 100644
--- a/third_party/SPIRV-Tools/source/opt/types.cpp
+++ b/third_party/SPIRV-Tools/source/opt/types.cpp
@@ -24,7 +24,6 @@
 
 #include "source/util/hash_combine.h"
 #include "source/util/make_unique.h"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 namespace opt {
@@ -65,7 +64,7 @@
   return true;
 }
 
-}  // anonymous namespace
+}  // namespace
 
 std::string Type::GetDecorationStr() const {
   std::ostringstream oss;
@@ -357,8 +356,9 @@
   return element_type_->ComputeHashValue(hash, seen);
 }
 
-Image::Image(Type* type, SpvDim dimen, uint32_t d, bool array, bool multisample,
-             uint32_t sampling, SpvImageFormat f, SpvAccessQualifier qualifier)
+Image::Image(Type* type, spv::Dim dimen, uint32_t d, bool array,
+             bool multisample, uint32_t sampling, spv::ImageFormat f,
+             spv::AccessQualifier qualifier)
     : Type(kImage),
       sampled_type_(type),
       dim_(dimen),
@@ -383,9 +383,9 @@
 
 std::string Image::str() const {
   std::ostringstream oss;
-  oss << "image(" << sampled_type_->str() << ", " << dim_ << ", " << depth_
-      << ", " << arrayed_ << ", " << ms_ << ", " << sampled_ << ", " << format_
-      << ", " << access_qualifier_ << ")";
+  oss << "image(" << sampled_type_->str() << ", " << uint32_t(dim_) << ", "
+      << depth_ << ", " << arrayed_ << ", " << ms_ << ", " << sampled_ << ", "
+      << uint32_t(format_) << ", " << uint32_t(access_qualifier_) << ")";
   return oss.str();
 }
 
@@ -557,7 +557,7 @@
   return hash_combine(hash, name_);
 }
 
-Pointer::Pointer(const Type* type, SpvStorageClass sc)
+Pointer::Pointer(const Type* type, spv::StorageClass sc)
     : Type(kPointer), pointee_type_(type), storage_class_(sc) {}
 
 bool Pointer::IsSameImpl(const Type* that, IsSameCache* seen) const {
@@ -636,7 +636,7 @@
 
 std::string Pipe::str() const {
   std::ostringstream oss;
-  oss << "pipe(" << access_qualifier_ << ")";
+  oss << "pipe(" << uint32_t(access_qualifier_) << ")";
   return oss.str();
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/types.h b/third_party/SPIRV-Tools/source/opt/types.h
index a92669e..645dbd4 100644
--- a/third_party/SPIRV-Tools/source/opt/types.h
+++ b/third_party/SPIRV-Tools/source/opt/types.h
@@ -302,9 +302,9 @@
 
 class Image : public Type {
  public:
-  Image(Type* type, SpvDim dimen, uint32_t d, bool array, bool multisample,
-        uint32_t sampling, SpvImageFormat f,
-        SpvAccessQualifier qualifier = SpvAccessQualifierReadOnly);
+  Image(Type* type, spv::Dim dimen, uint32_t d, bool array, bool multisample,
+        uint32_t sampling, spv::ImageFormat f,
+        spv::AccessQualifier qualifier = spv::AccessQualifier::ReadOnly);
   Image(const Image&) = default;
 
   std::string str() const override;
@@ -313,13 +313,13 @@
   const Image* AsImage() const override { return this; }
 
   const Type* sampled_type() const { return sampled_type_; }
-  SpvDim dim() const { return dim_; }
+  spv::Dim dim() const { return dim_; }
   uint32_t depth() const { return depth_; }
   bool is_arrayed() const { return arrayed_; }
   bool is_multisampled() const { return ms_; }
   uint32_t sampled() const { return sampled_; }
-  SpvImageFormat format() const { return format_; }
-  SpvAccessQualifier access_qualifier() const { return access_qualifier_; }
+  spv::ImageFormat format() const { return format_; }
+  spv::AccessQualifier access_qualifier() const { return access_qualifier_; }
 
   size_t ComputeExtraStateHash(size_t hash, SeenTypes* seen) const override;
 
@@ -327,13 +327,13 @@
   bool IsSameImpl(const Type* that, IsSameCache*) const override;
 
   Type* sampled_type_;
-  SpvDim dim_;
+  spv::Dim dim_;
   uint32_t depth_;
   bool arrayed_;
   bool ms_;
   uint32_t sampled_;
-  SpvImageFormat format_;
-  SpvAccessQualifier access_qualifier_;
+  spv::ImageFormat format_;
+  spv::AccessQualifier access_qualifier_;
 };
 
 class SampledImage : public Type {
@@ -491,12 +491,12 @@
 
 class Pointer : public Type {
  public:
-  Pointer(const Type* pointee, SpvStorageClass sc);
+  Pointer(const Type* pointee, spv::StorageClass sc);
   Pointer(const Pointer&) = default;
 
   std::string str() const override;
   const Type* pointee_type() const { return pointee_type_; }
-  SpvStorageClass storage_class() const { return storage_class_; }
+  spv::StorageClass storage_class() const { return storage_class_; }
 
   Pointer* AsPointer() override { return this; }
   const Pointer* AsPointer() const override { return this; }
@@ -509,7 +509,7 @@
   bool IsSameImpl(const Type* that, IsSameCache*) const override;
 
   const Type* pointee_type_;
-  SpvStorageClass storage_class_;
+  spv::StorageClass storage_class_;
 };
 
 class Function : public Type {
@@ -540,7 +540,7 @@
 
 class Pipe : public Type {
  public:
-  Pipe(SpvAccessQualifier qualifier)
+  Pipe(spv::AccessQualifier qualifier)
       : Type(kPipe), access_qualifier_(qualifier) {}
   Pipe(const Pipe&) = default;
 
@@ -549,19 +549,19 @@
   Pipe* AsPipe() override { return this; }
   const Pipe* AsPipe() const override { return this; }
 
-  SpvAccessQualifier access_qualifier() const { return access_qualifier_; }
+  spv::AccessQualifier access_qualifier() const { return access_qualifier_; }
 
   size_t ComputeExtraStateHash(size_t hash, SeenTypes* seen) const override;
 
  private:
   bool IsSameImpl(const Type* that, IsSameCache*) const override;
 
-  SpvAccessQualifier access_qualifier_;
+  spv::AccessQualifier access_qualifier_;
 };
 
 class ForwardPointer : public Type {
  public:
-  ForwardPointer(uint32_t id, SpvStorageClass sc)
+  ForwardPointer(uint32_t id, spv::StorageClass sc)
       : Type(kForwardPointer),
         target_id_(id),
         storage_class_(sc),
@@ -570,7 +570,7 @@
 
   uint32_t target_id() const { return target_id_; }
   void SetTargetPointer(const Pointer* pointer) { pointer_ = pointer; }
-  SpvStorageClass storage_class() const { return storage_class_; }
+  spv::StorageClass storage_class() const { return storage_class_; }
   const Pointer* target_pointer() const { return pointer_; }
 
   std::string str() const override;
@@ -584,7 +584,7 @@
   bool IsSameImpl(const Type* that, IsSameCache*) const override;
 
   uint32_t target_id_;
-  SpvStorageClass storage_class_;
+  spv::StorageClass storage_class_;
   const Pointer* pointer_;
 };
 
diff --git a/third_party/SPIRV-Tools/source/opt/unify_const_pass.cpp b/third_party/SPIRV-Tools/source/opt/unify_const_pass.cpp
index 6bfa11a..f774aa6 100644
--- a/third_party/SPIRV-Tools/source/opt/unify_const_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/unify_const_pass.cpp
@@ -25,7 +25,6 @@
 
 namespace spvtools {
 namespace opt {
-
 namespace {
 
 // The trie that stores a bunch of result ids and, for a given instruction,
@@ -103,7 +102,7 @@
 
   std::unique_ptr<Node> root_;  // The root node of the trie.
 };
-}  // anonymous namespace
+}  // namespace
 
 Pass::Status UnifyConstantPass::Process() {
   bool modified = false;
@@ -139,12 +138,12 @@
     // processing is up to a descendant. This makes comparing the key array
     // always valid for judging duplication.
     switch (inst->opcode()) {
-      case SpvOp::SpvOpConstantTrue:
-      case SpvOp::SpvOpConstantFalse:
-      case SpvOp::SpvOpConstant:
-      case SpvOp::SpvOpConstantNull:
-      case SpvOp::SpvOpConstantSampler:
-      case SpvOp::SpvOpConstantComposite:
+      case spv::Op::OpConstantTrue:
+      case spv::Op::OpConstantFalse:
+      case spv::Op::OpConstant:
+      case spv::Op::OpConstantNull:
+      case spv::Op::OpConstantSampler:
+      case spv::Op::OpConstantComposite:
       // Only spec constants defined with OpSpecConstantOp and
       // OpSpecConstantComposite should be processed in this pass. Spec
       // constants defined with OpSpecConstant{|True|False} are decorated with
@@ -154,8 +153,8 @@
       // unique. When all the operands/components are the same between two
       // OpSpecConstant{Op|Composite} results, their result values must be the
       // same so are unifiable.
-      case SpvOp::SpvOpSpecConstantOp:
-      case SpvOp::SpvOpSpecConstantComposite: {
+      case spv::Op::OpSpecConstantOp:
+      case spv::Op::OpSpecConstantComposite: {
         uint32_t id = defined_constants.LookupEquivalentResultFor(*inst);
         if (id != inst->result_id()) {
           // The constant is a duplicated one, use the cached constant to
diff --git a/third_party/SPIRV-Tools/source/opt/upgrade_memory_model.cpp b/third_party/SPIRV-Tools/source/opt/upgrade_memory_model.cpp
index 9d6a5bc..1b439a6 100644
--- a/third_party/SPIRV-Tools/source/opt/upgrade_memory_model.cpp
+++ b/third_party/SPIRV-Tools/source/opt/upgrade_memory_model.cpp
@@ -28,14 +28,16 @@
 Pass::Status UpgradeMemoryModel::Process() {
   // TODO: This pass needs changes to support cooperative matrices.
   if (context()->get_feature_mgr()->HasCapability(
-          SpvCapabilityCooperativeMatrixNV)) {
+          spv::Capability::CooperativeMatrixNV)) {
     return Pass::Status::SuccessWithoutChange;
   }
 
   // Only update Logical GLSL450 to Logical VulkanKHR.
   Instruction* memory_model = get_module()->GetMemoryModel();
-  if (memory_model->GetSingleWordInOperand(0u) != SpvAddressingModelLogical ||
-      memory_model->GetSingleWordInOperand(1u) != SpvMemoryModelGLSL450) {
+  if (memory_model->GetSingleWordInOperand(0u) !=
+          uint32_t(spv::AddressingModel::Logical) ||
+      memory_model->GetSingleWordInOperand(1u) !=
+          uint32_t(spv::MemoryModel::GLSL450)) {
     return Pass::Status::SuccessWithoutChange;
   }
 
@@ -55,16 +57,17 @@
   // 3. Modify the memory model.
   Instruction* memory_model = get_module()->GetMemoryModel();
   context()->AddCapability(MakeUnique<Instruction>(
-      context(), SpvOpCapability, 0, 0,
+      context(), spv::Op::OpCapability, 0, 0,
       std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityVulkanMemoryModelKHR}}}));
+          {SPV_OPERAND_TYPE_CAPABILITY,
+           {uint32_t(spv::Capability::VulkanMemoryModelKHR)}}}));
   const std::string extension = "SPV_KHR_vulkan_memory_model";
   std::vector<uint32_t> words = spvtools::utils::MakeVector(extension);
   context()->AddExtension(
-      MakeUnique<Instruction>(context(), SpvOpExtension, 0, 0,
+      MakeUnique<Instruction>(context(), spv::Op::OpExtension, 0, 0,
                               std::initializer_list<Operand>{
                                   {SPV_OPERAND_TYPE_LITERAL_STRING, words}}));
-  memory_model->SetInOperand(1u, {SpvMemoryModelVulkanKHR});
+  memory_model->SetInOperand(1u, {uint32_t(spv::MemoryModel::VulkanKHR)});
 }
 
 void UpgradeMemoryModel::UpgradeInstructions() {
@@ -79,7 +82,7 @@
   // In SPIR-V 1.4 or later, normalize OpCopyMemory* access operands.
   for (auto& func : *get_module()) {
     func.ForEachInst([this](Instruction* inst) {
-      if (inst->opcode() == SpvOpExtInst) {
+      if (inst->opcode() == spv::Op::OpExtInst) {
         auto ext_inst = inst->GetSingleWordInOperand(1u);
         if (ext_inst == GLSLstd450Modf || ext_inst == GLSLstd450Frexp) {
           auto import =
@@ -89,9 +92,10 @@
           }
         }
       } else if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
-        if (inst->opcode() == SpvOpCopyMemory ||
-            inst->opcode() == SpvOpCopyMemorySized) {
-          uint32_t start_operand = inst->opcode() == SpvOpCopyMemory ? 2u : 3u;
+        if (inst->opcode() == spv::Op::OpCopyMemory ||
+            inst->opcode() == spv::Op::OpCopyMemorySized) {
+          uint32_t start_operand =
+              inst->opcode() == spv::Op::OpCopyMemory ? 2u : 3u;
           if (inst->NumInOperands() > start_operand) {
             auto num_access_words = MemoryAccessNumWords(
                 inst->GetSingleWordInOperand(start_operand));
@@ -105,10 +109,10 @@
             }
           } else {
             // Add two memory access operands.
-            inst->AddOperand(
-                {SPV_OPERAND_TYPE_MEMORY_ACCESS, {SpvMemoryAccessMaskNone}});
-            inst->AddOperand(
-                {SPV_OPERAND_TYPE_MEMORY_ACCESS, {SpvMemoryAccessMaskNone}});
+            inst->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS,
+                              {uint32_t(spv::MemoryAccessMask::MaskNone)}});
+            inst->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS,
+                              {uint32_t(spv::MemoryAccessMask::MaskNone)}});
           }
         }
       }
@@ -129,23 +133,23 @@
       bool dst_coherent = false;
       bool dst_volatile = false;
       uint32_t start_operand = 0u;
-      SpvScope scope = SpvScopeQueueFamilyKHR;
-      SpvScope src_scope = SpvScopeQueueFamilyKHR;
-      SpvScope dst_scope = SpvScopeQueueFamilyKHR;
+      spv::Scope scope = spv::Scope::QueueFamilyKHR;
+      spv::Scope src_scope = spv::Scope::QueueFamilyKHR;
+      spv::Scope dst_scope = spv::Scope::QueueFamilyKHR;
       switch (inst->opcode()) {
-        case SpvOpLoad:
-        case SpvOpStore:
+        case spv::Op::OpLoad:
+        case spv::Op::OpStore:
           std::tie(is_coherent, is_volatile, scope) =
               GetInstructionAttributes(inst->GetSingleWordInOperand(0u));
           break;
-        case SpvOpImageRead:
-        case SpvOpImageSparseRead:
-        case SpvOpImageWrite:
+        case spv::Op::OpImageRead:
+        case spv::Op::OpImageSparseRead:
+        case spv::Op::OpImageWrite:
           std::tie(is_coherent, is_volatile, scope) =
               GetInstructionAttributes(inst->GetSingleWordInOperand(0u));
           break;
-        case SpvOpCopyMemory:
-        case SpvOpCopyMemorySized:
+        case spv::Op::OpCopyMemory:
+        case spv::Op::OpCopyMemorySized:
           std::tie(dst_coherent, dst_volatile, dst_scope) =
               GetInstructionAttributes(inst->GetSingleWordInOperand(0u));
           std::tie(src_coherent, src_volatile, src_scope) =
@@ -156,17 +160,17 @@
       }
 
       switch (inst->opcode()) {
-        case SpvOpLoad:
+        case spv::Op::OpLoad:
           UpgradeFlags(inst, 1u, is_coherent, is_volatile, kVisibility,
                        kMemory);
           break;
-        case SpvOpStore:
+        case spv::Op::OpStore:
           UpgradeFlags(inst, 2u, is_coherent, is_volatile, kAvailability,
                        kMemory);
           break;
-        case SpvOpCopyMemory:
-        case SpvOpCopyMemorySized:
-          start_operand = inst->opcode() == SpvOpCopyMemory ? 2u : 3u;
+        case spv::Op::OpCopyMemory:
+        case spv::Op::OpCopyMemorySized:
+          start_operand = inst->opcode() == spv::Op::OpCopyMemory ? 2u : 3u;
           if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
             // There are guaranteed to be two memory access operands at this
             // point so treat source and target separately.
@@ -183,11 +187,11 @@
                          kVisibility, kMemory);
           }
           break;
-        case SpvOpImageRead:
-        case SpvOpImageSparseRead:
+        case spv::Op::OpImageRead:
+        case spv::Op::OpImageSparseRead:
           UpgradeFlags(inst, 2u, is_coherent, is_volatile, kVisibility, kImage);
           break;
-        case SpvOpImageWrite:
+        case spv::Op::OpImageWrite:
           UpgradeFlags(inst, 3u, is_coherent, is_volatile, kAvailability,
                        kImage);
           break;
@@ -205,7 +209,7 @@
         // There are two memory access operands. The first is for the target and
         // the second is for the source.
         if (dst_coherent || src_coherent) {
-          start_operand = inst->opcode() == SpvOpCopyMemory ? 2u : 3u;
+          start_operand = inst->opcode() == spv::Op::OpCopyMemory ? 2u : 3u;
           std::vector<Operand> new_operands;
           uint32_t num_access_words =
               MemoryAccessNumWords(inst->GetSingleWordInOperand(start_operand));
@@ -255,13 +259,13 @@
       if (spvOpcodeIsAtomicOp(inst->opcode())) {
         bool unused_coherent = false;
         bool is_volatile = false;
-        SpvScope unused_scope = SpvScopeQueueFamilyKHR;
+        spv::Scope unused_scope = spv::Scope::QueueFamilyKHR;
         std::tie(unused_coherent, is_volatile, unused_scope) =
             GetInstructionAttributes(inst->GetSingleWordInOperand(0));
 
         UpgradeSemantics(inst, 2u, is_volatile);
-        if (inst->opcode() == SpvOpAtomicCompareExchange ||
-            inst->opcode() == SpvOpAtomicCompareExchangeWeak) {
+        if (inst->opcode() == spv::Op::OpAtomicCompareExchange ||
+            inst->opcode() == spv::Op::OpAtomicCompareExchangeWeak) {
           UpgradeSemantics(inst, 3u, is_volatile);
         }
       }
@@ -286,14 +290,14 @@
     value = constant->GetU32();
   }
 
-  value |= SpvMemorySemanticsVolatileMask;
+  value |= uint32_t(spv::MemorySemanticsMask::Volatile);
   auto new_constant = context()->get_constant_mgr()->GetConstant(type, {value});
   auto new_semantics =
       context()->get_constant_mgr()->GetDefiningInstruction(new_constant);
   inst->SetInOperand(in_operand, {new_semantics->result_id()});
 }
 
-std::tuple<bool, bool, SpvScope> UpgradeMemoryModel::GetInstructionAttributes(
+std::tuple<bool, bool, spv::Scope> UpgradeMemoryModel::GetInstructionAttributes(
     uint32_t id) {
   // |id| is a pointer used in a memory/image instruction. Need to determine if
   // that pointer points to volatile or coherent memory. Workgroup storage
@@ -302,8 +306,8 @@
   Instruction* inst = context()->get_def_use_mgr()->GetDef(id);
   analysis::Type* type = context()->get_type_mgr()->GetType(inst->type_id());
   if (type->AsPointer() &&
-      type->AsPointer()->storage_class() == SpvStorageClassWorkgroup) {
-    return std::make_tuple(true, false, SpvScopeWorkgroup);
+      type->AsPointer()->storage_class() == spv::StorageClass::Workgroup) {
+    return std::make_tuple(true, false, spv::Scope::Workgroup);
   }
 
   bool is_coherent = false;
@@ -313,7 +317,7 @@
       TraceInstruction(context()->get_def_use_mgr()->GetDef(id),
                        std::vector<uint32_t>(), &visited);
 
-  return std::make_tuple(is_coherent, is_volatile, SpvScopeQueueFamilyKHR);
+  return std::make_tuple(is_coherent, is_volatile, spv::Scope::QueueFamilyKHR);
 }
 
 std::pair<bool, bool> UpgradeMemoryModel::TraceInstruction(
@@ -336,10 +340,10 @@
   bool is_coherent = false;
   bool is_volatile = false;
   switch (inst->opcode()) {
-    case SpvOpVariable:
-    case SpvOpFunctionParameter:
-      is_coherent |= HasDecoration(inst, 0, SpvDecorationCoherent);
-      is_volatile |= HasDecoration(inst, 0, SpvDecorationVolatile);
+    case spv::Op::OpVariable:
+    case spv::Op::OpFunctionParameter:
+      is_coherent |= HasDecoration(inst, 0, spv::Decoration::Coherent);
+      is_volatile |= HasDecoration(inst, 0, spv::Decoration::Volatile);
       if (!is_coherent || !is_volatile) {
         bool type_coherent = false;
         bool type_volatile = false;
@@ -349,14 +353,14 @@
         is_volatile |= type_volatile;
       }
       break;
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
       // Store indices in reverse order.
       for (uint32_t i = inst->NumInOperands() - 1; i > 0; --i) {
         indices.push_back(inst->GetSingleWordInOperand(i));
       }
       break;
-    case SpvOpPtrAccessChain:
+    case spv::Op::OpPtrAccessChain:
       // Store indices in reverse order. Skip the |Element| operand.
       for (uint32_t i = inst->NumInOperands() - 1; i > 1; --i) {
         indices.push_back(inst->GetSingleWordInOperand(i));
@@ -375,8 +379,8 @@
 
   // Variables and function parameters are sources. Continue searching until we
   // reach them.
-  if (inst->opcode() != SpvOpVariable &&
-      inst->opcode() != SpvOpFunctionParameter) {
+  if (inst->opcode() != spv::Op::OpVariable &&
+      inst->opcode() != spv::Op::OpFunctionParameter) {
     inst->ForEachInId([this, &is_coherent, &is_volatile, &indices,
                        &visited](const uint32_t* id_ptr) {
       Instruction* op_inst = context()->get_def_use_mgr()->GetDef(*id_ptr);
@@ -404,24 +408,24 @@
   bool is_coherent = false;
   bool is_volatile = false;
   Instruction* type_inst = context()->get_def_use_mgr()->GetDef(type_id);
-  assert(type_inst->opcode() == SpvOpTypePointer);
+  assert(type_inst->opcode() == spv::Op::OpTypePointer);
   Instruction* element_inst = context()->get_def_use_mgr()->GetDef(
       type_inst->GetSingleWordInOperand(1u));
   for (int i = (int)indices.size() - 1; i >= 0; --i) {
     if (is_coherent && is_volatile) break;
 
-    if (element_inst->opcode() == SpvOpTypePointer) {
+    if (element_inst->opcode() == spv::Op::OpTypePointer) {
       element_inst = context()->get_def_use_mgr()->GetDef(
           element_inst->GetSingleWordInOperand(1u));
-    } else if (element_inst->opcode() == SpvOpTypeStruct) {
+    } else if (element_inst->opcode() == spv::Op::OpTypeStruct) {
       uint32_t index = indices.at(i);
       Instruction* index_inst = context()->get_def_use_mgr()->GetDef(index);
-      assert(index_inst->opcode() == SpvOpConstant);
+      assert(index_inst->opcode() == spv::Op::OpConstant);
       uint64_t value = GetIndexValue(index_inst);
       is_coherent |= HasDecoration(element_inst, static_cast<uint32_t>(value),
-                                   SpvDecorationCoherent);
+                                   spv::Decoration::Coherent);
       is_volatile |= HasDecoration(element_inst, static_cast<uint32_t>(value),
-                                   SpvDecorationVolatile);
+                                   spv::Decoration::Volatile);
       element_inst = context()->get_def_use_mgr()->GetDef(
           element_inst->GetSingleWordInOperand(static_cast<uint32_t>(value)));
     } else {
@@ -457,13 +461,13 @@
 
     if (!visited.insert(def).second) continue;
 
-    if (def->opcode() == SpvOpTypeStruct) {
+    if (def->opcode() == spv::Op::OpTypeStruct) {
       // Any member decorated with coherent and/or volatile is enough to have
       // the related operation be flagged as coherent and/or volatile.
       is_coherent |= HasDecoration(def, std::numeric_limits<uint32_t>::max(),
-                                   SpvDecorationCoherent);
+                                   spv::Decoration::Coherent);
       is_volatile |= HasDecoration(def, std::numeric_limits<uint32_t>::max(),
-                                   SpvDecorationVolatile);
+                                   spv::Decoration::Volatile);
       if (is_coherent && is_volatile)
         return std::make_pair(is_coherent, is_volatile);
 
@@ -475,7 +479,7 @@
     } else if (spvOpcodeIsComposite(def->opcode())) {
       stack.push_back(context()->get_def_use_mgr()->GetDef(
           def->GetSingleWordInOperand(0u)));
-    } else if (def->opcode() == SpvOpTypePointer) {
+    } else if (def->opcode() == spv::Op::OpTypePointer) {
       stack.push_back(context()->get_def_use_mgr()->GetDef(
           def->GetSingleWordInOperand(1u)));
     }
@@ -504,14 +508,15 @@
 }
 
 bool UpgradeMemoryModel::HasDecoration(const Instruction* inst, uint32_t value,
-                                       SpvDecoration decoration) {
+                                       spv::Decoration decoration) {
   // If the iteration was terminated early then an appropriate decoration was
   // found.
   return !context()->get_decoration_mgr()->WhileEachDecoration(
-      inst->result_id(), decoration, [value](const Instruction& i) {
-        if (i.opcode() == SpvOpDecorate || i.opcode() == SpvOpDecorateId) {
+      inst->result_id(), (uint32_t)decoration, [value](const Instruction& i) {
+        if (i.opcode() == spv::Op::OpDecorate ||
+            i.opcode() == spv::Op::OpDecorateId) {
           return false;
-        } else if (i.opcode() == SpvOpMemberDecorate) {
+        } else if (i.opcode() == spv::Op::OpMemberDecorate) {
           if (value == i.GetSingleWordInOperand(1u) ||
               value == std::numeric_limits<uint32_t>::max())
             return false;
@@ -533,27 +538,27 @@
   }
   if (is_coherent) {
     if (inst_type == kMemory) {
-      flags |= SpvMemoryAccessNonPrivatePointerKHRMask;
+      flags |= uint32_t(spv::MemoryAccessMask::NonPrivatePointerKHR);
       if (operation_type == kVisibility) {
-        flags |= SpvMemoryAccessMakePointerVisibleKHRMask;
+        flags |= uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR);
       } else {
-        flags |= SpvMemoryAccessMakePointerAvailableKHRMask;
+        flags |= uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR);
       }
     } else {
-      flags |= SpvImageOperandsNonPrivateTexelKHRMask;
+      flags |= uint32_t(spv::ImageOperandsMask::NonPrivateTexelKHR);
       if (operation_type == kVisibility) {
-        flags |= SpvImageOperandsMakeTexelVisibleKHRMask;
+        flags |= uint32_t(spv::ImageOperandsMask::MakeTexelVisibleKHR);
       } else {
-        flags |= SpvImageOperandsMakeTexelAvailableKHRMask;
+        flags |= uint32_t(spv::ImageOperandsMask::MakeTexelAvailableKHR);
       }
     }
   }
 
   if (is_volatile) {
     if (inst_type == kMemory) {
-      flags |= SpvMemoryAccessVolatileMask;
+      flags |= uint32_t(spv::MemoryAccessMask::Volatile);
     } else {
-      flags |= SpvImageOperandsVolatileTexelKHRMask;
+      flags |= uint32_t(spv::ImageOperandsMask::VolatileTexelKHR);
     }
   }
 
@@ -566,7 +571,7 @@
   }
 }
 
-uint32_t UpgradeMemoryModel::GetScopeConstant(SpvScope scope) {
+uint32_t UpgradeMemoryModel::GetScopeConstant(spv::Scope scope) {
   analysis::Integer int_ty(32, false);
   uint32_t int_id = context()->get_type_mgr()->GetTypeInstruction(&int_ty);
   const analysis::Constant* constant =
@@ -587,15 +592,19 @@
       context()->get_decoration_mgr()->RemoveDecorationsFrom(
           inst->result_id(), [](const Instruction& dec) {
             switch (dec.opcode()) {
-              case SpvOpDecorate:
-              case SpvOpDecorateId:
-                if (dec.GetSingleWordInOperand(1u) == SpvDecorationCoherent ||
-                    dec.GetSingleWordInOperand(1u) == SpvDecorationVolatile)
+              case spv::Op::OpDecorate:
+              case spv::Op::OpDecorateId:
+                if (spv::Decoration(dec.GetSingleWordInOperand(1u)) ==
+                        spv::Decoration::Coherent ||
+                    spv::Decoration(dec.GetSingleWordInOperand(1u)) ==
+                        spv::Decoration::Volatile)
                   return true;
                 break;
-              case SpvOpMemberDecorate:
-                if (dec.GetSingleWordInOperand(2u) == SpvDecorationCoherent ||
-                    dec.GetSingleWordInOperand(2u) == SpvDecorationVolatile)
+              case spv::Op::OpMemberDecorate:
+                if (spv::Decoration(dec.GetSingleWordInOperand(2u)) ==
+                        spv::Decoration::Coherent ||
+                    spv::Decoration(dec.GetSingleWordInOperand(2u)) ==
+                        spv::Decoration::Volatile)
                   return true;
                 break;
               default:
@@ -616,7 +625,7 @@
     for (auto& block : *function) {
       block.ForEachInst([this, &barriers,
                          &operates_on_output](Instruction* inst) {
-        if (inst->opcode() == SpvOpControlBarrier) {
+        if (inst->opcode() == spv::Op::OpControlBarrier) {
           barriers.push_back(inst);
         } else if (!operates_on_output) {
           // This instruction operates on output storage class if it is a
@@ -625,7 +634,7 @@
           analysis::Type* type =
               context()->get_type_mgr()->GetType(inst->type_id());
           if (type && type->AsPointer() &&
-              type->AsPointer()->storage_class() == SpvStorageClassOutput) {
+              type->AsPointer()->storage_class() == spv::StorageClass::Output) {
             operates_on_output = true;
             return;
           }
@@ -635,7 +644,8 @@
             analysis::Type* op_type =
                 context()->get_type_mgr()->GetType(op_inst->type_id());
             if (op_type && op_type->AsPointer() &&
-                op_type->AsPointer()->storage_class() == SpvStorageClassOutput)
+                op_type->AsPointer()->storage_class() ==
+                    spv::StorageClass::Output)
               operates_on_output = true;
           });
         }
@@ -646,7 +656,8 @@
 
   std::queue<uint32_t> roots;
   for (auto& e : get_module()->entry_points())
-    if (e.GetSingleWordInOperand(0u) == SpvExecutionModelTessellationControl) {
+    if (spv::ExecutionModel(e.GetSingleWordInOperand(0u)) ==
+        spv::ExecutionModel::TessellationControl) {
       roots.push(e.GetSingleWordInOperand(1u));
       if (context()->ProcessCallTreeFromRoots(CollectBarriers, &roots)) {
         for (auto barrier : barriers) {
@@ -659,8 +670,9 @@
           uint64_t semantics_value = GetIndexValue(semantics_inst);
           const analysis::Constant* constant =
               context()->get_constant_mgr()->GetConstant(
-                  semantics_type, {static_cast<uint32_t>(semantics_value) |
-                                   SpvMemorySemanticsOutputMemoryKHRMask});
+                  semantics_type,
+                  {static_cast<uint32_t>(semantics_value) |
+                   uint32_t(spv::MemorySemanticsMask::OutputMemoryKHR)});
           barrier->SetInOperand(2u, {context()
                                          ->get_constant_mgr()
                                          ->GetDefiningInstruction(constant)
@@ -680,15 +692,15 @@
     // * Workgroup ops (e.g. async_copy) have at most workgroup scope.
     if (spvOpcodeIsAtomicOp(inst->opcode())) {
       if (IsDeviceScope(inst->GetSingleWordInOperand(1))) {
-        inst->SetInOperand(1, {GetScopeConstant(SpvScopeQueueFamilyKHR)});
+        inst->SetInOperand(1, {GetScopeConstant(spv::Scope::QueueFamilyKHR)});
       }
-    } else if (inst->opcode() == SpvOpControlBarrier) {
+    } else if (inst->opcode() == spv::Op::OpControlBarrier) {
       if (IsDeviceScope(inst->GetSingleWordInOperand(1))) {
-        inst->SetInOperand(1, {GetScopeConstant(SpvScopeQueueFamilyKHR)});
+        inst->SetInOperand(1, {GetScopeConstant(spv::Scope::QueueFamilyKHR)});
       }
-    } else if (inst->opcode() == SpvOpMemoryBarrier) {
+    } else if (inst->opcode() == spv::Op::OpMemoryBarrier) {
       if (IsDeviceScope(inst->GetSingleWordInOperand(0))) {
-        inst->SetInOperand(0, {GetScopeConstant(SpvScopeQueueFamilyKHR)});
+        inst->SetInOperand(0, {GetScopeConstant(spv::Scope::QueueFamilyKHR)});
       }
     }
   });
@@ -704,14 +716,14 @@
   assert(type->width() == 32 || type->width() == 64);
   if (type->width() == 32) {
     if (type->IsSigned())
-      return static_cast<uint32_t>(constant->GetS32()) == SpvScopeDevice;
+      return static_cast<spv::Scope>(constant->GetS32()) == spv::Scope::Device;
     else
-      return static_cast<uint32_t>(constant->GetU32()) == SpvScopeDevice;
+      return static_cast<spv::Scope>(constant->GetU32()) == spv::Scope::Device;
   } else {
     if (type->IsSigned())
-      return static_cast<uint32_t>(constant->GetS64()) == SpvScopeDevice;
+      return static_cast<spv::Scope>(constant->GetS64()) == spv::Scope::Device;
     else
-      return static_cast<uint32_t>(constant->GetU64()) == SpvScopeDevice;
+      return static_cast<spv::Scope>(constant->GetU64()) == spv::Scope::Device;
   }
 
   assert(false);
@@ -758,9 +770,9 @@
 
 uint32_t UpgradeMemoryModel::MemoryAccessNumWords(uint32_t mask) {
   uint32_t result = 1;
-  if (mask & SpvMemoryAccessAlignedMask) ++result;
-  if (mask & SpvMemoryAccessMakePointerAvailableKHRMask) ++result;
-  if (mask & SpvMemoryAccessMakePointerVisibleKHRMask) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::Aligned)) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR)) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR)) ++result;
   return result;
 }
 
diff --git a/third_party/SPIRV-Tools/source/opt/upgrade_memory_model.h b/third_party/SPIRV-Tools/source/opt/upgrade_memory_model.h
index f75304e..489436b 100644
--- a/third_party/SPIRV-Tools/source/opt/upgrade_memory_model.h
+++ b/third_party/SPIRV-Tools/source/opt/upgrade_memory_model.h
@@ -71,7 +71,7 @@
   void UpgradeAtomics();
 
   // Returns whether |id| is coherent and/or volatile.
-  std::tuple<bool, bool, SpvScope> GetInstructionAttributes(uint32_t id);
+  std::tuple<bool, bool, spv::Scope> GetInstructionAttributes(uint32_t id);
 
   // Traces |inst| to determine if it is coherent and/or volatile.
   // |indices| tracks the access chain indices seen so far.
@@ -84,7 +84,7 @@
   // match the index or |value| must be a maximum allowable value. The max
   // value allows any element to match.
   bool HasDecoration(const Instruction* inst, uint32_t value,
-                     SpvDecoration decoration);
+                     spv::Decoration decoration);
 
   // Returns whether |type_id| indexed via |indices| is coherent and/or
   // volatile.
@@ -108,7 +108,7 @@
                         bool is_volatile);
 
   // Returns the result id for a constant for |scope|.
-  uint32_t GetScopeConstant(SpvScope scope);
+  uint32_t GetScopeConstant(spv::Scope scope);
 
   // Returns the value of |index_inst|. |index_inst| must be an OpConstant of
   // integer type.g
@@ -127,7 +127,7 @@
   // scope.
   void UpgradeMemoryScope();
 
-  // Returns true if |scope_id| is SpvScopeDevice.
+  // Returns true if |scope_id| is spv::Scope::Device.
   bool IsDeviceScope(uint32_t scope_id);
 
   // Upgrades GLSL.std.450 modf and frexp. Both instructions are replaced with
diff --git a/third_party/SPIRV-Tools/source/opt/value_number_table.cpp b/third_party/SPIRV-Tools/source/opt/value_number_table.cpp
index 5271e3f..743dc52 100644
--- a/third_party/SPIRV-Tools/source/opt/value_number_table.cpp
+++ b/third_party/SPIRV-Tools/source/opt/value_number_table.cpp
@@ -57,9 +57,9 @@
   }
 
   switch (inst->opcode()) {
-    case SpvOpSampledImage:
-    case SpvOpImage:
-    case SpvOpVariable:
+    case spv::Op::OpSampledImage:
+    case spv::Op::OpImage:
+    case spv::Op::OpVariable:
       value = TakeNextValueNumber();
       id_to_value_[inst->result_id()] = value;
       return value;
@@ -82,7 +82,7 @@
   analysis::DecorationManager* dec_mgr = context()->get_decoration_mgr();
 
   // When we copy an object, the value numbers should be the same.
-  if (inst->opcode() == SpvOpCopyObject &&
+  if (inst->opcode() == spv::Op::OpCopyObject &&
       dec_mgr->HaveTheSameDecorations(inst->result_id(),
                                       inst->GetSingleWordInOperand(0))) {
     value = GetValueNumber(inst->GetSingleWordInOperand(0));
@@ -94,7 +94,7 @@
 
   // Phi nodes are a type of copy.  If all of the inputs have the same value
   // number, then we can assign the result of the phi the same value number.
-  if (inst->opcode() == SpvOpPhi && inst->NumInOperands() > 0 &&
+  if (inst->opcode() == spv::Op::OpPhi && inst->NumInOperands() > 0 &&
       dec_mgr->HaveTheSameDecorations(inst->result_id(),
                                       inst->GetSingleWordInOperand(0))) {
     value = GetValueNumber(inst->GetSingleWordInOperand(0));
@@ -226,7 +226,7 @@
   // instructions that are the same except for the result to hash to the
   // same value.
   std::u32string h;
-  h.push_back(inst.opcode());
+  h.push_back(uint32_t(inst.opcode()));
   h.push_back(inst.type_id());
   for (uint32_t i = 0; i < inst.NumInOperands(); ++i) {
     const auto& opnd = inst.GetInOperand(i);
diff --git a/third_party/SPIRV-Tools/source/opt/vector_dce.cpp b/third_party/SPIRV-Tools/source/opt/vector_dce.cpp
index 28d94a0..1e8d255 100644
--- a/third_party/SPIRV-Tools/source/opt/vector_dce.cpp
+++ b/third_party/SPIRV-Tools/source/opt/vector_dce.cpp
@@ -19,11 +19,9 @@
 namespace spvtools {
 namespace opt {
 namespace {
-
-const uint32_t kExtractCompositeIdInIdx = 0;
-const uint32_t kInsertObjectIdInIdx = 0;
-const uint32_t kInsertCompositeIdInIdx = 1;
-
+constexpr uint32_t kExtractCompositeIdInIdx = 0;
+constexpr uint32_t kInsertObjectIdInIdx = 0;
+constexpr uint32_t kInsertCompositeIdInIdx = 1;
 }  // namespace
 
 Pass::Status VectorDCE::Process() {
@@ -68,17 +66,17 @@
     Instruction* current_inst = current_item.instruction;
 
     switch (current_inst->opcode()) {
-      case SpvOpCompositeExtract:
+      case spv::Op::OpCompositeExtract:
         MarkExtractUseAsLive(current_inst, current_item.components,
                              live_components, &work_list);
         break;
-      case SpvOpCompositeInsert:
+      case spv::Op::OpCompositeInsert:
         MarkInsertUsesAsLive(current_item, live_components, &work_list);
         break;
-      case SpvOpVectorShuffle:
+      case spv::Op::OpVectorShuffle:
         MarkVectorShuffleUsesAsLive(current_item, live_components, &work_list);
         break;
-      case SpvOpCompositeConstruct:
+      case spv::Op::OpCompositeConstruct:
         MarkCompositeContructUsesAsLive(current_item, live_components,
                                         &work_list);
         break;
@@ -347,11 +345,11 @@
     }
 
     switch (current_inst->opcode()) {
-      case SpvOpCompositeInsert:
+      case spv::Op::OpCompositeInsert:
         modified |= RewriteInsertInstruction(
             current_inst, live_component->second, &dead_dbg_value);
         break;
-      case SpvOpCompositeConstruct:
+      case spv::Op::OpCompositeConstruct:
         // TODO: The members that are not live can be replaced by an undef
         // or constant. This will remove uses of those values, and possibly
         // create opportunities for ADCE.
diff --git a/third_party/SPIRV-Tools/source/opt/workaround1209.cpp b/third_party/SPIRV-Tools/source/opt/workaround1209.cpp
index d6e9d2c..0cf954a 100644
--- a/third_party/SPIRV-Tools/source/opt/workaround1209.cpp
+++ b/third_party/SPIRV-Tools/source/opt/workaround1209.cpp
@@ -43,13 +43,13 @@
         loop_merges.pop();
       }
 
-      if (bb->tail()->opcode() == SpvOpUnreachable) {
+      if (bb->tail()->opcode() == spv::Op::OpUnreachable) {
         if (!loop_merges.empty()) {
           // We found an OpUnreachable inside a loop.
           // Replace it with an unconditional branch to the loop merge.
           context()->KillInst(&*bb->tail());
           std::unique_ptr<Instruction> new_branch(
-              new Instruction(context(), SpvOpBranch, 0, 0,
+              new Instruction(context(), spv::Op::OpBranch, 0, 0,
                               {{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
                                 {loop_merges.top()}}}));
           context()->AnalyzeDefUse(&*new_branch);
diff --git a/third_party/SPIRV-Tools/source/opt/wrap_opkill.cpp b/third_party/SPIRV-Tools/source/opt/wrap_opkill.cpp
index 51432a7..c0c6d62 100644
--- a/third_party/SPIRV-Tools/source/opt/wrap_opkill.cpp
+++ b/third_party/SPIRV-Tools/source/opt/wrap_opkill.cpp
@@ -28,7 +28,8 @@
     Function* func = context()->GetFunction(func_id);
     bool successful = func->WhileEachInst([this, &modified](Instruction* inst) {
       const auto opcode = inst->opcode();
-      if ((opcode == SpvOpKill) || (opcode == SpvOpTerminateInvocation)) {
+      if ((opcode == spv::Op::OpKill) ||
+          (opcode == spv::Op::OpTerminateInvocation)) {
         modified = true;
         if (!ReplaceWithFunctionCall(inst)) {
           return false;
@@ -56,8 +57,8 @@
 }
 
 bool WrapOpKill::ReplaceWithFunctionCall(Instruction* inst) {
-  assert((inst->opcode() == SpvOpKill ||
-          inst->opcode() == SpvOpTerminateInvocation) &&
+  assert((inst->opcode() == spv::Op::OpKill ||
+          inst->opcode() == spv::Op::OpTerminateInvocation) &&
          "|inst| must be an OpKill or OpTerminateInvocation instruction.");
   InstructionBuilder ir_builder(
       context(), inst,
@@ -76,14 +77,15 @@
   Instruction* return_inst = nullptr;
   uint32_t return_type_id = GetOwningFunctionsReturnType(inst);
   if (return_type_id != GetVoidTypeId()) {
-    Instruction* undef = ir_builder.AddNullaryOp(return_type_id, SpvOpUndef);
+    Instruction* undef =
+        ir_builder.AddNullaryOp(return_type_id, spv::Op::OpUndef);
     if (undef == nullptr) {
       return false;
     }
     return_inst =
-        ir_builder.AddUnaryOp(0, SpvOpReturnValue, undef->result_id());
+        ir_builder.AddUnaryOp(0, spv::Op::OpReturnValue, undef->result_id());
   } else {
-    return_inst = ir_builder.AddNullaryOp(0, SpvOpReturn);
+    return_inst = ir_builder.AddNullaryOp(0, spv::Op::OpReturn);
   }
 
   if (return_inst == nullptr) {
@@ -115,13 +117,13 @@
   return type_mgr->GetTypeInstruction(&func_type);
 }
 
-uint32_t WrapOpKill::GetKillingFuncId(SpvOp opcode) {
+uint32_t WrapOpKill::GetKillingFuncId(spv::Op opcode) {
   //  Parameterize by opcode
-  assert(opcode == SpvOpKill || opcode == SpvOpTerminateInvocation);
+  assert(opcode == spv::Op::OpKill || opcode == spv::Op::OpTerminateInvocation);
 
   std::unique_ptr<Function>* const killing_func =
-      (opcode == SpvOpKill) ? &opkill_function_
-                            : &opterminateinvocation_function_;
+      (opcode == spv::Op::OpKill) ? &opkill_function_
+                                  : &opterminateinvocation_function_;
 
   if (*killing_func != nullptr) {
     return (*killing_func)->result_id();
@@ -139,14 +141,14 @@
 
   // Generate the function start instruction
   std::unique_ptr<Instruction> func_start(new Instruction(
-      context(), SpvOpFunction, void_type_id, killing_func_id, {}));
+      context(), spv::Op::OpFunction, void_type_id, killing_func_id, {}));
   func_start->AddOperand({SPV_OPERAND_TYPE_FUNCTION_CONTROL, {0}});
   func_start->AddOperand({SPV_OPERAND_TYPE_ID, {GetVoidFunctionTypeId()}});
   (*killing_func).reset(new Function(std::move(func_start)));
 
   // Generate the function end instruction
   std::unique_ptr<Instruction> func_end(
-      new Instruction(context(), SpvOpFunctionEnd, 0, 0, {}));
+      new Instruction(context(), spv::Op::OpFunctionEnd, 0, 0, {}));
   (*killing_func)->SetFunctionEnd(std::move(func_end));
 
   // Create the one basic block for the function.
@@ -155,7 +157,7 @@
     return 0;
   }
   std::unique_ptr<Instruction> label_inst(
-      new Instruction(context(), SpvOpLabel, 0, lab_id, {}));
+      new Instruction(context(), spv::Op::OpLabel, 0, lab_id, {}));
   std::unique_ptr<BasicBlock> bb(new BasicBlock(std::move(label_inst)));
 
   // Add the OpKill to the basic block
diff --git a/third_party/SPIRV-Tools/source/opt/wrap_opkill.h b/third_party/SPIRV-Tools/source/opt/wrap_opkill.h
index 7e43ca6..c9eb888 100644
--- a/third_party/SPIRV-Tools/source/opt/wrap_opkill.h
+++ b/third_party/SPIRV-Tools/source/opt/wrap_opkill.h
@@ -53,7 +53,7 @@
   // Return the id of a function that has return type void, has no parameters,
   // and contains a single instruction, which is |opcode|, either OpKill or
   // OpTerminateInvocation.  Returns 0 if the function could not be generated.
-  uint32_t GetKillingFuncId(SpvOp opcode);
+  uint32_t GetKillingFuncId(spv::Op opcode);
 
   // Returns the id of the return type for the function that contains |inst|.
   // Returns 0 if |inst| is not in a function.
diff --git a/third_party/SPIRV-Tools/source/print.cpp b/third_party/SPIRV-Tools/source/print.cpp
index 2418c5b..6c94e2b 100644
--- a/third_party/SPIRV-Tools/source/print.cpp
+++ b/third_party/SPIRV-Tools/source/print.cpp
@@ -16,7 +16,8 @@
 
 #if defined(SPIRV_ANDROID) || defined(SPIRV_LINUX) || defined(SPIRV_MAC) || \
     defined(SPIRV_IOS) || defined(SPIRV_TVOS) || defined(SPIRV_FREEBSD) ||  \
-    defined(SPIRV_EMSCRIPTEN) || defined(SPIRV_FUCHSIA)
+    defined(SPIRV_OPENBSD) || defined(SPIRV_EMSCRIPTEN) ||                  \
+    defined(SPIRV_FUCHSIA) || defined(SPIRV_GNU)
 namespace spvtools {
 
 clr::reset::operator const char*() { return "\x1b[0m"; }
diff --git a/third_party/SPIRV-Tools/source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp b/third_party/SPIRV-Tools/source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp
index 2cd779a..93b51a1 100644
--- a/third_party/SPIRV-Tools/source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp
@@ -36,9 +36,9 @@
     for (auto* function : GetTargetFunctions(context, target_function)) {
       // Consider every block in the function.
       for (auto& block : *function) {
-        // The terminator must be SpvOpBranchConditional.
+        // The terminator must be spv::Op::OpBranchConditional.
         opt::Instruction* terminator = block.terminator();
-        if (terminator->opcode() != SpvOpBranchConditional) {
+        if (terminator->opcode() != spv::Op::OpBranchConditional) {
           continue;
         }
 
diff --git a/third_party/SPIRV-Tools/source/reduce/merge_blocks_reduction_opportunity.cpp b/third_party/SPIRV-Tools/source/reduce/merge_blocks_reduction_opportunity.cpp
index a2c3b40..e626d60 100644
--- a/third_party/SPIRV-Tools/source/reduce/merge_blocks_reduction_opportunity.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/merge_blocks_reduction_opportunity.cpp
@@ -23,7 +23,7 @@
 MergeBlocksReductionOpportunity::MergeBlocksReductionOpportunity(
     opt::IRContext* context, opt::Function* function, opt::BasicBlock* block) {
   // Precondition: the terminator has to be OpBranch.
-  assert(block->terminator()->opcode() == SpvOpBranch);
+  assert(block->terminator()->opcode() == spv::Op::OpBranch);
   context_ = context;
   function_ = function;
   // Get the successor block associated with the OpBranch.
diff --git a/third_party/SPIRV-Tools/source/reduce/operand_to_const_reduction_opportunity_finder.cpp b/third_party/SPIRV-Tools/source/reduce/operand_to_const_reduction_opportunity_finder.cpp
index eb7498a..c6196f3 100644
--- a/third_party/SPIRV-Tools/source/reduce/operand_to_const_reduction_opportunity_finder.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/operand_to_const_reduction_opportunity_finder.cpp
@@ -50,7 +50,7 @@
                 // The argument is already a constant.
                 continue;
               }
-              if (def->opcode() == SpvOpFunction) {
+              if (def->opcode() == spv::Op::OpFunction) {
                 // The argument refers to a function, e.g. the function called
                 // by OpFunctionCall; avoid replacing this with a constant of
                 // the function's return type.
diff --git a/third_party/SPIRV-Tools/source/reduce/operand_to_undef_reduction_opportunity_finder.cpp b/third_party/SPIRV-Tools/source/reduce/operand_to_undef_reduction_opportunity_finder.cpp
index 06bf955..c7bc121 100644
--- a/third_party/SPIRV-Tools/source/reduce/operand_to_undef_reduction_opportunity_finder.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/operand_to_undef_reduction_opportunity_finder.cpp
@@ -32,7 +32,7 @@
         auto type_id = inst.type_id();
         if (type_id) {
           auto type_id_def = context->get_def_use_mgr()->GetDef(type_id);
-          if (type_id_def->opcode() == SpvOpTypePointer) {
+          if (type_id_def->opcode() == spv::Op::OpTypePointer) {
             continue;
           }
         }
@@ -57,7 +57,7 @@
             }
 
             // Don't replace function operands with undef.
-            if (operand_id_def->opcode() == SpvOpFunction) {
+            if (operand_id_def->opcode() == spv::Op::OpFunction) {
               continue;
             }
 
@@ -68,7 +68,7 @@
                   context->get_def_use_mgr()->GetDef(operand_type_id);
 
               // Skip pointer operands.
-              if (operand_type_id_def->opcode() == SpvOpTypePointer) {
+              if (operand_type_id_def->opcode() == spv::Op::OpTypePointer) {
                 continue;
               }
 
diff --git a/third_party/SPIRV-Tools/source/reduce/reduction_util.cpp b/third_party/SPIRV-Tools/source/reduce/reduction_util.cpp
index 511f432..c9882d5 100644
--- a/third_party/SPIRV-Tools/source/reduce/reduction_util.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/reduction_util.cpp
@@ -26,7 +26,7 @@
 uint32_t FindOrCreateGlobalVariable(opt::IRContext* context,
                                     uint32_t pointer_type_id) {
   for (auto& inst : context->module()->types_values()) {
-    if (inst.opcode() != SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       continue;
     }
     if (inst.type_id() == pointer_type_id) {
@@ -35,7 +35,7 @@
   }
   const uint32_t variable_id = context->TakeNextId();
   auto variable_inst = MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, pointer_type_id, variable_id,
+      context, spv::Op::OpVariable, pointer_type_id, variable_id,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_STORAGE_CLASS,
             {static_cast<uint32_t>(context->get_type_mgr()
@@ -53,7 +53,7 @@
   assert(context->get_type_mgr()
              ->GetType(pointer_type_id)
              ->AsPointer()
-             ->storage_class() == SpvStorageClassFunction);
+             ->storage_class() == spv::StorageClass::Function);
 
   // Go through the instructions in the function's first block until we find a
   // suitable variable, or go past all the variables.
@@ -62,7 +62,7 @@
     // We will either find a suitable variable, or find a non-variable
     // instruction; we won't exhaust all instructions.
     assert(iter != function->begin()->end());
-    if (iter->opcode() != SpvOpVariable) {
+    if (iter->opcode() != spv::Op::OpVariable) {
       // If we see a non-variable, we have gone through all the variables.
       break;
     }
@@ -74,16 +74,17 @@
   // function's entry block.
   const uint32_t variable_id = context->TakeNextId();
   auto variable_inst = MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, pointer_type_id, variable_id,
+      context, spv::Op::OpVariable, pointer_type_id, variable_id,
       opt::Instruction::OperandList(
-          {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
+          {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+            {uint32_t(spv::StorageClass::Function)}}}));
   iter->InsertBefore(std::move(variable_inst));
   return variable_id;
 }
 
 uint32_t FindOrCreateGlobalUndef(opt::IRContext* context, uint32_t type_id) {
   for (auto& inst : context->module()->types_values()) {
-    if (inst.opcode() != SpvOpUndef) {
+    if (inst.opcode() != spv::Op::OpUndef) {
       continue;
     }
     if (inst.type_id() == type_id) {
@@ -91,8 +92,9 @@
     }
   }
   const uint32_t undef_id = context->TakeNextId();
-  auto undef_inst = MakeUnique<opt::Instruction>(
-      context, SpvOpUndef, type_id, undef_id, opt::Instruction::OperandList());
+  auto undef_inst =
+      MakeUnique<opt::Instruction>(context, spv::Op::OpUndef, type_id, undef_id,
+                                   opt::Instruction::OperandList());
   assert(undef_id == undef_inst->result_id());
   context->module()->AddGlobalValue(std::move(undef_inst));
   return undef_id;
diff --git a/third_party/SPIRV-Tools/source/reduce/remove_selection_reduction_opportunity_finder.cpp b/third_party/SPIRV-Tools/source/reduce/remove_selection_reduction_opportunity_finder.cpp
index 74df1b8..6abadf2 100644
--- a/third_party/SPIRV-Tools/source/reduce/remove_selection_reduction_opportunity_finder.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/remove_selection_reduction_opportunity_finder.cpp
@@ -36,7 +36,7 @@
   for (auto* function : GetTargetFunctions(context, target_function)) {
     for (auto& block : *function) {
       if (auto merge_instruction = block.GetMergeInst()) {
-        if (merge_instruction->opcode() == SpvOpLoopMerge) {
+        if (merge_instruction->opcode() == spv::Op::OpLoopMerge) {
           uint32_t merge_block_id =
               merge_instruction->GetSingleWordOperand(kMergeNodeIndex);
           uint32_t continue_block_id =
@@ -54,7 +54,7 @@
   for (auto& function : *context->module()) {
     for (auto& block : function) {
       if (auto merge_instruction = block.GetMergeInst()) {
-        if (merge_instruction->opcode() == SpvOpSelectionMerge) {
+        if (merge_instruction->opcode() == spv::Op::OpSelectionMerge) {
           if (CanOpSelectionMergeBeRemoved(
                   context, block, merge_instruction,
                   merge_and_continue_blocks_from_loops)) {
diff --git a/third_party/SPIRV-Tools/source/reduce/remove_struct_member_reduction_opportunity.cpp b/third_party/SPIRV-Tools/source/reduce/remove_struct_member_reduction_opportunity.cpp
index e72ed35..3309fd0 100644
--- a/third_party/SPIRV-Tools/source/reduce/remove_struct_member_reduction_opportunity.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/remove_struct_member_reduction_opportunity.cpp
@@ -36,14 +36,14 @@
       struct_type_, [this, &decorations_to_kill](opt::Instruction* user,
                                                  uint32_t /*operand_index*/) {
         switch (user->opcode()) {
-          case SpvOpCompositeConstruct:
-          case SpvOpConstantComposite:
+          case spv::Op::OpCompositeConstruct:
+          case spv::Op::OpConstantComposite:
             // This use is constructing a composite of the struct type, so we
             // must remove the id that was provided for the member we are
             // removing.
             user->RemoveInOperand(member_index_);
             break;
-          case SpvOpMemberDecorate:
+          case spv::Op::OpMemberDecorate:
             // This use is decorating a member of the struct.
             if (user->GetSingleWordInOperand(1) == member_index_) {
               // The member we are removing is being decorated, so we record
@@ -78,8 +78,8 @@
     for (auto& block : function) {
       for (auto& inst : block) {
         switch (inst.opcode()) {
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain: {
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain: {
             // These access chain instructions take sequences of ids for
             // indexing, starting from input operand 1.
             auto composite_type_id =
@@ -90,8 +90,8 @@
                     ->GetSingleWordInOperand(1);
             AdjustAccessedIndices(composite_type_id, 1, false, context, &inst);
           } break;
-          case SpvOpPtrAccessChain:
-          case SpvOpInBoundsPtrAccessChain: {
+          case spv::Op::OpPtrAccessChain:
+          case spv::Op::OpInBoundsPtrAccessChain: {
             // These access chain instructions take sequences of ids for
             // indexing, starting from input operand 2.
             auto composite_type_id =
@@ -102,7 +102,7 @@
                     ->GetSingleWordInOperand(1);
             AdjustAccessedIndices(composite_type_id, 2, false, context, &inst);
           } break;
-          case SpvOpCompositeExtract: {
+          case spv::Op::OpCompositeExtract: {
             // OpCompositeExtract uses literals for indexing, starting at input
             // operand 1.
             auto composite_type_id =
@@ -111,7 +111,7 @@
                     ->type_id();
             AdjustAccessedIndices(composite_type_id, 1, true, context, &inst);
           } break;
-          case SpvOpCompositeInsert: {
+          case spv::Op::OpCompositeInsert: {
             // OpCompositeInsert uses literals for indexing, starting at input
             // operand 2.
             auto composite_type_id =
@@ -146,13 +146,13 @@
        i < composite_access_instruction->NumInOperands(); i++) {
     auto type_inst = context->get_def_use_mgr()->GetDef(next_type);
     switch (type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
         next_type = type_inst->GetSingleWordInOperand(0);
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // Struct types are special because (a) we may need to adjust the index
         // being used, if the struct type is the one from which we are removing
         // a member, and (b) the type encountered by following the current index
diff --git a/third_party/SPIRV-Tools/source/reduce/remove_unused_instruction_reduction_opportunity_finder.cpp b/third_party/SPIRV-Tools/source/reduce/remove_unused_instruction_reduction_opportunity_finder.cpp
index d7bb3a8..fbbeb34 100644
--- a/third_party/SPIRV-Tools/source/reduce/remove_unused_instruction_reduction_opportunity_finder.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/remove_unused_instruction_reduction_opportunity_finder.cpp
@@ -103,8 +103,8 @@
           continue;
         }
         if (spvOpcodeIsBlockTerminator(inst.opcode()) ||
-            inst.opcode() == SpvOpSelectionMerge ||
-            inst.opcode() == SpvOpLoopMerge) {
+            inst.opcode() == spv::Op::OpSelectionMerge ||
+            inst.opcode() == spv::Op::OpLoopMerge) {
           // In this reduction pass we do not want to affect static
           // control flow.
           continue;
@@ -133,7 +133,7 @@
       &inst, [this](opt::Instruction* user, uint32_t use_index) -> bool {
         return (user->IsDecoration() &&
                 !IsIndependentlyRemovableDecoration(*user)) ||
-               (user->opcode() == SpvOpEntryPoint && use_index > 2);
+               (user->opcode() == spv::Op::OpEntryPoint && use_index > 2);
       });
 }
 
@@ -141,13 +141,13 @@
     IsIndependentlyRemovableDecoration(const opt::Instruction& inst) const {
   uint32_t decoration;
   switch (inst.opcode()) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateString:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateString:
       decoration = inst.GetSingleWordInOperand(1u);
       break;
-    case SpvOpMemberDecorate:
-    case SpvOpMemberDecorateString:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpMemberDecorateString:
       decoration = inst.GetSingleWordInOperand(2u);
       break;
     default:
@@ -160,12 +160,12 @@
   // not change the shader interface, will not make the shader invalid, will
   // actually be found in practice, etc.
 
-  switch (decoration) {
-    case SpvDecorationRelaxedPrecision:
-    case SpvDecorationNoSignedWrap:
-    case SpvDecorationNoContraction:
-    case SpvDecorationNoUnsignedWrap:
-    case SpvDecorationUserSemantic:
+  switch (spv::Decoration(decoration)) {
+    case spv::Decoration::RelaxedPrecision:
+    case spv::Decoration::NoSignedWrap:
+    case spv::Decoration::NoContraction:
+    case spv::Decoration::NoUnsignedWrap:
+    case spv::Decoration::UserSemantic:
       return true;
     default:
       return false;
diff --git a/third_party/SPIRV-Tools/source/reduce/remove_unused_struct_member_reduction_opportunity_finder.cpp b/third_party/SPIRV-Tools/source/reduce/remove_unused_struct_member_reduction_opportunity_finder.cpp
index cd0c4e4..db381e0 100644
--- a/third_party/SPIRV-Tools/source/reduce/remove_unused_struct_member_reduction_opportunity_finder.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/remove_unused_struct_member_reduction_opportunity_finder.cpp
@@ -43,7 +43,7 @@
 
   // Consider every struct type in the module.
   for (auto& type_or_value : context->types_values()) {
-    if (type_or_value.opcode() != SpvOpTypeStruct) {
+    if (type_or_value.opcode() != spv::Op::OpTypeStruct) {
       continue;
     }
 
@@ -60,7 +60,7 @@
         &type_or_value,
         [&unused_members](opt::Instruction* user, uint32_t /*operand_index*/) {
           switch (user->opcode()) {
-            case SpvOpMemberName:
+            case spv::Op::OpMemberName:
               unused_members.erase(user->GetSingleWordInOperand(1));
               break;
             default:
@@ -91,8 +91,8 @@
           // The way the helper is invoked depends on whether the instruction
           // uses literal or id indices, and the offset into the instruction's
           // input operands from which index operands are provided.
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain: {
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain: {
             auto composite_type_id =
                 context->get_def_use_mgr()
                     ->GetDef(context->get_def_use_mgr()
@@ -102,8 +102,8 @@
             MarkAccessedMembersAsUsed(context, composite_type_id, 1, false,
                                       inst, &unused_member_to_structs);
           } break;
-          case SpvOpPtrAccessChain:
-          case SpvOpInBoundsPtrAccessChain: {
+          case spv::Op::OpPtrAccessChain:
+          case spv::Op::OpInBoundsPtrAccessChain: {
             auto composite_type_id =
                 context->get_def_use_mgr()
                     ->GetDef(context->get_def_use_mgr()
@@ -113,7 +113,7 @@
             MarkAccessedMembersAsUsed(context, composite_type_id, 2, false,
                                       inst, &unused_member_to_structs);
           } break;
-          case SpvOpCompositeExtract: {
+          case spv::Op::OpCompositeExtract: {
             auto composite_type_id =
                 context->get_def_use_mgr()
                     ->GetDef(inst.GetSingleWordInOperand(0))
@@ -121,7 +121,7 @@
             MarkAccessedMembersAsUsed(context, composite_type_id, 1, true, inst,
                                       &unused_member_to_structs);
           } break;
-          case SpvOpCompositeInsert: {
+          case spv::Op::OpCompositeInsert: {
             auto composite_type_id =
                 context->get_def_use_mgr()
                     ->GetDef(inst.GetSingleWordInOperand(1))
@@ -163,13 +163,13 @@
        i < composite_access_instruction.NumInOperands(); i++) {
     auto type_inst = context->get_def_use_mgr()->GetDef(next_type);
     switch (type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
         next_type = type_inst->GetSingleWordInOperand(0);
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         uint32_t index_operand =
             composite_access_instruction.GetSingleWordInOperand(i);
         uint32_t member = literal_indices ? index_operand
diff --git a/third_party/SPIRV-Tools/source/reduce/simple_conditional_branch_to_branch_opportunity_finder.cpp b/third_party/SPIRV-Tools/source/reduce/simple_conditional_branch_to_branch_opportunity_finder.cpp
index d867c3a..9637f0f 100644
--- a/third_party/SPIRV-Tools/source/reduce/simple_conditional_branch_to_branch_opportunity_finder.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/simple_conditional_branch_to_branch_opportunity_finder.cpp
@@ -29,15 +29,15 @@
   for (auto* function : GetTargetFunctions(context, target_function)) {
     // Consider every block in the function.
     for (auto& block : *function) {
-      // The terminator must be SpvOpBranchConditional.
+      // The terminator must be spv::Op::OpBranchConditional.
       opt::Instruction* terminator = block.terminator();
-      if (terminator->opcode() != SpvOpBranchConditional) {
+      if (terminator->opcode() != spv::Op::OpBranchConditional) {
         continue;
       }
       // It must not be a selection header, as these cannot be followed by
       // OpBranch.
       if (block.GetMergeInst() &&
-          block.GetMergeInst()->opcode() == SpvOpSelectionMerge) {
+          block.GetMergeInst()->opcode() == spv::Op::OpSelectionMerge) {
         continue;
       }
       // The conditional branch must be simplified.
diff --git a/third_party/SPIRV-Tools/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp b/third_party/SPIRV-Tools/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp
index a2be0c4..6d772b5 100644
--- a/third_party/SPIRV-Tools/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp
@@ -31,7 +31,8 @@
 }
 
 void SimpleConditionalBranchToBranchReductionOpportunity::Apply() {
-  assert(conditional_branch_instruction_->opcode() == SpvOpBranchConditional &&
+  assert(conditional_branch_instruction_->opcode() ==
+             spv::Op::OpBranchConditional &&
          "SimpleConditionalBranchToBranchReductionOpportunity: branch was not "
          "a conditional branch");
 
@@ -46,7 +47,7 @@
   // ->
   // OpBranch %block_id
 
-  conditional_branch_instruction_->SetOpcode(SpvOpBranch);
+  conditional_branch_instruction_->SetOpcode(spv::Op::OpBranch);
   conditional_branch_instruction_->ReplaceOperands(
       {{SPV_OPERAND_TYPE_ID,
         {conditional_branch_instruction_->GetSingleWordInOperand(
diff --git a/third_party/SPIRV-Tools/source/reduce/structured_construct_to_block_reduction_opportunity.cpp b/third_party/SPIRV-Tools/source/reduce/structured_construct_to_block_reduction_opportunity.cpp
index ed73841..cc5ffe3 100644
--- a/third_party/SPIRV-Tools/source/reduce/structured_construct_to_block_reduction_opportunity.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/structured_construct_to_block_reduction_opportunity.cpp
@@ -55,7 +55,7 @@
 
   // The terminator for the header block is changed to be an unconditional
   // branch to the merge block.
-  header_block->terminator()->SetOpcode(SpvOpBranch);
+  header_block->terminator()->SetOpcode(spv::Op::OpBranch);
   header_block->terminator()->SetInOperands(
       {{SPV_OPERAND_TYPE_ID, {merge_block->id()}}});
 
diff --git a/third_party/SPIRV-Tools/source/reduce/structured_loop_to_selection_reduction_opportunity.cpp b/third_party/SPIRV-Tools/source/reduce/structured_loop_to_selection_reduction_opportunity.cpp
index 850af45..45b9528 100644
--- a/third_party/SPIRV-Tools/source/reduce/structured_loop_to_selection_reduction_opportunity.cpp
+++ b/third_party/SPIRV-Tools/source/reduce/structured_loop_to_selection_reduction_opportunity.cpp
@@ -129,12 +129,12 @@
   // Figure out which operands of the terminator need to be considered for
   // redirection.
   std::vector<uint32_t> operand_indices;
-  if (terminator->opcode() == SpvOpBranch) {
+  if (terminator->opcode() == spv::Op::OpBranch) {
     operand_indices = {0};
-  } else if (terminator->opcode() == SpvOpBranchConditional) {
+  } else if (terminator->opcode() == spv::Op::OpBranchConditional) {
     operand_indices = {1, 2};
   } else {
-    assert(terminator->opcode() == SpvOpSwitch);
+    assert(terminator->opcode() == spv::Op::OpSwitch);
     for (uint32_t label_index = 1; label_index < terminator->NumOperands();
          label_index += 2) {
       operand_indices.push_back(label_index);
@@ -179,18 +179,19 @@
   auto loop_merge_inst = loop_construct_header_->GetLoopMergeInst();
   auto const loop_merge_block_id =
       loop_merge_inst->GetSingleWordOperand(kMergeNodeIndex);
-  loop_merge_inst->SetOpcode(SpvOpSelectionMerge);
+  loop_merge_inst->SetOpcode(spv::Op::OpSelectionMerge);
   loop_merge_inst->ReplaceOperands(
       {{loop_merge_inst->GetOperand(kMergeNodeIndex).type,
         {loop_merge_block_id}},
-       {SPV_OPERAND_TYPE_SELECTION_CONTROL, {SpvSelectionControlMaskNone}}});
+       {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+        {uint32_t(spv::SelectionControlMask::MaskNone)}}});
 
   // The loop header either finishes with OpBranch or OpBranchConditional.
   // The latter is fine for a selection.  In the former case we need to turn
   // it into OpBranchConditional.  We use "true" as the condition, and make
   // the "else" branch be the merge block.
   auto terminator = loop_construct_header_->terminator();
-  if (terminator->opcode() == SpvOpBranch) {
+  if (terminator->opcode() == spv::Op::OpBranch) {
     opt::analysis::Bool temp;
     const opt::analysis::Bool* bool_type =
         context_->get_type_mgr()->GetRegisteredType(&temp)->AsBool();
@@ -199,7 +200,7 @@
     auto true_const_result_id =
         const_mgr->GetDefiningInstruction(true_const)->result_id();
     auto original_branch_id = terminator->GetSingleWordOperand(0);
-    terminator->SetOpcode(SpvOpBranchConditional);
+    terminator->SetOpcode(spv::Op::OpBranchConditional);
     terminator->ReplaceOperands({{SPV_OPERAND_TYPE_ID, {true_const_result_id}},
                                  {SPV_OPERAND_TYPE_ID, {original_branch_id}},
                                  {SPV_OPERAND_TYPE_ID, {loop_merge_block_id}}});
@@ -215,7 +216,7 @@
   // Consider each instruction in the function.
   for (auto& block : *loop_construct_header_->GetParent()) {
     for (auto& def : block) {
-      if (def.opcode() == SpvOpVariable) {
+      if (def.opcode() == spv::Op::OpVariable) {
         // Variables are defined at the start of the function, and can be
         // accessed by all blocks, even by unreachable blocks that have no
         // dominators, so we do not need to worry about them.
@@ -233,11 +234,11 @@
         // access chain, in which case replace it with some (possibly fresh)
         // variable (as we cannot load from / store to OpUndef).
         if (!DefinitionSufficientlyDominatesUse(&def, use, index, block)) {
-          if (def.opcode() == SpvOpAccessChain) {
+          if (def.opcode() == spv::Op::OpAccessChain) {
             auto pointer_type =
                 context_->get_type_mgr()->GetType(def.type_id())->AsPointer();
             switch (pointer_type->storage_class()) {
-              case SpvStorageClassFunction:
+              case spv::StorageClass::Function:
                 use->SetOperand(
                     index, {FindOrCreateFunctionVariable(
                                context_, loop_construct_header_->GetParent(),
@@ -270,7 +271,7 @@
                                        opt::Instruction* use,
                                        uint32_t use_index,
                                        opt::BasicBlock& def_block) {
-  if (use->opcode() == SpvOpPhi) {
+  if (use->opcode() == spv::Op::OpPhi) {
     // A use in a phi doesn't need to be dominated by its definition, but the
     // associated parent block does need to be dominated by the definition.
     return context_->GetDominatorAnalysis(loop_construct_header_->GetParent())
diff --git a/third_party/SPIRV-Tools/source/spirv_validator_options.cpp b/third_party/SPIRV-Tools/source/spirv_validator_options.cpp
index e5b1eec..b72a644 100644
--- a/third_party/SPIRV-Tools/source/spirv_validator_options.cpp
+++ b/third_party/SPIRV-Tools/source/spirv_validator_options.cpp
@@ -125,3 +125,8 @@
                                             bool val) {
   options->allow_localsizeid = val;
 }
+
+void spvValidatorOptionsSetFriendlyNames(spv_validator_options options,
+                                         bool val) {
+  options->use_friendly_names = val;
+}
diff --git a/third_party/SPIRV-Tools/source/spirv_validator_options.h b/third_party/SPIRV-Tools/source/spirv_validator_options.h
index a357c03..0145048 100644
--- a/third_party/SPIRV-Tools/source/spirv_validator_options.h
+++ b/third_party/SPIRV-Tools/source/spirv_validator_options.h
@@ -48,7 +48,8 @@
         workgroup_scalar_block_layout(false),
         skip_block_layout(false),
         allow_localsizeid(false),
-        before_hlsl_legalization(false) {}
+        before_hlsl_legalization(false),
+        use_friendly_names(true) {}
 
   validator_universal_limits_t universal_limits_;
   bool relax_struct_store;
@@ -60,6 +61,7 @@
   bool skip_block_layout;
   bool allow_localsizeid;
   bool before_hlsl_legalization;
+  bool use_friendly_names;
 };
 
 #endif  // SOURCE_SPIRV_VALIDATOR_OPTIONS_H_
diff --git a/third_party/SPIRV-Tools/source/table.h b/third_party/SPIRV-Tools/source/table.h
index 5adf04a..8097f13 100644
--- a/third_party/SPIRV-Tools/source/table.h
+++ b/third_party/SPIRV-Tools/source/table.h
@@ -21,9 +21,9 @@
 
 typedef struct spv_opcode_desc_t {
   const char* name;
-  const SpvOp opcode;
+  const spv::Op opcode;
   const uint32_t numCapabilities;
-  const SpvCapability* capabilities;
+  const spv::Capability* capabilities;
   // operandTypes[0..numTypes-1] describe logical operands for the instruction.
   // The operand types include result id and result-type id, followed by
   // the types of arguments.
@@ -48,7 +48,7 @@
   const char* name;
   const uint32_t value;
   const uint32_t numCapabilities;
-  const SpvCapability* capabilities;
+  const spv::Capability* capabilities;
   // A set of extensions that enable this feature. If empty then this operand
   // value is in core and its availability is subject to minVersion. The
   // assembler, binary parser, and disassembler ignore this rule, so you can
@@ -73,7 +73,7 @@
   const char* name;
   const uint32_t ext_inst;
   const uint32_t numCapabilities;
-  const SpvCapability* capabilities;
+  const spv::Capability* capabilities;
   const spv_operand_type_t operandTypes[16];  // TODO: Smaller/larger?
 } spv_ext_inst_desc_t;
 
diff --git a/third_party/SPIRV-Tools/source/text.cpp b/third_party/SPIRV-Tools/source/text.cpp
index 90f69c5..8f77d62 100644
--- a/third_party/SPIRV-Tools/source/text.cpp
+++ b/third_party/SPIRV-Tools/source/text.cpp
@@ -227,7 +227,8 @@
 
       // Set the extended instruction type.
       // The import set id is the 3rd operand of OpExtInst.
-      if (pInst->opcode == SpvOpExtInst && pInst->words.size() == 4) {
+      if (spv::Op(pInst->opcode) == spv::Op::OpExtInst &&
+          pInst->words.size() == 4) {
         auto ext_inst_type = context->getExtInstTypeForId(pInst->words[3]);
         if (ext_inst_type == SPV_EXT_INST_TYPE_NONE) {
           return context->diagnostic()
@@ -279,7 +280,7 @@
       // The assembler accepts the symbolic name for the opcode, but without
       // the "Op" prefix.  For example, "IAdd" is accepted.  The number
       // of the opcode is emitted.
-      SpvOp opcode;
+      spv::Op opcode;
       if (grammar.lookupSpecConstantOpcode(textValue, &opcode)) {
         return context->diagnostic() << "Invalid " << spvOperandTypeStr(type)
                                      << " '" << textValue << "'.";
@@ -327,8 +328,8 @@
       // The encoding for OpConstant, OpSpecConstant and OpSwitch all
       // depend on either their own result-id or the result-id of
       // one of their parameters.
-      if (SpvOpConstant == pInst->opcode ||
-          SpvOpSpecConstant == pInst->opcode) {
+      if (spv::Op::OpConstant == pInst->opcode ||
+          spv::Op::OpSpecConstant == pInst->opcode) {
         // The type of the literal is determined by the type Id of the
         // instruction.
         expected_type =
@@ -344,7 +345,7 @@
                  << "Type for " << opcode_name
                  << " must be a scalar floating point or integer type";
         }
-      } else if (pInst->opcode == SpvOpSwitch) {
+      } else if (pInst->opcode == spv::Op::OpSwitch) {
         // The type of the literal is the same as the type of the selector.
         expected_type = context->getTypeOfValueInstruction(pInst->words[1]);
         if (!spvtools::isScalarIntegral(expected_type)) {
@@ -375,7 +376,7 @@
       }
 
       // NOTE: Special case for extended instruction library import
-      if (SpvOpExtInstImport == pInst->opcode) {
+      if (spv::Op::OpExtInstImport == pInst->opcode) {
         const spv_ext_inst_type_t ext_inst_type =
             spvExtInstImportTypeGet(literal.str.c_str());
         if (SPV_EXT_INST_TYPE_NONE == ext_inst_type) {
@@ -688,7 +689,7 @@
                        uint32_t* header) {
   if (!header) return SPV_ERROR_INVALID_BINARY;
 
-  header[SPV_INDEX_MAGIC_NUMBER] = SpvMagicNumber;
+  header[SPV_INDEX_MAGIC_NUMBER] = spv::MagicNumber;
   header[SPV_INDEX_VERSION_NUMBER] = spvVersionForTargetEnv(env);
   header[SPV_INDEX_GENERATOR_NUMBER] =
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, kAssemblerVersion);
@@ -722,7 +723,7 @@
     // being parsed. A malformed input might feature such an operand *before*
     // the opcode is known. To guard against accessing an uninitialized opcode,
     // the instruction's opcode is initialized to a default value.
-    inst.opcode = SpvOpMax;
+    inst.opcode = spv::Op::Max;
 
     if (spvTextEncodeOpcode(grammar, &context, &inst)) {
       return SPV_ERROR_INVALID_TEXT;
diff --git a/third_party/SPIRV-Tools/source/text_handler.cpp b/third_party/SPIRV-Tools/source/text_handler.cpp
index 15c1741..35c4b83 100644
--- a/third_party/SPIRV-Tools/source/text_handler.cpp
+++ b/third_party/SPIRV-Tools/source/text_handler.cpp
@@ -323,12 +323,12 @@
                         << " has already been used to generate a type";
   }
 
-  if (pInst->opcode == SpvOpTypeInt) {
+  if (pInst->opcode == spv::Op::OpTypeInt) {
     if (pInst->words.size() != 4)
       return diagnostic() << "Invalid OpTypeInt instruction";
     types_[value] = {pInst->words[2], pInst->words[3] != 0,
                      IdTypeClass::kScalarIntegerType};
-  } else if (pInst->opcode == SpvOpTypeFloat) {
+  } else if (pInst->opcode == spv::Op::OpTypeFloat) {
     if (pInst->words.size() != 3)
       return diagnostic() << "Invalid OpTypeFloat instruction";
     types_[value] = {pInst->words[2], false, IdTypeClass::kScalarFloatType};
diff --git a/third_party/SPIRV-Tools/source/val/construct.cpp b/third_party/SPIRV-Tools/source/val/construct.cpp
index 52e61d5..1b6a54f 100644
--- a/third_party/SPIRV-Tools/source/val/construct.cpp
+++ b/third_party/SPIRV-Tools/source/val/construct.cpp
@@ -164,8 +164,8 @@
     //  ii. The immediate dominator of |block|.
     auto NextBlock = [](const BasicBlock* block) -> const BasicBlock* {
       for (auto& use : block->label()->uses()) {
-        if ((use.first->opcode() == SpvOpLoopMerge ||
-             use.first->opcode() == SpvOpSelectionMerge) &&
+        if ((use.first->opcode() == spv::Op::OpLoopMerge ||
+             use.first->opcode() == spv::Op::OpSelectionMerge) &&
             use.second == 1 &&
             use.first->block()->structurally_dominates(*block)) {
           return use.first->block();
@@ -181,10 +181,10 @@
       auto terminator = block->terminator();
       auto index = terminator - &_.ordered_instructions()[0];
       auto merge_inst = &_.ordered_instructions()[index - 1];
-      if (merge_inst->opcode() == SpvOpLoopMerge ||
-          (header->terminator()->opcode() != SpvOpSwitch &&
-           merge_inst->opcode() == SpvOpSelectionMerge &&
-           terminator->opcode() == SpvOpSwitch)) {
+      if (merge_inst->opcode() == spv::Op::OpLoopMerge ||
+          (header->terminator()->opcode() != spv::Op::OpSwitch &&
+           merge_inst->opcode() == spv::Op::OpSelectionMerge &&
+           terminator->opcode() == spv::Op::OpSwitch)) {
         auto merge_target = merge_inst->GetOperandAs<uint32_t>(0u);
         auto merge_block = merge_inst->function()->GetBlock(merge_target).first;
         if (merge_block->structurally_dominates(*header)) {
@@ -192,22 +192,22 @@
           continue;
         }
 
-        if ((!seen_switch || merge_inst->opcode() == SpvOpLoopMerge) &&
+        if ((!seen_switch || merge_inst->opcode() == spv::Op::OpLoopMerge) &&
             dest->id() == merge_target) {
           return true;
-        } else if (merge_inst->opcode() == SpvOpLoopMerge) {
+        } else if (merge_inst->opcode() == spv::Op::OpLoopMerge) {
           auto continue_target = merge_inst->GetOperandAs<uint32_t>(1u);
           if (dest->id() == continue_target) {
             return true;
           }
         }
 
-        if (terminator->opcode() == SpvOpSwitch) {
+        if (terminator->opcode() == spv::Op::OpSwitch) {
           seen_switch = true;
         }
 
         // Hit an enclosing loop and didn't break or continue.
-        if (merge_inst->opcode() == SpvOpLoopMerge) return false;
+        if (merge_inst->opcode() == spv::Op::OpLoopMerge) return false;
       }
 
       block = NextBlock(block);
diff --git a/third_party/SPIRV-Tools/source/val/decoration.h b/third_party/SPIRV-Tools/source/val/decoration.h
index 4f53f20..384cc57 100644
--- a/third_party/SPIRV-Tools/source/val/decoration.h
+++ b/third_party/SPIRV-Tools/source/val/decoration.h
@@ -39,33 +39,33 @@
 //
 // Example 1: Decoration for an object<id> with no parameters:
 // OpDecorate %obj Flat
-//            dec_type_ = SpvDecorationFlat
+//            dec_type_ = spv::Decoration::Flat
 //              params_ = empty vector
 // struct_member_index_ = kInvalidMember
 //
 // Example 2: Decoration for an object<id> with two parameters:
 // OpDecorate %obj LinkageAttributes "link" Import
-//            dec_type_ = SpvDecorationLinkageAttributes
+//            dec_type_ = spv::Decoration::LinkageAttributes
 //              params_ = vector { link, Import }
 // struct_member_index_ = kInvalidMember
 //
 // Example 3: Decoration for a member of a structure with one parameter:
 // OpMemberDecorate %struct 2 Offset 2
-//            dec_type_ = SpvDecorationOffset
+//            dec_type_ = spv::Decoration::Offset
 //              params_ = vector { 2 }
 // struct_member_index_ = 2
 //
 class Decoration {
  public:
   enum { kInvalidMember = -1 };
-  Decoration(SpvDecoration t,
+  Decoration(spv::Decoration t,
              const std::vector<uint32_t>& parameters = std::vector<uint32_t>(),
              uint32_t member_index = kInvalidMember)
       : dec_type_(t), params_(parameters), struct_member_index_(member_index) {}
 
   void set_struct_member_index(uint32_t index) { struct_member_index_ = index; }
   int struct_member_index() const { return struct_member_index_; }
-  SpvDecoration dec_type() const { return dec_type_; }
+  spv::Decoration dec_type() const { return dec_type_; }
   std::vector<uint32_t>& params() { return params_; }
   const std::vector<uint32_t>& params() const { return params_; }
 
@@ -84,7 +84,7 @@
   }
 
  private:
-  SpvDecoration dec_type_;
+  spv::Decoration dec_type_;
   std::vector<uint32_t> params_;
 
   // If the decoration applies to a member of a structure type, then the index
diff --git a/third_party/SPIRV-Tools/source/val/function.cpp b/third_party/SPIRV-Tools/source/val/function.cpp
index fc7ccd0..8b4423a 100644
--- a/third_party/SPIRV-Tools/source/val/function.cpp
+++ b/third_party/SPIRV-Tools/source/val/function.cpp
@@ -33,7 +33,7 @@
 static const uint32_t kInvalidId = 0x400000;
 
 Function::Function(uint32_t function_id, uint32_t result_type_id,
-                   SpvFunctionControlMask function_control,
+                   spv::FunctionControlMask function_control,
                    uint32_t function_type_id)
     : id_(function_id),
       function_type_id_(function_type_id),
@@ -371,10 +371,10 @@
   return block_depth_[bb];
 }
 
-void Function::RegisterExecutionModelLimitation(SpvExecutionModel model,
+void Function::RegisterExecutionModelLimitation(spv::ExecutionModel model,
                                                 const std::string& message) {
   execution_model_limitations_.push_back(
-      [model, message](SpvExecutionModel in_model, std::string* out_message) {
+      [model, message](spv::ExecutionModel in_model, std::string* out_message) {
         if (model != in_model) {
           if (out_message) {
             *out_message = message;
@@ -385,7 +385,7 @@
       });
 }
 
-bool Function::IsCompatibleWithExecutionModel(SpvExecutionModel model,
+bool Function::IsCompatibleWithExecutionModel(spv::ExecutionModel model,
                                               std::string* reason) const {
   bool return_value = true;
   std::stringstream ss_reason;
diff --git a/third_party/SPIRV-Tools/source/val/function.h b/third_party/SPIRV-Tools/source/val/function.h
index 126b1dc..4811794 100644
--- a/third_party/SPIRV-Tools/source/val/function.h
+++ b/third_party/SPIRV-Tools/source/val/function.h
@@ -55,7 +55,8 @@
 class Function {
  public:
   Function(uint32_t id, uint32_t result_type_id,
-           SpvFunctionControlMask function_control, uint32_t function_type_id);
+           spv::FunctionControlMask function_control,
+           uint32_t function_type_id);
 
   /// Registers a function parameter in the current function
   /// @return Returns SPV_SUCCESS if the call was successful
@@ -80,7 +81,8 @@
   ///
   /// @return Returns SPV_SUCCESS if the call was successful
   spv_result_t RegisterBlockVariable(uint32_t type_id, uint32_t id,
-                                     SpvStorageClass storage, uint32_t init_id);
+                                     spv::StorageClass storage,
+                                     uint32_t init_id);
 
   /// Registers a loop merge construct in the function
   ///
@@ -205,12 +207,12 @@
 
   /// Registers execution model limitation such as "Feature X is only available
   /// with Execution Model Y".
-  void RegisterExecutionModelLimitation(SpvExecutionModel model,
+  void RegisterExecutionModelLimitation(spv::ExecutionModel model,
                                         const std::string& message);
 
   /// Registers execution model limitation with an |is_compatible| functor.
   void RegisterExecutionModelLimitation(
-      std::function<bool(SpvExecutionModel, std::string*)> is_compatible) {
+      std::function<bool(spv::ExecutionModel, std::string*)> is_compatible) {
     execution_model_limitations_.push_back(is_compatible);
   }
 
@@ -227,7 +229,7 @@
   /// Returns true if the given execution model passes the limitations stored in
   /// execution_model_limitations_. Returns false otherwise and fills optional
   /// |reason| parameter.
-  bool IsCompatibleWithExecutionModel(SpvExecutionModel model,
+  bool IsCompatibleWithExecutionModel(spv::ExecutionModel model,
                                       std::string* reason = nullptr) const;
 
   // Inserts id to the set of functions called from this function.
@@ -286,7 +288,7 @@
   uint32_t result_type_id_;
 
   /// The control fo the function
-  SpvFunctionControlMask function_control_;
+  spv::FunctionControlMask function_control_;
 
   /// The type of declaration of each function
   FunctionDecl declaration_type_;
@@ -381,7 +383,7 @@
   /// function. The functor stored in the list return true if execution model
   /// is compatible, false otherwise. If the functor returns false, it can also
   /// optionally fill the string parameter with the reason for incompatibility.
-  std::list<std::function<bool(SpvExecutionModel, std::string*)>>
+  std::list<std::function<bool(spv::ExecutionModel, std::string*)>>
       execution_model_limitations_;
 
   /// Stores limitations imposed by instructions used within the function.
diff --git a/third_party/SPIRV-Tools/source/val/instruction.h b/third_party/SPIRV-Tools/source/val/instruction.h
index 6d1f9f4..c524bd3 100644
--- a/third_party/SPIRV-Tools/source/val/instruction.h
+++ b/third_party/SPIRV-Tools/source/val/instruction.h
@@ -42,7 +42,7 @@
 
   uint32_t id() const { return inst_.result_id; }
   uint32_t type_id() const { return inst_.type_id; }
-  SpvOp opcode() const { return static_cast<SpvOp>(inst_.opcode); }
+  spv::Op opcode() const { return static_cast<spv::Op>(inst_.opcode); }
 
   /// Returns the Function where the instruction was defined. nullptr if it was
   /// defined outside of a Function
@@ -87,13 +87,13 @@
   }
 
   bool IsNonSemantic() const {
-    return opcode() == SpvOp::SpvOpExtInst &&
+    return opcode() == spv::Op::OpExtInst &&
            spvExtInstIsNonSemantic(inst_.ext_inst_type);
   }
 
   /// True if this is an OpExtInst for debug info extension.
   bool IsDebugInfo() const {
-    return opcode() == SpvOp::SpvOpExtInst &&
+    return opcode() == spv::Op::OpExtInst &&
            spvExtInstIsDebugInfo(inst_.ext_inst_type);
   }
 
diff --git a/third_party/SPIRV-Tools/source/val/validate.cpp b/third_party/SPIRV-Tools/source/val/validate.cpp
index 55e9fd2..10f3d43 100644
--- a/third_party/SPIRV-Tools/source/val/validate.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate.cpp
@@ -66,15 +66,15 @@
 
 // Parses the beginning of the module searching for OpExtension instructions.
 // Registers extensions if recognized. Returns SPV_REQUESTED_TERMINATION
-// once an instruction which is not SpvOpCapability and SpvOpExtension is
-// encountered. According to the SPIR-V spec extensions are declared after
-// capabilities and before everything else.
+// once an instruction which is not spv::Op::OpCapability and
+// spv::Op::OpExtension is encountered. According to the SPIR-V spec extensions
+// are declared after capabilities and before everything else.
 spv_result_t ProcessExtensions(void* user_data,
                                const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  if (opcode == SpvOpCapability) return SPV_SUCCESS;
+  const spv::Op opcode = static_cast<spv::Op>(inst->opcode);
+  if (opcode == spv::Op::OpCapability) return SPV_SUCCESS;
 
-  if (opcode == SpvOpExtension) {
+  if (opcode == spv::Op::OpExtension) {
     ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
     RegisterExtension(_, inst);
     return SPV_SUCCESS;
@@ -123,7 +123,7 @@
   _.ComputeFunctionToEntryPointMapping();
   _.ComputeRecursiveEntryPoints();
 
-  if (_.entry_points().empty() && !_.HasCapability(SpvCapabilityLinkage)) {
+  if (_.entry_points().empty() && !_.HasCapability(spv::Capability::Linkage)) {
     return _.diag(SPV_ERROR_INVALID_BINARY, nullptr)
            << "No OpEntryPoint instruction was found. This is only allowed if "
               "the Linkage capability is being used.";
@@ -209,6 +209,8 @@
     return error;
   }
 
+  bool has_mask_task_nv = false;
+  bool has_mask_task_ext = false;
   std::vector<Instruction*> visited_entry_points;
   for (auto& instruction : vstate->ordered_instructions()) {
     {
@@ -216,9 +218,9 @@
       // able to, briefly, de-const the instruction.
       Instruction* inst = const_cast<Instruction*>(&instruction);
 
-      if (inst->opcode() == SpvOpEntryPoint) {
+      if (inst->opcode() == spv::Op::OpEntryPoint) {
         const auto entry_point = inst->GetOperandAs<uint32_t>(1);
-        const auto execution_model = inst->GetOperandAs<SpvExecutionModel>(0);
+        const auto execution_model = inst->GetOperandAs<spv::ExecutionModel>(0);
         const std::string desc_name = inst->GetOperandAs<std::string>(2);
 
         ValidationState_t::EntryPointDescription desc;
@@ -234,7 +236,7 @@
         if (visited_entry_points.size() > 0) {
           for (const Instruction* check_inst : visited_entry_points) {
             const auto check_execution_model =
-                check_inst->GetOperandAs<SpvExecutionModel>(0);
+                check_inst->GetOperandAs<spv::ExecutionModel>(0);
             const std::string check_name =
                 check_inst->GetOperandAs<std::string>(2);
 
@@ -247,8 +249,13 @@
           }
         }
         visited_entry_points.push_back(inst);
+
+        has_mask_task_nv |= (execution_model == spv::ExecutionModel::TaskNV ||
+                             execution_model == spv::ExecutionModel::MeshNV);
+        has_mask_task_ext |= (execution_model == spv::ExecutionModel::TaskEXT ||
+                              execution_model == spv::ExecutionModel::MeshEXT);
       }
-      if (inst->opcode() == SpvOpFunctionCall) {
+      if (inst->opcode() == spv::Op::OpFunctionCall) {
         if (!vstate->in_function_body()) {
           return vstate->diag(SPV_ERROR_INVALID_LAYOUT, &instruction)
                  << "A FunctionCall must happen within a function body.";
@@ -279,7 +286,7 @@
     {
       Instruction* inst = const_cast<Instruction*>(&instruction);
       vstate->RegisterInstruction(inst);
-      if (inst->opcode() == SpvOpTypeForwardPointer) {
+      if (inst->opcode() == spv::Op::OpTypeForwardPointer) {
         vstate->RegisterForwardPointer(inst->GetOperandAs<uint32_t>(0));
       }
     }
@@ -293,11 +300,17 @@
     return vstate->diag(SPV_ERROR_INVALID_LAYOUT, nullptr)
            << "Missing OpFunctionEnd at end of module.";
 
-  if (vstate->HasCapability(SpvCapabilityBindlessTextureNV) &&
+  if (vstate->HasCapability(spv::Capability::BindlessTextureNV) &&
       !vstate->has_samplerimage_variable_address_mode_specified())
     return vstate->diag(SPV_ERROR_INVALID_LAYOUT, nullptr)
            << "Missing required OpSamplerImageAddressingModeNV instruction.";
 
+  if (has_mask_task_ext && has_mask_task_nv)
+    return vstate->diag(SPV_ERROR_INVALID_LAYOUT, nullptr)
+           << vstate->VkErrorID(7102)
+           << "Module can't mix MeshEXT/TaskEXT with MeshNV/TaskNV Execution "
+              "Model.";
+
   // Catch undefined forward references before performing further checks.
   if (auto error = ValidateForwardDecls(*vstate)) return error;
 
@@ -351,10 +364,13 @@
 
     if (auto error = LiteralsPass(*vstate, &instruction)) return error;
     if (auto error = RayQueryPass(*vstate, &instruction)) return error;
+    if (auto error = RayTracingPass(*vstate, &instruction)) return error;
+    if (auto error = MeshShadingPass(*vstate, &instruction)) return error;
   }
 
-  // Validate the preconditions involving adjacent instructions. e.g. SpvOpPhi
-  // must only be preceded by SpvOpLabel, SpvOpPhi, or SpvOpLine.
+  // Validate the preconditions involving adjacent instructions. e.g.
+  // spv::Op::OpPhi must only be preceded by spv::Op::OpLabel, spv::Op::OpPhi,
+  // or spv::Op::OpLine.
   if (auto error = ValidateAdjacency(*vstate)) return error;
 
   if (auto error = ValidateEntryPoints(*vstate)) return error;
diff --git a/third_party/SPIRV-Tools/source/val/validate.h b/third_party/SPIRV-Tools/source/val/validate.h
index 97d4683..fd84b06 100644
--- a/third_party/SPIRV-Tools/source/val/validate.h
+++ b/third_party/SPIRV-Tools/source/val/validate.h
@@ -69,8 +69,8 @@
 /// instructions.
 ///
 /// This function will iterate over all instructions and check for any required
-/// predecessor and/or successor instructions. e.g. SpvOpPhi must only be
-/// preceded by SpvOpLabel, SpvOpPhi, or SpvOpLine.
+/// predecessor and/or successor instructions. e.g. spv::Op::OpPhi must only be
+/// preceded by spv::Op::OpLabel, spv::Op::OpPhi, or spv::Op::OpLine.
 ///
 /// @param[in] _ the validation state of the module
 ///
@@ -200,6 +200,12 @@
 /// Validates correctness of ray query instructions.
 spv_result_t RayQueryPass(ValidationState_t& _, const Instruction* inst);
 
+/// Validates correctness of ray tracing instructions.
+spv_result_t RayTracingPass(ValidationState_t& _, const Instruction* inst);
+
+/// Validates correctness of mesh shading instructions.
+spv_result_t MeshShadingPass(ValidationState_t& _, const Instruction* inst);
+
 /// Calculates the reachability of basic blocks.
 void ReachabilityPass(ValidationState_t& _);
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_adjacency.cpp b/third_party/SPIRV-Tools/source/val/validate_adjacency.cpp
index 8e6c373..50c2e92 100644
--- a/third_party/SPIRV-Tools/source/val/validate_adjacency.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_adjacency.cpp
@@ -46,15 +46,15 @@
   for (size_t i = 0; i < instructions.size(); ++i) {
     const auto& inst = instructions[i];
     switch (inst.opcode()) {
-      case SpvOpFunction:
-      case SpvOpFunctionParameter:
+      case spv::Op::OpFunction:
+      case spv::Op::OpFunctionParameter:
         adjacency_status = IN_NEW_FUNCTION;
         break;
-      case SpvOpLabel:
+      case spv::Op::OpLabel:
         adjacency_status =
             adjacency_status == IN_NEW_FUNCTION ? IN_ENTRY_BLOCK : PHI_VALID;
         break;
-      case SpvOpExtInst:
+      case spv::Op::OpExtInst:
         // If it is a debug info instruction, we do not change the status to
         // allow debug info instructions before OpVariable in a function.
         // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/533): We need
@@ -67,7 +67,7 @@
           adjacency_status = PHI_AND_VAR_INVALID;
         }
         break;
-      case SpvOpPhi:
+      case spv::Op::OpPhi:
         if (adjacency_status != PHI_VALID) {
           return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                  << "OpPhi must appear within a non-entry block before all "
@@ -75,15 +75,15 @@
                  << "(except for OpLine, which can be mixed with OpPhi).";
         }
         break;
-      case SpvOpLine:
-      case SpvOpNoLine:
+      case spv::Op::OpLine:
+      case spv::Op::OpNoLine:
         break;
-      case SpvOpLoopMerge:
+      case spv::Op::OpLoopMerge:
         adjacency_status = PHI_AND_VAR_INVALID;
         if (i != (instructions.size() - 1)) {
           switch (instructions[i + 1].opcode()) {
-            case SpvOpBranch:
-            case SpvOpBranchConditional:
+            case spv::Op::OpBranch:
+            case spv::Op::OpBranchConditional:
               break;
             default:
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
@@ -94,12 +94,12 @@
           }
         }
         break;
-      case SpvOpSelectionMerge:
+      case spv::Op::OpSelectionMerge:
         adjacency_status = PHI_AND_VAR_INVALID;
         if (i != (instructions.size() - 1)) {
           switch (instructions[i + 1].opcode()) {
-            case SpvOpBranchConditional:
-            case SpvOpSwitch:
+            case spv::Op::OpBranchConditional:
+            case spv::Op::OpSwitch:
               break;
             default:
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
@@ -110,8 +110,9 @@
           }
         }
         break;
-      case SpvOpVariable:
-        if (inst.GetOperandAs<SpvStorageClass>(2) == SpvStorageClassFunction &&
+      case spv::Op::OpVariable:
+        if (inst.GetOperandAs<spv::StorageClass>(2) ==
+                spv::StorageClass::Function &&
             adjacency_status != IN_ENTRY_BLOCK) {
           return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                  << "All OpVariable instructions in a function must be the "
diff --git a/third_party/SPIRV-Tools/source/val/validate_annotation.cpp b/third_party/SPIRV-Tools/source/val/validate_annotation.cpp
index c27c799..2d13456 100644
--- a/third_party/SPIRV-Tools/source/val/validate_annotation.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_annotation.cpp
@@ -22,146 +22,14 @@
 namespace val {
 namespace {
 
-std::string LogStringForDecoration(uint32_t decoration) {
-  switch (decoration) {
-    case SpvDecorationRelaxedPrecision:
-      return "RelaxedPrecision";
-    case SpvDecorationSpecId:
-      return "SpecId";
-    case SpvDecorationBlock:
-      return "Block";
-    case SpvDecorationBufferBlock:
-      return "BufferBlock";
-    case SpvDecorationRowMajor:
-      return "RowMajor";
-    case SpvDecorationColMajor:
-      return "ColMajor";
-    case SpvDecorationArrayStride:
-      return "ArrayStride";
-    case SpvDecorationMatrixStride:
-      return "MatrixStride";
-    case SpvDecorationGLSLShared:
-      return "GLSLShared";
-    case SpvDecorationGLSLPacked:
-      return "GLSLPacked";
-    case SpvDecorationCPacked:
-      return "CPacked";
-    case SpvDecorationBuiltIn:
-      return "BuiltIn";
-    case SpvDecorationNoPerspective:
-      return "NoPerspective";
-    case SpvDecorationFlat:
-      return "Flat";
-    case SpvDecorationPatch:
-      return "Patch";
-    case SpvDecorationCentroid:
-      return "Centroid";
-    case SpvDecorationSample:
-      return "Sample";
-    case SpvDecorationInvariant:
-      return "Invariant";
-    case SpvDecorationRestrict:
-      return "Restrict";
-    case SpvDecorationAliased:
-      return "Aliased";
-    case SpvDecorationVolatile:
-      return "Volatile";
-    case SpvDecorationConstant:
-      return "Constant";
-    case SpvDecorationCoherent:
-      return "Coherent";
-    case SpvDecorationNonWritable:
-      return "NonWritable";
-    case SpvDecorationNonReadable:
-      return "NonReadable";
-    case SpvDecorationUniform:
-      return "Uniform";
-    case SpvDecorationSaturatedConversion:
-      return "SaturatedConversion";
-    case SpvDecorationStream:
-      return "Stream";
-    case SpvDecorationLocation:
-      return "Location";
-    case SpvDecorationComponent:
-      return "Component";
-    case SpvDecorationIndex:
-      return "Index";
-    case SpvDecorationBinding:
-      return "Binding";
-    case SpvDecorationDescriptorSet:
-      return "DescriptorSet";
-    case SpvDecorationOffset:
-      return "Offset";
-    case SpvDecorationXfbBuffer:
-      return "XfbBuffer";
-    case SpvDecorationXfbStride:
-      return "XfbStride";
-    case SpvDecorationFuncParamAttr:
-      return "FuncParamAttr";
-    case SpvDecorationFPRoundingMode:
-      return "FPRoundingMode";
-    case SpvDecorationFPFastMathMode:
-      return "FPFastMathMode";
-    case SpvDecorationLinkageAttributes:
-      return "LinkageAttributes";
-    case SpvDecorationNoContraction:
-      return "NoContraction";
-    case SpvDecorationInputAttachmentIndex:
-      return "InputAttachmentIndex";
-    case SpvDecorationAlignment:
-      return "Alignment";
-    case SpvDecorationMaxByteOffset:
-      return "MaxByteOffset";
-    case SpvDecorationAlignmentId:
-      return "AlignmentId";
-    case SpvDecorationMaxByteOffsetId:
-      return "MaxByteOffsetId";
-    case SpvDecorationNoSignedWrap:
-      return "NoSignedWrap";
-    case SpvDecorationNoUnsignedWrap:
-      return "NoUnsignedWrap";
-    case SpvDecorationExplicitInterpAMD:
-      return "ExplicitInterpAMD";
-    case SpvDecorationOverrideCoverageNV:
-      return "OverrideCoverageNV";
-    case SpvDecorationPassthroughNV:
-      return "PassthroughNV";
-    case SpvDecorationViewportRelativeNV:
-      return "ViewportRelativeNV";
-    case SpvDecorationSecondaryViewportRelativeNV:
-      return "SecondaryViewportRelativeNV";
-    case SpvDecorationPerPrimitiveNV:
-      return "PerPrimitiveNV";
-    case SpvDecorationPerViewNV:
-      return "PerViewNV";
-    case SpvDecorationPerTaskNV:
-      return "PerTaskNV";
-    case SpvDecorationPerVertexKHR:
-      return "PerVertexKHR";
-    case SpvDecorationNonUniform:
-      return "NonUniform";
-    case SpvDecorationRestrictPointer:
-      return "RestrictPointer";
-    case SpvDecorationAliasedPointer:
-      return "AliasedPointer";
-    case SpvDecorationCounterBuffer:
-      return "CounterBuffer";
-    case SpvDecorationHlslSemanticGOOGLE:
-      return "HlslSemanticGOOGLE";
-    default:
-      break;
-  }
-  return "Unknown";
-}
-
 // Returns true if the decoration takes ID parameters.
 // TODO(dneto): This can be generated from the grammar.
-bool DecorationTakesIdParameters(SpvDecoration type) {
+bool DecorationTakesIdParameters(spv::Decoration type) {
   switch (type) {
-    case SpvDecorationUniformId:
-    case SpvDecorationAlignmentId:
-    case SpvDecorationMaxByteOffsetId:
-    case SpvDecorationHlslCounterBufferGOOGLE:
+    case spv::Decoration::UniformId:
+    case spv::Decoration::AlignmentId:
+    case spv::Decoration::MaxByteOffsetId:
+    case spv::Decoration::HlslCounterBufferGOOGLE:
       return true;
     default:
       break;
@@ -169,14 +37,14 @@
   return false;
 }
 
-bool IsMemberDecorationOnly(SpvDecoration dec) {
+bool IsMemberDecorationOnly(spv::Decoration dec) {
   switch (dec) {
-    case SpvDecorationRowMajor:
-    case SpvDecorationColMajor:
-    case SpvDecorationMatrixStride:
+    case spv::Decoration::RowMajor:
+    case spv::Decoration::ColMajor:
+    case spv::Decoration::MatrixStride:
       // SPIR-V spec bug? Offset is generated on variables when dealing with
       // transform feedback.
-      // case SpvDecorationOffset:
+      // case spv::Decoration::Offset:
       return true;
     default:
       break;
@@ -184,42 +52,42 @@
   return false;
 }
 
-bool IsNotMemberDecoration(SpvDecoration dec) {
+bool IsNotMemberDecoration(spv::Decoration dec) {
   switch (dec) {
-    case SpvDecorationSpecId:
-    case SpvDecorationBlock:
-    case SpvDecorationBufferBlock:
-    case SpvDecorationArrayStride:
-    case SpvDecorationGLSLShared:
-    case SpvDecorationGLSLPacked:
-    case SpvDecorationCPacked:
+    case spv::Decoration::SpecId:
+    case spv::Decoration::Block:
+    case spv::Decoration::BufferBlock:
+    case spv::Decoration::ArrayStride:
+    case spv::Decoration::GLSLShared:
+    case spv::Decoration::GLSLPacked:
+    case spv::Decoration::CPacked:
     // TODO: https://github.com/KhronosGroup/glslang/issues/703:
     // glslang applies Restrict to structure members.
-    // case SpvDecorationRestrict:
-    case SpvDecorationAliased:
-    case SpvDecorationConstant:
-    case SpvDecorationUniform:
-    case SpvDecorationUniformId:
-    case SpvDecorationSaturatedConversion:
-    case SpvDecorationIndex:
-    case SpvDecorationBinding:
-    case SpvDecorationDescriptorSet:
-    case SpvDecorationFuncParamAttr:
-    case SpvDecorationFPRoundingMode:
-    case SpvDecorationFPFastMathMode:
-    case SpvDecorationLinkageAttributes:
-    case SpvDecorationNoContraction:
-    case SpvDecorationInputAttachmentIndex:
-    case SpvDecorationAlignment:
-    case SpvDecorationMaxByteOffset:
-    case SpvDecorationAlignmentId:
-    case SpvDecorationMaxByteOffsetId:
-    case SpvDecorationNoSignedWrap:
-    case SpvDecorationNoUnsignedWrap:
-    case SpvDecorationNonUniform:
-    case SpvDecorationRestrictPointer:
-    case SpvDecorationAliasedPointer:
-    case SpvDecorationCounterBuffer:
+    // case spv::Decoration::Restrict:
+    case spv::Decoration::Aliased:
+    case spv::Decoration::Constant:
+    case spv::Decoration::Uniform:
+    case spv::Decoration::UniformId:
+    case spv::Decoration::SaturatedConversion:
+    case spv::Decoration::Index:
+    case spv::Decoration::Binding:
+    case spv::Decoration::DescriptorSet:
+    case spv::Decoration::FuncParamAttr:
+    case spv::Decoration::FPRoundingMode:
+    case spv::Decoration::FPFastMathMode:
+    case spv::Decoration::LinkageAttributes:
+    case spv::Decoration::NoContraction:
+    case spv::Decoration::InputAttachmentIndex:
+    case spv::Decoration::Alignment:
+    case spv::Decoration::MaxByteOffset:
+    case spv::Decoration::AlignmentId:
+    case spv::Decoration::MaxByteOffsetId:
+    case spv::Decoration::NoSignedWrap:
+    case spv::Decoration::NoUnsignedWrap:
+    case spv::Decoration::NonUniform:
+    case spv::Decoration::RestrictPointer:
+    case spv::Decoration::AliasedPointer:
+    case spv::Decoration::CounterBuffer:
       return true;
     default:
       break;
@@ -227,87 +95,87 @@
   return false;
 }
 
-spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
+spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec,
                                       const Instruction* inst,
                                       const Instruction* target) {
   auto fail = [&_, dec, inst, target](uint32_t vuid) -> DiagnosticStream {
     DiagnosticStream ds = std::move(
         _.diag(SPV_ERROR_INVALID_ID, inst)
-        << _.VkErrorID(vuid) << LogStringForDecoration(dec)
-        << " decoration on target <id> '" << _.getIdName(target->id()) << "' ");
+        << _.VkErrorID(vuid) << _.SpvDecorationString(dec)
+        << " decoration on target <id> " << _.getIdName(target->id()) << " ");
     return ds;
   };
   switch (dec) {
-    case SpvDecorationSpecId:
+    case spv::Decoration::SpecId:
       if (!spvOpcodeIsScalarSpecConstant(target->opcode())) {
         return fail(0) << "must be a scalar specialization constant";
       }
       break;
-    case SpvDecorationBlock:
-    case SpvDecorationBufferBlock:
-    case SpvDecorationGLSLShared:
-    case SpvDecorationGLSLPacked:
-    case SpvDecorationCPacked:
-      if (target->opcode() != SpvOpTypeStruct) {
+    case spv::Decoration::Block:
+    case spv::Decoration::BufferBlock:
+    case spv::Decoration::GLSLShared:
+    case spv::Decoration::GLSLPacked:
+    case spv::Decoration::CPacked:
+      if (target->opcode() != spv::Op::OpTypeStruct) {
         return fail(0) << "must be a structure type";
       }
       break;
-    case SpvDecorationArrayStride:
-      if (target->opcode() != SpvOpTypeArray &&
-          target->opcode() != SpvOpTypeRuntimeArray &&
-          target->opcode() != SpvOpTypePointer) {
+    case spv::Decoration::ArrayStride:
+      if (target->opcode() != spv::Op::OpTypeArray &&
+          target->opcode() != spv::Op::OpTypeRuntimeArray &&
+          target->opcode() != spv::Op::OpTypePointer) {
         return fail(0) << "must be an array or pointer type";
       }
       break;
-    case SpvDecorationBuiltIn:
-      if (target->opcode() != SpvOpVariable &&
+    case spv::Decoration::BuiltIn:
+      if (target->opcode() != spv::Op::OpVariable &&
           !spvOpcodeIsConstant(target->opcode())) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "BuiltIns can only target variables, structure members or "
                   "constants";
       }
-      if (_.HasCapability(SpvCapabilityShader) &&
-          inst->GetOperandAs<SpvBuiltIn>(2) == SpvBuiltInWorkgroupSize) {
+      if (_.HasCapability(spv::Capability::Shader) &&
+          inst->GetOperandAs<spv::BuiltIn>(2) == spv::BuiltIn::WorkgroupSize) {
         if (!spvOpcodeIsConstant(target->opcode())) {
           return fail(0) << "must be a constant for WorkgroupSize";
         }
-      } else if (target->opcode() != SpvOpVariable) {
+      } else if (target->opcode() != spv::Op::OpVariable) {
         return fail(0) << "must be a variable";
       }
       break;
-    case SpvDecorationNoPerspective:
-    case SpvDecorationFlat:
-    case SpvDecorationPatch:
-    case SpvDecorationCentroid:
-    case SpvDecorationSample:
-    case SpvDecorationRestrict:
-    case SpvDecorationAliased:
-    case SpvDecorationVolatile:
-    case SpvDecorationCoherent:
-    case SpvDecorationNonWritable:
-    case SpvDecorationNonReadable:
-    case SpvDecorationXfbBuffer:
-    case SpvDecorationXfbStride:
-    case SpvDecorationComponent:
-    case SpvDecorationStream:
-    case SpvDecorationRestrictPointer:
-    case SpvDecorationAliasedPointer:
-      if (target->opcode() != SpvOpVariable &&
-          target->opcode() != SpvOpFunctionParameter) {
+    case spv::Decoration::NoPerspective:
+    case spv::Decoration::Flat:
+    case spv::Decoration::Patch:
+    case spv::Decoration::Centroid:
+    case spv::Decoration::Sample:
+    case spv::Decoration::Restrict:
+    case spv::Decoration::Aliased:
+    case spv::Decoration::Volatile:
+    case spv::Decoration::Coherent:
+    case spv::Decoration::NonWritable:
+    case spv::Decoration::NonReadable:
+    case spv::Decoration::XfbBuffer:
+    case spv::Decoration::XfbStride:
+    case spv::Decoration::Component:
+    case spv::Decoration::Stream:
+    case spv::Decoration::RestrictPointer:
+    case spv::Decoration::AliasedPointer:
+      if (target->opcode() != spv::Op::OpVariable &&
+          target->opcode() != spv::Op::OpFunctionParameter) {
         return fail(0) << "must be a memory object declaration";
       }
-      if (_.GetIdOpcode(target->type_id()) != SpvOpTypePointer) {
+      if (_.GetIdOpcode(target->type_id()) != spv::Op::OpTypePointer) {
         return fail(0) << "must be a pointer type";
       }
       break;
-    case SpvDecorationInvariant:
-    case SpvDecorationConstant:
-    case SpvDecorationLocation:
-    case SpvDecorationIndex:
-    case SpvDecorationBinding:
-    case SpvDecorationDescriptorSet:
-    case SpvDecorationInputAttachmentIndex:
-      if (target->opcode() != SpvOpVariable) {
+    case spv::Decoration::Invariant:
+    case spv::Decoration::Constant:
+    case spv::Decoration::Location:
+    case spv::Decoration::Index:
+    case spv::Decoration::Binding:
+    case spv::Decoration::DescriptorSet:
+    case spv::Decoration::InputAttachmentIndex:
+      if (target->opcode() != spv::Op::OpVariable) {
         return fail(0) << "must be a variable";
       }
       break;
@@ -317,57 +185,57 @@
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
     // The following were all checked as pointer types above.
-    SpvStorageClass sc = SpvStorageClassUniform;
+    spv::StorageClass sc = spv::StorageClass::Uniform;
     const auto type = _.FindDef(target->type_id());
     if (type && type->operands().size() > 2) {
-      sc = type->GetOperandAs<SpvStorageClass>(1);
+      sc = type->GetOperandAs<spv::StorageClass>(1);
     }
     switch (dec) {
-      case SpvDecorationLocation:
-      case SpvDecorationComponent:
+      case spv::Decoration::Location:
+      case spv::Decoration::Component:
         // Location is used for input, output and ray tracing stages.
-        if (sc != SpvStorageClassInput && sc != SpvStorageClassOutput &&
-            sc != SpvStorageClassRayPayloadKHR &&
-            sc != SpvStorageClassIncomingRayPayloadKHR &&
-            sc != SpvStorageClassHitAttributeKHR &&
-            sc != SpvStorageClassCallableDataKHR &&
-            sc != SpvStorageClassIncomingCallableDataKHR &&
-            sc != SpvStorageClassShaderRecordBufferKHR) {
+        if (sc != spv::StorageClass::Input && sc != spv::StorageClass::Output &&
+            sc != spv::StorageClass::RayPayloadKHR &&
+            sc != spv::StorageClass::IncomingRayPayloadKHR &&
+            sc != spv::StorageClass::HitAttributeKHR &&
+            sc != spv::StorageClass::CallableDataKHR &&
+            sc != spv::StorageClass::IncomingCallableDataKHR &&
+            sc != spv::StorageClass::ShaderRecordBufferKHR) {
           return _.diag(SPV_ERROR_INVALID_ID, target)
-                 << _.VkErrorID(6672) << LogStringForDecoration(dec)
+                 << _.VkErrorID(6672) << _.SpvDecorationString(dec)
                  << " decoration must not be applied to this storage class";
         }
         break;
-      case SpvDecorationIndex:
+      case spv::Decoration::Index:
         // Langauge from SPIR-V definition of Index
-        if (sc != SpvStorageClassOutput) {
+        if (sc != spv::StorageClass::Output) {
           return fail(0) << "must be in the Output storage class";
         }
         break;
-      case SpvDecorationBinding:
-      case SpvDecorationDescriptorSet:
-        if (sc != SpvStorageClassStorageBuffer &&
-            sc != SpvStorageClassUniform &&
-            sc != SpvStorageClassUniformConstant) {
+      case spv::Decoration::Binding:
+      case spv::Decoration::DescriptorSet:
+        if (sc != spv::StorageClass::StorageBuffer &&
+            sc != spv::StorageClass::Uniform &&
+            sc != spv::StorageClass::UniformConstant) {
           return fail(6491) << "must be in the StorageBuffer, Uniform, or "
                                "UniformConstant storage class";
         }
         break;
-      case SpvDecorationInputAttachmentIndex:
-        if (sc != SpvStorageClassUniformConstant) {
+      case spv::Decoration::InputAttachmentIndex:
+        if (sc != spv::StorageClass::UniformConstant) {
           return fail(6678) << "must be in the UniformConstant storage class";
         }
         break;
-      case SpvDecorationFlat:
-      case SpvDecorationNoPerspective:
-      case SpvDecorationCentroid:
-      case SpvDecorationSample:
-        if (sc != SpvStorageClassInput && sc != SpvStorageClassOutput) {
+      case spv::Decoration::Flat:
+      case spv::Decoration::NoPerspective:
+      case spv::Decoration::Centroid:
+      case spv::Decoration::Sample:
+        if (sc != spv::StorageClass::Input && sc != spv::StorageClass::Output) {
           return fail(4670) << "storage class must be Input or Output";
         }
         break;
-      case SpvDecorationPerVertexKHR:
-        if (sc != SpvStorageClassInput) {
+      case spv::Decoration::PerVertexKHR:
+        if (sc != spv::StorageClass::Input) {
           return fail(6777) << "storage class must be Input";
         }
         break;
@@ -379,7 +247,7 @@
 }
 
 spv_result_t ValidateDecorate(ValidationState_t& _, const Instruction* inst) {
-  const auto decoration = inst->GetOperandAs<SpvDecoration>(1);
+  const auto decoration = inst->GetOperandAs<spv::Decoration>(1);
   const auto target_id = inst->GetOperandAs<uint32_t>(0);
   const auto target = _.FindDef(target_id);
   if (!target) {
@@ -387,11 +255,11 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if ((decoration == SpvDecorationGLSLShared) ||
-        (decoration == SpvDecorationGLSLPacked)) {
+    if ((decoration == spv::Decoration::GLSLShared) ||
+        (decoration == spv::Decoration::GLSLPacked)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << _.VkErrorID(4669) << "OpDecorate decoration '"
-             << LogStringForDecoration(decoration)
+             << _.SpvDecorationString(decoration)
              << "' is not valid for the Vulkan execution environment.";
     }
   }
@@ -402,10 +270,10 @@
               "OpDecorateId";
   }
 
-  if (target->opcode() != SpvOpDecorationGroup) {
+  if (target->opcode() != spv::Op::OpDecorationGroup) {
     if (IsMemberDecorationOnly(decoration)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << LogStringForDecoration(decoration)
+             << _.SpvDecorationString(decoration)
              << " can only be applied to structure members";
     }
 
@@ -419,7 +287,7 @@
 }
 
 spv_result_t ValidateDecorateId(ValidationState_t& _, const Instruction* inst) {
-  const auto decoration = inst->GetOperandAs<SpvDecoration>(1);
+  const auto decoration = inst->GetOperandAs<spv::Decoration>(1);
   if (!DecorationTakesIdParameters(decoration)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Decorations that don't take ID parameters may not be used with "
@@ -438,10 +306,10 @@
                                     const Instruction* inst) {
   const auto struct_type_id = inst->GetOperandAs<uint32_t>(0);
   const auto struct_type = _.FindDef(struct_type_id);
-  if (!struct_type || SpvOpTypeStruct != struct_type->opcode()) {
+  if (!struct_type || spv::Op::OpTypeStruct != struct_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpMemberDecorate Structure type <id> '"
-           << _.getIdName(struct_type_id) << "' is not a struct type.";
+           << "OpMemberDecorate Structure type <id> "
+           << _.getIdName(struct_type_id) << " is not a struct type.";
   }
   const auto member = inst->GetOperandAs<uint32_t>(1);
   const auto member_count =
@@ -455,10 +323,10 @@
            << " members. Largest valid index is " << member_count - 1 << ".";
   }
 
-  const auto decoration = inst->GetOperandAs<SpvDecoration>(2);
+  const auto decoration = inst->GetOperandAs<spv::Decoration>(2);
   if (IsNotMemberDecoration(decoration)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << LogStringForDecoration(decoration)
+           << _.SpvDecorationString(decoration)
            << " cannot be applied to structure members";
   }
 
@@ -471,10 +339,11 @@
   const auto decoration_group = _.FindDef(decoration_group_id);
   for (auto pair : decoration_group->uses()) {
     auto use = pair.first;
-    if (use->opcode() != SpvOpDecorate && use->opcode() != SpvOpGroupDecorate &&
-        use->opcode() != SpvOpGroupMemberDecorate &&
-        use->opcode() != SpvOpName && use->opcode() != SpvOpDecorateId &&
-        !use->IsNonSemantic()) {
+    if (use->opcode() != spv::Op::OpDecorate &&
+        use->opcode() != spv::Op::OpGroupDecorate &&
+        use->opcode() != spv::Op::OpGroupMemberDecorate &&
+        use->opcode() != spv::Op::OpName &&
+        use->opcode() != spv::Op::OpDecorateId && !use->IsNonSemantic()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Result id of OpDecorationGroup can only "
              << "be targeted by OpName, OpGroupDecorate, "
@@ -488,19 +357,19 @@
                                    const Instruction* inst) {
   const auto decoration_group_id = inst->GetOperandAs<uint32_t>(0);
   auto decoration_group = _.FindDef(decoration_group_id);
-  if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) {
+  if (!decoration_group ||
+      spv::Op::OpDecorationGroup != decoration_group->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpGroupDecorate Decoration group <id> '"
-           << _.getIdName(decoration_group_id)
-           << "' is not a decoration group.";
+           << "OpGroupDecorate Decoration group <id> "
+           << _.getIdName(decoration_group_id) << " is not a decoration group.";
   }
   for (unsigned i = 1; i < inst->operands().size(); ++i) {
     auto target_id = inst->GetOperandAs<uint32_t>(i);
     auto target = _.FindDef(target_id);
-    if (!target || target->opcode() == SpvOpDecorationGroup) {
+    if (!target || target->opcode() == spv::Op::OpDecorationGroup) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpGroupDecorate may not target OpDecorationGroup <id> '"
-             << _.getIdName(target_id) << "'";
+             << "OpGroupDecorate may not target OpDecorationGroup <id> "
+             << _.getIdName(target_id);
     }
   }
   return SPV_SUCCESS;
@@ -510,11 +379,11 @@
                                          const Instruction* inst) {
   const auto decoration_group_id = inst->GetOperandAs<uint32_t>(0);
   const auto decoration_group = _.FindDef(decoration_group_id);
-  if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) {
+  if (!decoration_group ||
+      spv::Op::OpDecorationGroup != decoration_group->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpGroupMemberDecorate Decoration group <id> '"
-           << _.getIdName(decoration_group_id)
-           << "' is not a decoration group.";
+           << "OpGroupMemberDecorate Decoration group <id> "
+           << _.getIdName(decoration_group_id) << " is not a decoration group.";
   }
   // Grammar checks ensures that the number of arguments to this instruction
   // is an odd number: 1 decoration group + (id,literal) pairs.
@@ -522,10 +391,10 @@
     const uint32_t struct_id = inst->GetOperandAs<uint32_t>(i);
     const uint32_t index = inst->GetOperandAs<uint32_t>(i + 1);
     auto struct_instr = _.FindDef(struct_id);
-    if (!struct_instr || SpvOpTypeStruct != struct_instr->opcode()) {
+    if (!struct_instr || spv::Op::OpTypeStruct != struct_instr->opcode()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpGroupMemberDecorate Structure type <id> '"
-             << _.getIdName(struct_id) << "' is not a struct type.";
+             << "OpGroupMemberDecorate Structure type <id> "
+             << _.getIdName(struct_id) << " is not a struct type.";
     }
     const uint32_t num_struct_members =
         static_cast<uint32_t>(struct_instr->words().size() - 2);
@@ -547,10 +416,11 @@
 spv_result_t RegisterDecorations(ValidationState_t& _,
                                  const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId: {
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId: {
       const uint32_t target_id = inst->word(1);
-      const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->word(2));
+      const spv::Decoration dec_type =
+          static_cast<spv::Decoration>(inst->word(2));
       std::vector<uint32_t> dec_params;
       if (inst->words().size() > 3) {
         dec_params.insert(dec_params.end(), inst->words().begin() + 3,
@@ -559,10 +429,11 @@
       _.RegisterDecorationForId(target_id, Decoration(dec_type, dec_params));
       break;
     }
-    case SpvOpMemberDecorate: {
+    case spv::Op::OpMemberDecorate: {
       const uint32_t struct_id = inst->word(1);
       const uint32_t index = inst->word(2);
-      const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->word(3));
+      const spv::Decoration dec_type =
+          static_cast<spv::Decoration>(inst->word(3));
       std::vector<uint32_t> dec_params;
       if (inst->words().size() > 4) {
         dec_params.insert(dec_params.end(), inst->words().begin() + 4,
@@ -572,12 +443,12 @@
                                 Decoration(dec_type, dec_params, index));
       break;
     }
-    case SpvOpDecorationGroup: {
+    case spv::Op::OpDecorationGroup: {
       // We don't need to do anything right now. Assigning decorations to groups
       // will be taken care of via OpGroupDecorate.
       break;
     }
-    case SpvOpGroupDecorate: {
+    case spv::Op::OpGroupDecorate: {
       // Word 1 is the group <id>. All subsequent words are target <id>s that
       // are going to be decorated with the decorations.
       const uint32_t decoration_group_id = inst->word(1);
@@ -590,7 +461,7 @@
       }
       break;
     }
-    case SpvOpGroupMemberDecorate: {
+    case spv::Op::OpGroupMemberDecorate: {
       // Word 1 is the Decoration Group <id> followed by (struct<id>,literal)
       // pairs. All decorations of the group should be applied to all the struct
       // members that are specified in the instructions.
@@ -620,24 +491,24 @@
 
 spv_result_t AnnotationPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpDecorate:
+    case spv::Op::OpDecorate:
       if (auto error = ValidateDecorate(_, inst)) return error;
       break;
-    case SpvOpDecorateId:
+    case spv::Op::OpDecorateId:
       if (auto error = ValidateDecorateId(_, inst)) return error;
       break;
-    // TODO(dneto): SpvOpDecorateStringGOOGLE
+    // TODO(dneto): spv::Op::OpDecorateStringGOOGLE
     // See https://github.com/KhronosGroup/SPIRV-Tools/issues/2253
-    case SpvOpMemberDecorate:
+    case spv::Op::OpMemberDecorate:
       if (auto error = ValidateMemberDecorate(_, inst)) return error;
       break;
-    case SpvOpDecorationGroup:
+    case spv::Op::OpDecorationGroup:
       if (auto error = ValidateDecorationGroup(_, inst)) return error;
       break;
-    case SpvOpGroupDecorate:
+    case spv::Op::OpGroupDecorate:
       if (auto error = ValidateGroupDecorate(_, inst)) return error;
       break;
-    case SpvOpGroupMemberDecorate:
+    case spv::Op::OpGroupMemberDecorate:
       if (auto error = ValidateGroupMemberDecorate(_, inst)) return error;
       break;
     default:
diff --git a/third_party/SPIRV-Tools/source/val/validate_arithmetics.cpp b/third_party/SPIRV-Tools/source/val/validate_arithmetics.cpp
index bae9b5d..a082eeb 100644
--- a/third_party/SPIRV-Tools/source/val/validate_arithmetics.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_arithmetics.cpp
@@ -28,19 +28,20 @@
 
 // Validates correctness of arithmetic instructions.
 spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpFAdd:
-    case SpvOpFSub:
-    case SpvOpFMul:
-    case SpvOpFDiv:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpFNegate: {
+    case spv::Op::OpFAdd:
+    case spv::Op::OpFSub:
+    case spv::Op::OpFMul:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpFNegate: {
       bool supportsCoopMat =
-          (opcode != SpvOpFMul && opcode != SpvOpFRem && opcode != SpvOpFMod);
+          (opcode != spv::Op::OpFMul && opcode != spv::Op::OpFRem &&
+           opcode != spv::Op::OpFMod);
       if (!_.IsFloatScalarType(result_type) &&
           !_.IsFloatVectorType(result_type) &&
           !(supportsCoopMat && _.IsFloatCooperativeMatrixType(result_type)))
@@ -59,9 +60,9 @@
       break;
     }
 
-    case SpvOpUDiv:
-    case SpvOpUMod: {
-      bool supportsCoopMat = (opcode == SpvOpUDiv);
+    case spv::Op::OpUDiv:
+    case spv::Op::OpUMod: {
+      bool supportsCoopMat = (opcode == spv::Op::OpUDiv);
       if (!_.IsUnsignedIntScalarType(result_type) &&
           !_.IsUnsignedIntVectorType(result_type) &&
           !(supportsCoopMat &&
@@ -81,15 +82,16 @@
       break;
     }
 
-    case SpvOpISub:
-    case SpvOpIAdd:
-    case SpvOpIMul:
-    case SpvOpSDiv:
-    case SpvOpSMod:
-    case SpvOpSRem:
-    case SpvOpSNegate: {
+    case spv::Op::OpISub:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpIMul:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpSMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSNegate: {
       bool supportsCoopMat =
-          (opcode != SpvOpIMul && opcode != SpvOpSRem && opcode != SpvOpSMod);
+          (opcode != spv::Op::OpIMul && opcode != spv::Op::OpSRem &&
+           opcode != spv::Op::OpSMod);
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
           !(supportsCoopMat && _.IsIntCooperativeMatrixType(result_type)))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -125,7 +127,7 @@
       break;
     }
 
-    case SpvOpDot: {
+    case spv::Op::OpDot: {
       if (!_.IsFloatScalarType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected float scalar type as Result Type: "
@@ -162,7 +164,7 @@
       break;
     }
 
-    case SpvOpVectorTimesScalar: {
+    case spv::Op::OpVectorTimesScalar: {
       if (!_.IsFloatVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected float vector type as Result Type: "
@@ -185,7 +187,7 @@
       break;
     }
 
-    case SpvOpMatrixTimesScalar: {
+    case spv::Op::OpMatrixTimesScalar: {
       if (!_.IsFloatMatrixType(result_type) &&
           !_.IsCooperativeMatrixType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -209,7 +211,7 @@
       break;
     }
 
-    case SpvOpVectorTimesMatrix: {
+    case spv::Op::OpVectorTimesMatrix: {
       const uint32_t vector_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 3);
 
@@ -259,7 +261,7 @@
       break;
     }
 
-    case SpvOpMatrixTimesVector: {
+    case spv::Op::OpMatrixTimesVector: {
       const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t vector_type_id = _.GetOperandTypeId(inst, 3);
 
@@ -303,7 +305,7 @@
       break;
     }
 
-    case SpvOpMatrixTimesMatrix: {
+    case spv::Op::OpMatrixTimesMatrix: {
       const uint32_t left_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t right_type_id = _.GetOperandTypeId(inst, 3);
 
@@ -369,7 +371,7 @@
       break;
     }
 
-    case SpvOpOuterProduct: {
+    case spv::Op::OpOuterProduct: {
       const uint32_t left_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t right_type_id = _.GetOperandTypeId(inst, 3);
 
@@ -407,10 +409,10 @@
       break;
     }
 
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended: {
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended: {
       std::vector<uint32_t> result_types;
       if (!_.GetStructMemberTypes(result_type, &result_types))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -422,7 +424,7 @@
                << "Expected Result Type struct to have two members: "
                << spvOpcodeString(opcode);
 
-      if (opcode == SpvOpSMulExtended) {
+      if (opcode == spv::Op::OpSMulExtended) {
         if (!_.IsIntScalarType(result_types[0]) &&
             !_.IsIntVectorType(result_types[0]))
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -453,7 +455,7 @@
       break;
     }
 
-    case SpvOpCooperativeMatrixMulAddNV: {
+    case spv::Op::OpCooperativeMatrixMulAddNV: {
       const uint32_t D_type_id = _.GetOperandTypeId(inst, 1);
       const uint32_t A_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t B_type_id = _.GetOperandTypeId(inst, 3);
diff --git a/third_party/SPIRV-Tools/source/val/validate_atomics.cpp b/third_party/SPIRV-Tools/source/val/validate_atomics.cpp
index 3b0a7fa..d6b094c 100644
--- a/third_party/SPIRV-Tools/source/val/validate_atomics.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_atomics.cpp
@@ -29,17 +29,18 @@
 
 namespace {
 
-bool IsStorageClassAllowedByUniversalRules(uint32_t storage_class) {
+bool IsStorageClassAllowedByUniversalRules(spv::StorageClass storage_class) {
   switch (storage_class) {
-    case SpvStorageClassUniform:
-    case SpvStorageClassStorageBuffer:
-    case SpvStorageClassWorkgroup:
-    case SpvStorageClassCrossWorkgroup:
-    case SpvStorageClassGeneric:
-    case SpvStorageClassAtomicCounter:
-    case SpvStorageClassImage:
-    case SpvStorageClassFunction:
-    case SpvStorageClassPhysicalStorageBuffer:
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::StorageBuffer:
+    case spv::StorageClass::Workgroup:
+    case spv::StorageClass::CrossWorkgroup:
+    case spv::StorageClass::Generic:
+    case spv::StorageClass::AtomicCounter:
+    case spv::StorageClass::Image:
+    case spv::StorageClass::Function:
+    case spv::StorageClass::PhysicalStorageBuffer:
+    case spv::StorageClass::TaskPayloadWorkgroupEXT:
       return true;
       break;
     default:
@@ -47,10 +48,10 @@
   }
 }
 
-bool HasReturnType(uint32_t opcode) {
+bool HasReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicStore:
-    case SpvOpAtomicFlagClear:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicFlagClear:
       return false;
       break;
     default:
@@ -58,11 +59,11 @@
   }
 }
 
-bool HasOnlyFloatReturnType(uint32_t opcode) {
+bool HasOnlyFloatReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicFAddEXT:
-    case SpvOpAtomicFMinEXT:
-    case SpvOpAtomicFMaxEXT:
+    case spv::Op::OpAtomicFAddEXT:
+    case spv::Op::OpAtomicFMinEXT:
+    case spv::Op::OpAtomicFMaxEXT:
       return true;
       break;
     default:
@@ -70,21 +71,21 @@
   }
 }
 
-bool HasOnlyIntReturnType(uint32_t opcode) {
+bool HasOnlyIntReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
       return true;
       break;
     default:
@@ -92,10 +93,10 @@
   }
 }
 
-bool HasIntOrFloatReturnType(uint32_t opcode) {
+bool HasIntOrFloatReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
       return true;
       break;
     default:
@@ -103,9 +104,9 @@
   }
 }
 
-bool HasOnlyBoolReturnType(uint32_t opcode) {
+bool HasOnlyBoolReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return true;
       break;
     default:
@@ -120,29 +121,29 @@
 
 // Validates correctness of atomic instructions.
 spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   switch (opcode) {
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicFAddEXT:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicFMinEXT:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicFMaxEXT:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
-    case SpvOpAtomicFlagClear: {
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicFAddEXT:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicFMinEXT:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicFMaxEXT:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicFlagClear: {
       const uint32_t result_type = inst->type_id();
 
       // All current atomics only are scalar result
@@ -176,7 +177,7 @@
       uint32_t operand_index = HasReturnType(opcode) ? 2 : 0;
       const uint32_t pointer_type = _.GetOperandTypeId(inst, operand_index++);
       uint32_t data_type = 0;
-      uint32_t storage_class = 0;
+      spv::StorageClass storage_class;
       if (!_.GetPointerTypeInfo(pointer_type, &data_type, &storage_class)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
@@ -184,8 +185,8 @@
       }
 
       // Can't use result_type because OpAtomicStore doesn't have a result
-      if ( _.IsIntScalarType(data_type) &&_.GetBitWidth(data_type) == 64 &&
-          !_.HasCapability(SpvCapabilityInt64Atomics)) {
+      if (_.IsIntScalarType(data_type) && _.GetBitWidth(data_type) == 64 &&
+          !_.HasCapability(spv::Capability::Int64Atomics)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
                << ": 64-bit atomics require the Int64Atomics capability";
@@ -199,68 +200,69 @@
       }
 
       // Then Shader rules
-      if (_.HasCapability(SpvCapabilityShader)) {
+      if (_.HasCapability(spv::Capability::Shader)) {
         // Vulkan environment rule
         if (spvIsVulkanEnv(_.context()->target_env)) {
-          if ((storage_class != SpvStorageClassUniform) &&
-              (storage_class != SpvStorageClassStorageBuffer) &&
-              (storage_class != SpvStorageClassWorkgroup) &&
-              (storage_class != SpvStorageClassImage) &&
-              (storage_class != SpvStorageClassPhysicalStorageBuffer)) {
+          if ((storage_class != spv::StorageClass::Uniform) &&
+              (storage_class != spv::StorageClass::StorageBuffer) &&
+              (storage_class != spv::StorageClass::Workgroup) &&
+              (storage_class != spv::StorageClass::Image) &&
+              (storage_class != spv::StorageClass::PhysicalStorageBuffer) &&
+              (storage_class != spv::StorageClass::TaskPayloadWorkgroupEXT)) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << _.VkErrorID(4686) << spvOpcodeString(opcode)
                    << ": Vulkan spec only allows storage classes for atomic to "
-                      "be: Uniform, Workgroup, Image, StorageBuffer, or "
-                      "PhysicalStorageBuffer.";
+                      "be: Uniform, Workgroup, Image, StorageBuffer, "
+                      "PhysicalStorageBuffer or TaskPayloadWorkgroupEXT.";
           }
-        } else if (storage_class == SpvStorageClassFunction) {
+        } else if (storage_class == spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << spvOpcodeString(opcode)
                  << ": Function storage class forbidden when the Shader "
                     "capability is declared.";
         }
 
-        if (opcode == SpvOpAtomicFAddEXT) {
+        if (opcode == spv::Op::OpAtomicFAddEXT) {
           // result type being float checked already
           if ((_.GetBitWidth(result_type) == 16) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat16AddEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat16AddEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float add atomics require the AtomicFloat32AddEXT "
                       "capability";
           }
           if ((_.GetBitWidth(result_type) == 32) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat32AddEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat32AddEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float add atomics require the AtomicFloat32AddEXT "
                       "capability";
           }
           if ((_.GetBitWidth(result_type) == 64) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat64AddEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat64AddEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float add atomics require the AtomicFloat64AddEXT "
                       "capability";
           }
-        } else if (opcode == SpvOpAtomicFMinEXT ||
-                   opcode == SpvOpAtomicFMaxEXT) {
+        } else if (opcode == spv::Op::OpAtomicFMinEXT ||
+                   opcode == spv::Op::OpAtomicFMaxEXT) {
           if ((_.GetBitWidth(result_type) == 16) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat16MinMaxEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat16MinMaxEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float min/max atomics require the "
                       "AtomicFloat16MinMaxEXT capability";
           }
           if ((_.GetBitWidth(result_type) == 32) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat32MinMaxEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat32MinMaxEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float min/max atomics require the "
                       "AtomicFloat32MinMaxEXT capability";
           }
           if ((_.GetBitWidth(result_type) == 64) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat64MinMaxEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat64MinMaxEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float min/max atomics require the "
@@ -271,10 +273,10 @@
 
       // And finally OpenCL environment rules
       if (spvIsOpenCLEnv(_.context()->target_env)) {
-        if ((storage_class != SpvStorageClassFunction) &&
-            (storage_class != SpvStorageClassWorkgroup) &&
-            (storage_class != SpvStorageClassCrossWorkgroup) &&
-            (storage_class != SpvStorageClassGeneric)) {
+        if ((storage_class != spv::StorageClass::Function) &&
+            (storage_class != spv::StorageClass::Workgroup) &&
+            (storage_class != spv::StorageClass::CrossWorkgroup) &&
+            (storage_class != spv::StorageClass::Generic)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << spvOpcodeString(opcode)
                  << ": storage class must be Function, Workgroup, "
@@ -282,7 +284,7 @@
         }
 
         if (_.context()->target_env == SPV_ENV_OPENCL_1_2) {
-          if (storage_class == SpvStorageClassGeneric) {
+          if (storage_class == spv::StorageClass::Generic) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << "Storage class cannot be Generic in OpenCL 1.2 "
                       "environment";
@@ -291,15 +293,15 @@
       }
 
       // If result and pointer type are different, need to do special check here
-      if (opcode == SpvOpAtomicFlagTestAndSet ||
-          opcode == SpvOpAtomicFlagClear) {
+      if (opcode == spv::Op::OpAtomicFlagTestAndSet ||
+          opcode == spv::Op::OpAtomicFlagClear) {
         if (!_.IsIntScalarType(data_type) || _.GetBitWidth(data_type) != 32) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << spvOpcodeString(opcode)
                  << ": expected Pointer to point to a value of 32-bit integer "
                     "type";
         }
-      } else if (opcode == SpvOpAtomicStore) {
+      } else if (opcode == spv::Op::OpAtomicStore) {
         if (!_.IsFloatScalarType(data_type) && !_.IsIntScalarType(data_type)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << spvOpcodeString(opcode)
@@ -323,8 +325,8 @@
                                                memory_scope))
         return error;
 
-      if (opcode == SpvOpAtomicCompareExchange ||
-          opcode == SpvOpAtomicCompareExchangeWeak) {
+      if (opcode == spv::Op::OpAtomicCompareExchange ||
+          opcode == spv::Op::OpAtomicCompareExchangeWeak) {
         const auto unequal_semantics_index = operand_index++;
         if (auto error = ValidateMemorySemantics(
                 _, inst, unequal_semantics_index, memory_scope))
@@ -344,15 +346,15 @@
             _.EvalInt32IfConst(
                 inst->GetOperandAs<uint32_t>(unequal_semantics_index));
         if (is_equal_const && is_unequal_const &&
-            ((equal_value & SpvMemorySemanticsVolatileMask) ^
-             (unequal_value & SpvMemorySemanticsVolatileMask))) {
+            ((equal_value & uint32_t(spv::MemorySemanticsMask::Volatile)) ^
+             (unequal_value & uint32_t(spv::MemorySemanticsMask::Volatile)))) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << "Volatile mask setting must match for Equal and Unequal "
                     "memory semantics";
         }
       }
 
-      if (opcode == SpvOpAtomicStore) {
+      if (opcode == spv::Op::OpAtomicStore) {
         const uint32_t value_type = _.GetOperandTypeId(inst, 3);
         if (value_type != data_type) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -360,10 +362,11 @@
                  << ": expected Value type and the type pointed to by "
                     "Pointer to be the same";
         }
-      } else if (opcode != SpvOpAtomicLoad && opcode != SpvOpAtomicIIncrement &&
-                 opcode != SpvOpAtomicIDecrement &&
-                 opcode != SpvOpAtomicFlagTestAndSet &&
-                 opcode != SpvOpAtomicFlagClear) {
+      } else if (opcode != spv::Op::OpAtomicLoad &&
+                 opcode != spv::Op::OpAtomicIIncrement &&
+                 opcode != spv::Op::OpAtomicIDecrement &&
+                 opcode != spv::Op::OpAtomicFlagTestAndSet &&
+                 opcode != spv::Op::OpAtomicFlagClear) {
         const uint32_t value_type = _.GetOperandTypeId(inst, operand_index++);
         if (value_type != result_type) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -372,8 +375,8 @@
         }
       }
 
-      if (opcode == SpvOpAtomicCompareExchange ||
-          opcode == SpvOpAtomicCompareExchangeWeak) {
+      if (opcode == spv::Op::OpAtomicCompareExchange ||
+          opcode == spv::Op::OpAtomicCompareExchangeWeak) {
         const uint32_t comparator_type =
             _.GetOperandTypeId(inst, operand_index++);
         if (comparator_type != result_type) {
diff --git a/third_party/SPIRV-Tools/source/val/validate_barriers.cpp b/third_party/SPIRV-Tools/source/val/validate_barriers.cpp
index 3a9e3e7..59d886a 100644
--- a/third_party/SPIRV-Tools/source/val/validate_barriers.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_barriers.cpp
@@ -32,25 +32,26 @@
 
 // Validates correctness of barrier instructions.
 spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpControlBarrier: {
+    case spv::Op::OpControlBarrier: {
       if (_.version() < SPV_SPIRV_VERSION_WORD(1, 3)) {
         _.function(inst->function()->id())
             ->RegisterExecutionModelLimitation(
-                [](SpvExecutionModel model, std::string* message) {
-                  if (model != SpvExecutionModelTessellationControl &&
-                      model != SpvExecutionModelGLCompute &&
-                      model != SpvExecutionModelKernel &&
-                      model != SpvExecutionModelTaskNV &&
-                      model != SpvExecutionModelMeshNV) {
+                [](spv::ExecutionModel model, std::string* message) {
+                  if (model != spv::ExecutionModel::TessellationControl &&
+                      model != spv::ExecutionModel::GLCompute &&
+                      model != spv::ExecutionModel::Kernel &&
+                      model != spv::ExecutionModel::TaskNV &&
+                      model != spv::ExecutionModel::MeshNV) {
                     if (message) {
                       *message =
                           "OpControlBarrier requires one of the following "
                           "Execution "
-                          "Models: TessellationControl, GLCompute or Kernel";
+                          "Models: TessellationControl, GLCompute, Kernel, "
+                          "MeshNV or TaskNV";
                     }
                     return false;
                   }
@@ -75,7 +76,7 @@
       break;
     }
 
-    case SpvOpMemoryBarrier: {
+    case spv::Op::OpMemoryBarrier: {
       const uint32_t memory_scope = inst->word(1);
 
       if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
@@ -88,8 +89,8 @@
       break;
     }
 
-    case SpvOpNamedBarrierInitialize: {
-      if (_.GetIdOpcode(result_type) != SpvOpTypeNamedBarrier) {
+    case spv::Op::OpNamedBarrierInitialize: {
+      if (_.GetIdOpcode(result_type) != spv::Op::OpTypeNamedBarrier) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
                << ": expected Result Type to be OpTypeNamedBarrier";
@@ -105,9 +106,9 @@
       break;
     }
 
-    case SpvOpMemoryNamedBarrier: {
+    case spv::Op::OpMemoryNamedBarrier: {
       const uint32_t named_barrier_type = _.GetOperandTypeId(inst, 0);
-      if (_.GetIdOpcode(named_barrier_type) != SpvOpTypeNamedBarrier) {
+      if (_.GetIdOpcode(named_barrier_type) != spv::Op::OpTypeNamedBarrier) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
                << ": expected Named Barrier to be of type OpTypeNamedBarrier";
diff --git a/third_party/SPIRV-Tools/source/val/validate_bitwise.cpp b/third_party/SPIRV-Tools/source/val/validate_bitwise.cpp
index e6e97c4..87c9556 100644
--- a/third_party/SPIRV-Tools/source/val/validate_bitwise.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_bitwise.cpp
@@ -27,7 +27,7 @@
 // Validates when base and result need to be the same type
 spv_result_t ValidateBaseType(ValidationState_t& _, const Instruction* inst,
                               const uint32_t base_type) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   if (!_.IsIntScalarType(base_type) && !_.IsIntVectorType(base_type)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -47,7 +47,7 @@
   }
 
   // OpBitCount just needs same number of components
-  if (base_type != inst->type_id() && opcode != SpvOpBitCount) {
+  if (base_type != inst->type_id() && opcode != spv::Op::OpBitCount) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Base Type to be equal to Result Type: "
            << spvOpcodeString(opcode);
@@ -58,13 +58,13 @@
 
 // Validates correctness of bitwise instructions.
 spv_result_t BitwisePass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical: {
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar or vector type as Result Type: "
@@ -103,10 +103,10 @@
       break;
     }
 
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot: {
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar or vector type as Result Type: "
@@ -140,7 +140,7 @@
       break;
     }
 
-    case SpvOpBitFieldInsert: {
+    case spv::Op::OpBitFieldInsert: {
       const uint32_t base_type = _.GetOperandTypeId(inst, 2);
       const uint32_t insert_type = _.GetOperandTypeId(inst, 3);
       const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
@@ -167,8 +167,8 @@
       break;
     }
 
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract: {
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract: {
       const uint32_t base_type = _.GetOperandTypeId(inst, 2);
       const uint32_t offset_type = _.GetOperandTypeId(inst, 3);
       const uint32_t count_type = _.GetOperandTypeId(inst, 4);
@@ -189,7 +189,7 @@
       break;
     }
 
-    case SpvOpBitReverse: {
+    case spv::Op::OpBitReverse: {
       const uint32_t base_type = _.GetOperandTypeId(inst, 2);
 
       if (spv_result_t error = ValidateBaseType(_, inst, base_type)) {
@@ -199,7 +199,7 @@
       break;
     }
 
-    case SpvOpBitCount: {
+    case spv::Op::OpBitCount: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar or vector type as Result Type: "
diff --git a/third_party/SPIRV-Tools/source/val/validate_builtins.cpp b/third_party/SPIRV-Tools/source/val/validate_builtins.cpp
index 379705a..c07dcad 100644
--- a/third_party/SPIRV-Tools/source/val/validate_builtins.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_builtins.cpp
@@ -62,7 +62,7 @@
                                const Instruction& inst,
                                uint32_t* underlying_type) {
   if (decoration.struct_member_index() != Decoration::kInvalidMember) {
-    if (inst.opcode() != SpvOpTypeStruct) {
+    if (inst.opcode() != spv::Op::OpTypeStruct) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << GetIdDesc(inst)
              << "Attempted to get underlying data type via member index for "
@@ -72,7 +72,7 @@
     return SPV_SUCCESS;
   }
 
-  if (inst.opcode() == SpvOpTypeStruct) {
+  if (inst.opcode() == spv::Op::OpTypeStruct) {
     return _.diag(SPV_ERROR_INVALID_DATA, &inst)
            << GetIdDesc(inst)
            << " did not find an member index to get underlying data type for "
@@ -84,7 +84,7 @@
     return SPV_SUCCESS;
   }
 
-  uint32_t storage_class = 0;
+  spv::StorageClass storage_class;
   if (!_.GetPointerTypeInfo(inst.type_id(), underlying_type, &storage_class)) {
     return _.diag(SPV_ERROR_INVALID_DATA, &inst)
            << GetIdDesc(inst)
@@ -95,22 +95,22 @@
 }
 
 // Returns Storage Class used by the instruction if applicable.
-// Returns SpvStorageClassMax if not.
-SpvStorageClass GetStorageClass(const Instruction& inst) {
+// Returns spv::StorageClass::Max if not.
+spv::StorageClass GetStorageClass(const Instruction& inst) {
   switch (inst.opcode()) {
-    case SpvOpTypePointer:
-    case SpvOpTypeForwardPointer: {
-      return SpvStorageClass(inst.word(2));
+    case spv::Op::OpTypePointer:
+    case spv::Op::OpTypeForwardPointer: {
+      return spv::StorageClass(inst.word(2));
     }
-    case SpvOpVariable: {
-      return SpvStorageClass(inst.word(3));
+    case spv::Op::OpVariable: {
+      return spv::StorageClass(inst.word(3));
     }
-    case SpvOpGenericCastToPtrExplicit: {
-      return SpvStorageClass(inst.word(4));
+    case spv::Op::OpGenericCastToPtrExplicit: {
+      return spv::StorageClass(inst.word(4));
     }
     default: { break; }
   }
-  return SpvStorageClassMax;
+  return spv::StorageClass::Max;
 }
 
 typedef enum VUIDError_ {
@@ -123,52 +123,52 @@
 const static uint32_t NumVUIDBuiltins = 36;
 
 typedef struct {
-  SpvBuiltIn builtIn;
+  spv::BuiltIn builtIn;
   uint32_t vuid[VUIDErrorMax];  // execution mode, storage class, type VUIDs
 } BuiltinVUIDMapping;
 
 std::array<BuiltinVUIDMapping, NumVUIDBuiltins> builtinVUIDInfo = {{
     // clang-format off
-    {SpvBuiltInSubgroupEqMask,            {0,    4370, 4371}},
-    {SpvBuiltInSubgroupGeMask,            {0,    4372, 4373}},
-    {SpvBuiltInSubgroupGtMask,            {0,    4374, 4375}},
-    {SpvBuiltInSubgroupLeMask,            {0,    4376, 4377}},
-    {SpvBuiltInSubgroupLtMask,            {0,    4378, 4379}},
-    {SpvBuiltInSubgroupLocalInvocationId, {0,    4380, 4381}},
-    {SpvBuiltInSubgroupSize,              {0,    4382, 4383}},
-    {SpvBuiltInGlobalInvocationId,        {4236, 4237, 4238}},
-    {SpvBuiltInLocalInvocationId,         {4281, 4282, 4283}},
-    {SpvBuiltInNumWorkgroups,             {4296, 4297, 4298}},
-    {SpvBuiltInNumSubgroups,              {4293, 4294, 4295}},
-    {SpvBuiltInSubgroupId,                {4367, 4368, 4369}},
-    {SpvBuiltInWorkgroupId,               {4422, 4423, 4424}},
-    {SpvBuiltInHitKindKHR,                {4242, 4243, 4244}},
-    {SpvBuiltInHitTNV,                    {4245, 4246, 4247}},
-    {SpvBuiltInInstanceCustomIndexKHR,    {4251, 4252, 4253}},
-    {SpvBuiltInInstanceId,                {4254, 4255, 4256}},
-    {SpvBuiltInRayGeometryIndexKHR,       {4345, 4346, 4347}},
-    {SpvBuiltInObjectRayDirectionKHR,     {4299, 4300, 4301}},
-    {SpvBuiltInObjectRayOriginKHR,        {4302, 4303, 4304}},
-    {SpvBuiltInObjectToWorldKHR,          {4305, 4306, 4307}},
-    {SpvBuiltInWorldToObjectKHR,          {4434, 4435, 4436}},
-    {SpvBuiltInIncomingRayFlagsKHR,       {4248, 4249, 4250}},
-    {SpvBuiltInRayTminKHR,                {4351, 4352, 4353}},
-    {SpvBuiltInRayTmaxKHR,                {4348, 4349, 4350}},
-    {SpvBuiltInWorldRayDirectionKHR,      {4428, 4429, 4430}},
-    {SpvBuiltInWorldRayOriginKHR,         {4431, 4432, 4433}},
-    {SpvBuiltInLaunchIdKHR,               {4266, 4267, 4268}},
-    {SpvBuiltInLaunchSizeKHR,             {4269, 4270, 4271}},
-    {SpvBuiltInFragInvocationCountEXT,    {4217, 4218, 4219}},
-    {SpvBuiltInFragSizeEXT,               {4220, 4221, 4222}},
-    {SpvBuiltInFragStencilRefEXT,         {4223, 4224, 4225}},
-    {SpvBuiltInFullyCoveredEXT,           {4232, 4233, 4234}},
-    {SpvBuiltInCullMaskKHR,               {6735, 6736, 6737}},
-    {SpvBuiltInBaryCoordKHR,              {4154, 4155, 4156}},
-    {SpvBuiltInBaryCoordNoPerspKHR,       {4160, 4161, 4162}},
+    {spv::BuiltIn::SubgroupEqMask,            {0,    4370, 4371}},
+    {spv::BuiltIn::SubgroupGeMask,            {0,    4372, 4373}},
+    {spv::BuiltIn::SubgroupGtMask,            {0,    4374, 4375}},
+    {spv::BuiltIn::SubgroupLeMask,            {0,    4376, 4377}},
+    {spv::BuiltIn::SubgroupLtMask,            {0,    4378, 4379}},
+    {spv::BuiltIn::SubgroupLocalInvocationId, {0,    4380, 4381}},
+    {spv::BuiltIn::SubgroupSize,              {0,    4382, 4383}},
+    {spv::BuiltIn::GlobalInvocationId,        {4236, 4237, 4238}},
+    {spv::BuiltIn::LocalInvocationId,         {4281, 4282, 4283}},
+    {spv::BuiltIn::NumWorkgroups,             {4296, 4297, 4298}},
+    {spv::BuiltIn::NumSubgroups,              {4293, 4294, 4295}},
+    {spv::BuiltIn::SubgroupId,                {4367, 4368, 4369}},
+    {spv::BuiltIn::WorkgroupId,               {4422, 4423, 4424}},
+    {spv::BuiltIn::HitKindKHR,                {4242, 4243, 4244}},
+    {spv::BuiltIn::HitTNV,                    {4245, 4246, 4247}},
+    {spv::BuiltIn::InstanceCustomIndexKHR,    {4251, 4252, 4253}},
+    {spv::BuiltIn::InstanceId,                {4254, 4255, 4256}},
+    {spv::BuiltIn::RayGeometryIndexKHR,       {4345, 4346, 4347}},
+    {spv::BuiltIn::ObjectRayDirectionKHR,     {4299, 4300, 4301}},
+    {spv::BuiltIn::ObjectRayOriginKHR,        {4302, 4303, 4304}},
+    {spv::BuiltIn::ObjectToWorldKHR,          {4305, 4306, 4307}},
+    {spv::BuiltIn::WorldToObjectKHR,          {4434, 4435, 4436}},
+    {spv::BuiltIn::IncomingRayFlagsKHR,       {4248, 4249, 4250}},
+    {spv::BuiltIn::RayTminKHR,                {4351, 4352, 4353}},
+    {spv::BuiltIn::RayTmaxKHR,                {4348, 4349, 4350}},
+    {spv::BuiltIn::WorldRayDirectionKHR,      {4428, 4429, 4430}},
+    {spv::BuiltIn::WorldRayOriginKHR,         {4431, 4432, 4433}},
+    {spv::BuiltIn::LaunchIdKHR,               {4266, 4267, 4268}},
+    {spv::BuiltIn::LaunchSizeKHR,             {4269, 4270, 4271}},
+    {spv::BuiltIn::FragInvocationCountEXT,    {4217, 4218, 4219}},
+    {spv::BuiltIn::FragSizeEXT,               {4220, 4221, 4222}},
+    {spv::BuiltIn::FragStencilRefEXT,         {4223, 4224, 4225}},
+    {spv::BuiltIn::FullyCoveredEXT,           {4232, 4233, 4234}},
+    {spv::BuiltIn::CullMaskKHR,               {6735, 6736, 6737}},
+    {spv::BuiltIn::BaryCoordKHR,              {4154, 4155, 4156}},
+    {spv::BuiltIn::BaryCoordNoPerspKHR,       {4160, 4161, 4162}},
     // clang-format off
 } };
 
-uint32_t GetVUIDForBuiltin(SpvBuiltIn builtIn, VUIDError type) {
+uint32_t GetVUIDForBuiltin(spv::BuiltIn builtIn, VUIDError type) {
   uint32_t vuid = 0;
   for (const auto& iter: builtinVUIDInfo) {
     if (iter.builtIn == builtIn) {
@@ -180,57 +180,57 @@
   return vuid;
 }
 
-bool IsExecutionModelValidForRtBuiltIn(SpvBuiltIn builtin,
-                                       SpvExecutionModel stage) {
+bool IsExecutionModelValidForRtBuiltIn(spv::BuiltIn builtin,
+                                       spv::ExecutionModel stage) {
   switch (builtin) {
-    case SpvBuiltInHitKindKHR:
-    case SpvBuiltInHitTNV:
-      if (stage == SpvExecutionModelAnyHitKHR ||
-          stage == SpvExecutionModelClosestHitKHR) {
+    case spv::BuiltIn::HitKindKHR:
+    case spv::BuiltIn::HitTNV:
+      if (stage == spv::ExecutionModel::AnyHitKHR ||
+          stage == spv::ExecutionModel::ClosestHitKHR) {
         return true;
       }
       break;
-    case SpvBuiltInInstanceCustomIndexKHR:
-    case SpvBuiltInInstanceId:
-    case SpvBuiltInRayGeometryIndexKHR:
-    case SpvBuiltInObjectRayDirectionKHR:
-    case SpvBuiltInObjectRayOriginKHR:
-    case SpvBuiltInObjectToWorldKHR:
-    case SpvBuiltInWorldToObjectKHR:
+    case spv::BuiltIn::InstanceCustomIndexKHR:
+    case spv::BuiltIn::InstanceId:
+    case spv::BuiltIn::RayGeometryIndexKHR:
+    case spv::BuiltIn::ObjectRayDirectionKHR:
+    case spv::BuiltIn::ObjectRayOriginKHR:
+    case spv::BuiltIn::ObjectToWorldKHR:
+    case spv::BuiltIn::WorldToObjectKHR:
       switch (stage) {
-        case SpvExecutionModelIntersectionKHR:
-        case SpvExecutionModelAnyHitKHR:
-        case SpvExecutionModelClosestHitKHR:
+        case spv::ExecutionModel::IntersectionKHR:
+        case spv::ExecutionModel::AnyHitKHR:
+        case spv::ExecutionModel::ClosestHitKHR:
           return true;
         default:
           return false;
       }
       break;
-    case SpvBuiltInIncomingRayFlagsKHR:
-    case SpvBuiltInRayTminKHR:
-    case SpvBuiltInRayTmaxKHR:
-    case SpvBuiltInWorldRayDirectionKHR:
-    case SpvBuiltInWorldRayOriginKHR:
-    case SpvBuiltInCullMaskKHR:
+    case spv::BuiltIn::IncomingRayFlagsKHR:
+    case spv::BuiltIn::RayTminKHR:
+    case spv::BuiltIn::RayTmaxKHR:
+    case spv::BuiltIn::WorldRayDirectionKHR:
+    case spv::BuiltIn::WorldRayOriginKHR:
+    case spv::BuiltIn::CullMaskKHR:
       switch (stage) {
-        case SpvExecutionModelIntersectionKHR:
-        case SpvExecutionModelAnyHitKHR:
-        case SpvExecutionModelClosestHitKHR:
-        case SpvExecutionModelMissKHR:
+        case spv::ExecutionModel::IntersectionKHR:
+        case spv::ExecutionModel::AnyHitKHR:
+        case spv::ExecutionModel::ClosestHitKHR:
+        case spv::ExecutionModel::MissKHR:
           return true;
         default:
           return false;
       }
       break;
-    case SpvBuiltInLaunchIdKHR:
-    case SpvBuiltInLaunchSizeKHR:
+    case spv::BuiltIn::LaunchIdKHR:
+    case spv::BuiltIn::LaunchSizeKHR:
       switch (stage) {
-        case SpvExecutionModelRayGenerationKHR:
-        case SpvExecutionModelIntersectionKHR:
-        case SpvExecutionModelAnyHitKHR:
-        case SpvExecutionModelClosestHitKHR:
-        case SpvExecutionModelMissKHR:
-        case SpvExecutionModelCallableKHR:
+        case spv::ExecutionModel::RayGenerationKHR:
+        case spv::ExecutionModel::IntersectionKHR:
+        case spv::ExecutionModel::AnyHitKHR:
+        case spv::ExecutionModel::ClosestHitKHR:
+        case spv::ExecutionModel::MissKHR:
+        case spv::ExecutionModel::CallableKHR:
           return true;
         default:
           return false;
@@ -333,7 +333,7 @@
   // Used for GlobalInvocationId, LocalInvocationId, NumWorkgroups, WorkgroupId.
   spv_result_t ValidateComputeShaderI32Vec3InputAtDefinition(
       const Decoration& decoration, const Instruction& inst);
-  spv_result_t ValidateSMBuiltinsAtDefinition(const Decoration& decoration,
+  spv_result_t ValidateNVSMOrARMCoreBuiltinsAtDefinition(const Decoration& decoration,
                                               const Instruction& inst);
   // Used for BaryCoord, BaryCoordNoPersp.
   spv_result_t ValidateFragmentShaderF32Vec3InputAtDefinition(
@@ -528,7 +528,7 @@
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst);
 
-  spv_result_t ValidateSMBuiltinsAtReference(
+  spv_result_t ValidateNVSMOrARMCoreBuiltinsAtReference(
       const Decoration& decoration, const Instruction& built_in_inst,
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst);
@@ -559,7 +559,7 @@
   // |referenced_from_inst| - instruction which references id defined by
   //                          |referenced_inst| from within a function.
   spv_result_t ValidateNotCalledWithExecutionModel(
-      int vuid, const char* comment, SpvExecutionModel execution_model,
+      int vuid, const char* comment, spv::ExecutionModel execution_model,
       const Decoration& decoration, const Instruction& built_in_inst,
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst);
@@ -642,7 +642,7 @@
       const Decoration& decoration, const Instruction& built_in_inst,
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst,
-      SpvExecutionModel execution_model = SpvExecutionModelMax) const;
+      spv::ExecutionModel execution_model = spv::ExecutionModel::Max) const;
 
   // Generates strings like "ID <51> (OpTypePointer) uses storage class
   // UniformConstant".
@@ -671,12 +671,12 @@
   const std::vector<uint32_t>* entry_points_ = &no_entry_points;
 
   // Execution models with which the current function can be called.
-  std::set<SpvExecutionModel> execution_models_;
+  std::set<spv::ExecutionModel> execution_models_;
 };
 
 void BuiltInsValidator::Update(const Instruction& inst) {
-  const SpvOp opcode = inst.opcode();
-  if (opcode == SpvOpFunction) {
+  const spv::Op opcode = inst.opcode();
+  if (opcode == spv::Op::OpFunction) {
     // Entering a function.
     assert(function_id_ == 0);
     function_id_ = inst.id();
@@ -691,7 +691,7 @@
     }
   }
 
-  if (opcode == SpvOpFunctionEnd) {
+  if (opcode == spv::Op::OpFunctionEnd) {
     // Exiting a function.
     assert(function_id_ != 0);
     function_id_ = 0;
@@ -704,7 +704,7 @@
     const Decoration& decoration, const Instruction& inst) const {
   std::ostringstream ss;
   if (decoration.struct_member_index() != Decoration::kInvalidMember) {
-    assert(inst.opcode() == SpvOpTypeStruct);
+    assert(inst.opcode() == spv::Op::OpTypeStruct);
     ss << "Member #" << decoration.struct_member_index();
     ss << " of struct ID <" << inst.id() << ">";
   } else {
@@ -716,7 +716,7 @@
 std::string BuiltInsValidator::GetReferenceDesc(
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst, const Instruction& referenced_from_inst,
-    SpvExecutionModel execution_model) const {
+    spv::ExecutionModel execution_model) const {
   std::ostringstream ss;
   ss << GetIdDesc(referenced_from_inst) << " is referencing "
      << GetIdDesc(referenced_inst);
@@ -729,10 +729,10 @@
                                       decoration.params()[0]);
   if (function_id_) {
     ss << " in function <" << function_id_ << ">";
-    if (execution_model != SpvExecutionModelMax) {
+    if (execution_model != spv::ExecutionModel::Max) {
       ss << " called with execution model ";
       ss << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_EXECUTION_MODEL,
-                                          execution_model);
+                                          uint32_t(execution_model));
     }
   }
   ss << ".";
@@ -744,7 +744,7 @@
   std::ostringstream ss;
   ss << GetIdDesc(inst) << " uses storage class ";
   ss << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_STORAGE_CLASS,
-                                      GetStorageClass(inst));
+                                      uint32_t(GetStorageClass(inst)));
   ss << ".";
   return ss.str();
 }
@@ -803,7 +803,7 @@
   }
 
   // Strip the array, if present.
-  if (_.GetIdOpcode(underlying_type) == SpvOpTypeArray) {
+  if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) {
     underlying_type = _.FindDef(underlying_type)->word(2u);
   }
 
@@ -839,7 +839,7 @@
   }
 
   // Strip the array, if present.
-  if (_.GetIdOpcode(underlying_type) == SpvOpTypeArray) {
+  if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) {
     underlying_type = _.FindDef(underlying_type)->word(2u);
   }
 
@@ -922,7 +922,7 @@
   }
 
   // Strip the array, if present.
-  if (_.GetIdOpcode(underlying_type) == SpvOpTypeArray) {
+  if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) {
     underlying_type = _.FindDef(underlying_type)->word(2u);
   }
 
@@ -983,7 +983,7 @@
   }
 
   const Instruction* const type_inst = _.FindDef(underlying_type);
-  if (type_inst->opcode() != SpvOpTypeArray) {
+  if (type_inst->opcode() != spv::Op::OpTypeArray) {
     return diag(GetDefinitionDesc(decoration, inst) + " is not an array.");
   }
 
@@ -1029,9 +1029,9 @@
   }
 
   // Strip an extra layer of arraying if present.
-  if (_.GetIdOpcode(underlying_type) == SpvOpTypeArray) {
+  if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) {
     uint32_t subtype = _.FindDef(underlying_type)->word(2u);
-    if (_.GetIdOpcode(subtype) == SpvOpTypeArray) {
+    if (_.GetIdOpcode(subtype) == spv::Op::OpTypeArray) {
       underlying_type = subtype;
     }
   }
@@ -1046,7 +1046,7 @@
     const std::function<spv_result_t(const std::string& message)>& diag,
     uint32_t underlying_type) {
   const Instruction* const type_inst = _.FindDef(underlying_type);
-  if (type_inst->opcode() != SpvOpTypeArray) {
+  if (type_inst->opcode() != spv::Op::OpTypeArray) {
     return diag(GetDefinitionDesc(decoration, inst) + " is not an array.");
   }
 
@@ -1107,14 +1107,14 @@
 }
 
 spv_result_t BuiltInsValidator::ValidateNotCalledWithExecutionModel(
-    int vuid, const char* comment, SpvExecutionModel execution_model,
+    int vuid, const char* comment, spv::ExecutionModel execution_model,
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (function_id_) {
     if (execution_models_.count(execution_model)) {
       const char* execution_model_str = _.grammar().lookupOperandName(
-          SPV_OPERAND_TYPE_EXECUTION_MODEL, execution_model);
+          SPV_OPERAND_TYPE_EXECUTION_MODEL, uint32_t(execution_model));
       const char* built_in_str = _.grammar().lookupOperandName(
           SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@@ -1149,11 +1149,11 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInClipDistance) ? 4190 : 4199;
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4190 : 4199;
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -1165,47 +1165,54 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInClipDistance) ? 4188 : 4197;
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4188 : 4197;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
           "used for variables with Input storage class if execution model is "
           "Vertex.",
-          SpvExecutionModelVertex, decoration, built_in_inst,
+          spv::ExecutionModel::Vertex, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
           "used for variables with Input storage class if execution model is "
-          "Vertex.",
-          SpvExecutionModelMeshNV, decoration, built_in_inst,
+          "MeshNV.",
+          spv::ExecutionModel::MeshNV, decoration, built_in_inst,
+          referenced_from_inst, std::placeholders::_1));
+      id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
+          "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
+          "used for variables with Input storage class if execution model is "
+          "MeshEXT.",
+          spv::ExecutionModel::MeshEXT, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       assert(function_id_ == 0);
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInClipDistance) ? 4189 : 4198;
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4189 : 4198;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
           "used for variables with Output storage class if execution model is "
           "Fragment.",
-          SpvExecutionModelFragment, decoration, built_in_inst,
+          spv::ExecutionModel::Fragment, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelFragment:
-        case SpvExecutionModelVertex: {
+        case spv::ExecutionModel::Fragment:
+        case spv::ExecutionModel::Vertex: {
           if (spv_result_t error = ValidateF32Arr(
                   decoration, built_in_inst, /* Any number of components */ 0,
                   [this, &decoration, &referenced_from_inst](
                       const std::string& message) -> spv_result_t {
                     uint32_t vuid =
-                        (decoration.params()[0] == SpvBuiltInClipDistance)
+                        (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance)
                             ? 4191
                             : 4200;
                     return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@@ -1221,10 +1228,11 @@
           }
           break;
         }
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation:
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelMeshNV: {
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT: {
           if (decoration.struct_member_index() != Decoration::kInvalidMember) {
             // The outer level of array is applied on the variable.
             if (spv_result_t error = ValidateF32Arr(
@@ -1232,7 +1240,7 @@
                     [this, &decoration, &referenced_from_inst](
                         const std::string& message) -> spv_result_t {
                       uint32_t vuid =
-                          (decoration.params()[0] == SpvBuiltInClipDistance)
+                          (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance)
                               ? 4191
                               : 4200;
                       return _.diag(SPV_ERROR_INVALID_DATA,
@@ -1253,7 +1261,7 @@
                     [this, &decoration, &referenced_from_inst](
                         const std::string& message) -> spv_result_t {
                       uint32_t vuid =
-                          (decoration.params()[0] == SpvBuiltInClipDistance)
+                          (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance)
                               ? 4191
                               : 4200;
                       return _.diag(SPV_ERROR_INVALID_DATA,
@@ -1274,7 +1282,7 @@
 
         default: {
           uint32_t vuid =
-              (decoration.params()[0] == SpvBuiltInClipDistance) ? 4187 : 4196;
+              (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4187 : 4196;
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                  << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
                  << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -1327,9 +1335,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4211) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn FragCoord to be only used for "
@@ -1339,8 +1347,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4210)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1388,9 +1396,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4214) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn FragDepth to be only used for "
@@ -1400,8 +1408,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4213)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1416,7 +1424,7 @@
       // Every entry point from which this function is called needs to have
       // Execution Mode DepthReplacing.
       const auto* modes = _.GetExecutionModes(entry_point);
-      if (!modes || !modes->count(SpvExecutionModeDepthReplacing)) {
+      if (!modes || !modes->count(spv::ExecutionMode::DepthReplacing)) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4216)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1464,9 +1472,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4230) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn FrontFacing to be only used for "
@@ -1476,8 +1484,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4229)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1524,9 +1532,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4240)
              << "Vulkan spec allows BuiltIn HelperInvocation to be only used "
@@ -1536,8 +1544,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4239)
                << "Vulkan spec allows BuiltIn HelperInvocation to be used only "
@@ -1584,9 +1592,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4258)
              << "Vulkan spec allows BuiltIn InvocationId to be only used for "
@@ -1596,9 +1604,9 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelTessellationControl &&
-          execution_model != SpvExecutionModelGeometry) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::TessellationControl &&
+          execution_model != spv::ExecutionModel::Geometry) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4257)
                << "Vulkan spec allows BuiltIn InvocationId to be used only "
@@ -1645,9 +1653,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4264) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn InstanceIndex to be only used for "
@@ -1657,8 +1665,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelVertex) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Vertex) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4263)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1705,9 +1713,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4309)
              << "Vulkan spec allows BuiltIn PatchVertices to be only used for "
@@ -1717,9 +1725,9 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelTessellationControl &&
-          execution_model != SpvExecutionModelTessellationEvaluation) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::TessellationControl &&
+          execution_model != spv::ExecutionModel::TessellationEvaluation) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4308)
                << "Vulkan spec allows BuiltIn PatchVertices to be used only "
@@ -1767,9 +1775,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4312)
              << "Vulkan spec allows BuiltIn PointCoord to be only used for "
@@ -1779,8 +1787,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4311)
                << "Vulkan spec allows BuiltIn PointCoord to be used only with "
@@ -1812,10 +1820,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4316)
              << "Vulkan spec allows BuiltIn PointSize to be only used for "
@@ -1825,20 +1833,20 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4315,
           "Vulkan spec doesn't allow BuiltIn PointSize to be used for "
           "variables with Input storage class if execution model is "
           "Vertex.",
-          SpvExecutionModelVertex, decoration, built_in_inst,
+          spv::ExecutionModel::Vertex, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelVertex: {
+        case spv::ExecutionModel::Vertex: {
           if (spv_result_t error = ValidateF32(
                   decoration, built_in_inst,
                   [this, &referenced_from_inst](
@@ -1853,10 +1861,11 @@
           }
           break;
         }
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation:
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelMeshNV: {
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT: {
           // PointSize can be a per-vertex variable for tessellation control,
           // tessellation evaluation and geometry shader stages. In such cases
           // variables will have an array of 32-bit floats.
@@ -1929,10 +1938,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4320) << "Vulkan spec allows BuiltIn Position to be only used for "
                 "variables with Input or Output storage class. "
@@ -1941,27 +1950,34 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319,
           "Vulkan spec doesn't allow BuiltIn Position to be used "
           "for variables "
           "with Input storage class if execution model is Vertex.",
-          SpvExecutionModelVertex, decoration, built_in_inst,
+          spv::ExecutionModel::Vertex, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319,
           "Vulkan spec doesn't allow BuiltIn Position to be used "
           "for variables "
           "with Input storage class if execution model is MeshNV.",
-          SpvExecutionModelMeshNV, decoration, built_in_inst,
+          spv::ExecutionModel::MeshNV, decoration, built_in_inst,
+          referenced_from_inst, std::placeholders::_1));
+      id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+          &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319,
+          "Vulkan spec doesn't allow BuiltIn Position to be used "
+          "for variables "
+          "with Input storage class if execution model is MeshEXT.",
+          spv::ExecutionModel::MeshEXT, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelVertex: {
+        case spv::ExecutionModel::Vertex: {
           if (spv_result_t error = ValidateF32Vec(
                   decoration, built_in_inst, 4,
                   [this, &referenced_from_inst](
@@ -1977,10 +1993,11 @@
           }
           break;
         }
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation:
-        case SpvExecutionModelMeshNV: {
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT: {
           // Position can be a per-vertex variable for tessellation control,
           // tessellation evaluation, geometry and mesh shader stages. In such
           // cases variables will have an array of 4-component 32-bit float
@@ -2086,10 +2103,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << "Vulkan spec allows BuiltIn PrimitiveId to be only used for "
                 "variables with Input or Output storage class. "
@@ -2098,62 +2115,63 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "TessellationControl.",
-          SpvExecutionModelTessellationControl, decoration, built_in_inst,
+          spv::ExecutionModel::TessellationControl, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "TessellationEvaluation.",
-          SpvExecutionModelTessellationEvaluation, decoration, built_in_inst,
+          spv::ExecutionModel::TessellationEvaluation, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "Fragment.",
-          SpvExecutionModelFragment, decoration, built_in_inst,
+          spv::ExecutionModel::Fragment, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "IntersectionKHR.",
-          SpvExecutionModelIntersectionKHR, decoration, built_in_inst,
+          spv::ExecutionModel::IntersectionKHR, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "AnyHitKHR.",
-          SpvExecutionModelAnyHitKHR, decoration, built_in_inst,
+          spv::ExecutionModel::AnyHitKHR, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "ClosestHitKHR.",
-          SpvExecutionModelClosestHitKHR, decoration, built_in_inst,
+          spv::ExecutionModel::ClosestHitKHR, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelFragment:
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation:
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelMeshNV:
-        case SpvExecutionModelIntersectionKHR:
-        case SpvExecutionModelAnyHitKHR:
-        case SpvExecutionModelClosestHitKHR: {
+        case spv::ExecutionModel::Fragment:
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT:
+        case spv::ExecutionModel::IntersectionKHR:
+        case spv::ExecutionModel::AnyHitKHR:
+        case spv::ExecutionModel::ClosestHitKHR: {
           // Ok.
           break;
         }
@@ -2163,9 +2181,8 @@
                  << _.VkErrorID(4330)
                  << "Vulkan spec allows BuiltIn PrimitiveId to be used only "
                     "with Fragment, TessellationControl, "
-                    "TessellationEvaluation, Geometry, MeshNV, "
-                    "IntersectionKHR, "
-                    "AnyHitKHR, and ClosestHitKHR execution models. "
+                    "TessellationEvaluation, Geometry, MeshNV, MeshEXT, "
+                    "IntersectionKHR, AnyHitKHR, and ClosestHitKHR execution models. "
                  << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                      referenced_from_inst, execution_model);
         }
@@ -2208,9 +2225,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4355)
              << "Vulkan spec allows BuiltIn SampleId to be only used for "
@@ -2220,8 +2237,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4354)
                << "Vulkan spec allows BuiltIn SampleId to be used only with "
@@ -2267,10 +2284,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4358)
              << "Vulkan spec allows BuiltIn SampleMask to be only used for "
@@ -2280,8 +2297,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4357)
                << "Vulkan spec allows BuiltIn SampleMask to be used only "
@@ -2329,9 +2346,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4361)
              << "Vulkan spec allows BuiltIn SamplePosition to be only used "
@@ -2342,8 +2359,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4360)
                << "Vulkan spec allows BuiltIn SamplePosition to be used only "
@@ -2391,9 +2408,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4388)
              << "Vulkan spec allows BuiltIn TessCoord to be only used for "
@@ -2403,8 +2420,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelTessellationEvaluation) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::TessellationEvaluation) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4387)
                << "Vulkan spec allows BuiltIn TessCoord to be used only with "
@@ -2473,10 +2490,10 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2488,42 +2505,42 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInTessLevelOuter) ? 4391 : 4395;
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::TessLevelOuter) ? 4391 : 4395;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
           "used "
           "for variables with Input storage class if execution model is "
           "TessellationControl.",
-          SpvExecutionModelTessellationControl, decoration, built_in_inst,
+          spv::ExecutionModel::TessellationControl, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       assert(function_id_ == 0);
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInTessLevelOuter) ? 4392 : 4396;
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::TessLevelOuter) ? 4392 : 4396;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
           "used "
           "for variables with Output storage class if execution model is "
           "TessellationEvaluation.",
-          SpvExecutionModelTessellationEvaluation, decoration, built_in_inst,
+          spv::ExecutionModel::TessellationEvaluation, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation: {
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation: {
           // Ok.
           break;
         }
 
         default: {
-          uint32_t vuid = (operand == SpvBuiltInTessLevelOuter) ? 4390 : 4394;
+          uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::TessLevelOuter) ? 4390 : 4394;
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                  << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
                  << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2606,9 +2623,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4399) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn VertexIndex to be only used for "
@@ -2618,8 +2635,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelVertex) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Vertex) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4398)
                << spvLogStringForEnv(_.context()->target_env)
@@ -2653,7 +2670,7 @@
               [this, &decoration,
                &inst](const std::string& message) -> spv_result_t {
                 uint32_t vuid =
-                    (decoration.params()[0] == SpvBuiltInLayer) ? 4276 : 4408;
+                    (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::Layer) ? 4276 : 4408;
                 return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                        << _.VkErrorID(vuid)
                        << "According to the Vulkan spec BuiltIn "
@@ -2670,7 +2687,7 @@
               [this, &decoration,
                &inst](const std::string& message) -> spv_result_t {
                 uint32_t vuid =
-                    (decoration.params()[0] == SpvBuiltInLayer) ? 4276 : 4408;
+                    (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::Layer) ? 4276 : 4408;
                 return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                        << _.VkErrorID(vuid)
                        << "According to the Vulkan spec BuiltIn "
@@ -2694,10 +2711,10 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2709,63 +2726,65 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
       for (const auto em :
-           {SpvExecutionModelVertex, SpvExecutionModelTessellationEvaluation,
-            SpvExecutionModelGeometry, SpvExecutionModelMeshNV}) {
+           {spv::ExecutionModel::Vertex, spv::ExecutionModel::TessellationEvaluation,
+            spv::ExecutionModel::Geometry, spv::ExecutionModel::MeshNV,
+            spv::ExecutionModel::MeshEXT}) {
         id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
             std::bind(&BuiltInsValidator::ValidateNotCalledWithExecutionModel,
-                      this, ((operand == SpvBuiltInLayer) ? 4274 : 4406),
+                      this, ((spv::BuiltIn(operand) == spv::BuiltIn::Layer) ? 4274 : 4406),
                       "Vulkan spec doesn't allow BuiltIn Layer and "
                       "ViewportIndex to be "
                       "used for variables with Input storage class if "
                       "execution model is Vertex, TessellationEvaluation, "
-                      "Geometry, or MeshNV.",
+                      "Geometry, MeshNV or MeshEXT.",
                       em, decoration, built_in_inst, referenced_from_inst,
                       std::placeholders::_1));
       }
     }
 
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
           std::bind(&BuiltInsValidator::ValidateNotCalledWithExecutionModel,
-                    this, ((operand == SpvBuiltInLayer) ? 4275 : 4407),
+                    this, ((spv::BuiltIn(operand) == spv::BuiltIn::Layer) ? 4275 : 4407),
                     "Vulkan spec doesn't allow BuiltIn Layer and "
                     "ViewportIndex to be "
                     "used for variables with Output storage class if "
                     "execution model is "
                     "Fragment.",
-                    SpvExecutionModelFragment, decoration, built_in_inst,
+                    spv::ExecutionModel::Fragment, decoration, built_in_inst,
                     referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelFragment:
-        case SpvExecutionModelMeshNV:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::Fragment:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT:
           // Ok.
           break;
-        case SpvExecutionModelVertex:
-        case SpvExecutionModelTessellationEvaluation: {
-          if (!_.HasCapability(SpvCapabilityShaderViewportIndexLayerEXT)) {
-            if (operand == SpvBuiltInViewportIndex &&
-                _.HasCapability(SpvCapabilityShaderViewportIndex))
+        case spv::ExecutionModel::Vertex:
+        case spv::ExecutionModel::TessellationEvaluation: {
+          if (!_.HasCapability(spv::Capability::ShaderViewportIndexLayerEXT)) {
+            if (spv::BuiltIn(operand) == spv::BuiltIn::ViewportIndex &&
+                _.HasCapability(spv::Capability::ShaderViewportIndex))
               break;  // Ok
-            if (operand == SpvBuiltInLayer &&
-                _.HasCapability(SpvCapabilityShaderLayer))
+            if (spv::BuiltIn(operand) == spv::BuiltIn::Layer &&
+                _.HasCapability(spv::Capability::ShaderLayer))
               break;  // Ok
 
             const char* capability = "ShaderViewportIndexLayerEXT";
 
-            if (operand == SpvBuiltInViewportIndex)
+            if (spv::BuiltIn(operand) == spv::BuiltIn::ViewportIndex)
               capability = "ShaderViewportIndexLayerEXT or ShaderViewportIndex";
-            if (operand == SpvBuiltInLayer)
+            if (spv::BuiltIn(operand) == spv::BuiltIn::Layer)
               capability = "ShaderViewportIndexLayerEXT or ShaderLayer";
 
-            uint32_t vuid = (operand == SpvBuiltInLayer) ? 4273 : 4405;
+            uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::Layer) ? 4273 : 4405;
             return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                    << _.VkErrorID(vuid) << "Using BuiltIn "
                    << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2776,7 +2795,7 @@
           break;
         }
         default: {
-          uint32_t vuid = (operand == SpvBuiltInLayer) ? 4272 : 4404;
+          uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::Layer) ? 4272 : 4404;
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                  << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
                  << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2804,7 +2823,7 @@
 spv_result_t BuiltInsValidator::ValidateFragmentShaderF32Vec3InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateF32Vec(
             decoration, inst, 3,
             [this, &inst, builtin](const std::string& message) -> spv_result_t {
@@ -2814,7 +2833,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a 3-component 32-bit float "
                         "vector. "
                      << message;
@@ -2834,29 +2853,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -2878,7 +2897,7 @@
 spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI32Vec(
             decoration, inst, 3,
             [this, &inst, builtin](const std::string& message) -> spv_result_t {
@@ -2888,7 +2907,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a 3-component 32-bit int "
                         "vector. "
                      << message;
@@ -2907,33 +2926,37 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute ||
-                              execution_model == SpvExecutionModelTaskNV ||
-                              execution_model == SpvExecutionModelMeshNV;
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      bool has_vulkan_model = execution_model == spv::ExecutionModel::GLCompute ||
+                              execution_model == spv::ExecutionModel::TaskNV ||
+                              execution_model == spv::ExecutionModel::MeshNV ||
+                              execution_model == spv::ExecutionModel::TaskEXT ||
+                              execution_model == spv::ExecutionModel::MeshEXT;
+
       if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
-               << " to be used only with GLCompute, MeshNV, or TaskNV execution model. "
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
+               << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or"
+               << " TaskEXT execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
       }
@@ -2954,11 +2977,11 @@
 spv_result_t BuiltInsValidator::ValidateComputeI32InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32(
@@ -2970,7 +2993,7 @@
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                      << " variable needs to be a 32-bit int "
                         "vector. "
                      << message;
@@ -2988,34 +3011,37 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute ||
-                              execution_model == SpvExecutionModelTaskNV ||
-                              execution_model == SpvExecutionModelMeshNV;
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      bool has_vulkan_model = execution_model == spv::ExecutionModel::GLCompute ||
+                              execution_model == spv::ExecutionModel::TaskNV ||
+                              execution_model == spv::ExecutionModel::MeshNV ||
+                              execution_model == spv::ExecutionModel::TaskEXT ||
+                              execution_model == spv::ExecutionModel::MeshEXT;
       if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
-               << " to be used only with GLCompute, MeshNV, or TaskNV execution model. "
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
+               << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or "
+               << "TaskEXT execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
       }
@@ -3036,11 +3062,11 @@
 spv_result_t BuiltInsValidator::ValidateI32InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32(
@@ -3052,21 +3078,21 @@
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                      << " variable needs to be a 32-bit int. " << message;
             })) {
       return error;
     }
 
-    const SpvStorageClass storage_class = GetStorageClass(inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, inst, inst, inst) << " "
              << GetStorageClassDesc(inst);
@@ -3079,11 +3105,11 @@
 spv_result_t BuiltInsValidator::ValidateI32Vec4InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32Vec(
@@ -3095,7 +3121,7 @@
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                      << " variable needs to be a 4-component 32-bit int "
                         "vector. "
                      << message;
@@ -3103,15 +3129,15 @@
       return error;
     }
 
-    const SpvStorageClass storage_class = GetStorageClass(inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, inst, inst, inst) << " "
              << GetStorageClassDesc(inst);
@@ -3156,17 +3182,20 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelGLCompute &&
-          execution_model != SpvExecutionModelTaskNV &&
-          execution_model != SpvExecutionModelMeshNV) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::GLCompute &&
+          execution_model != spv::ExecutionModel::TaskNV &&
+          execution_model != spv::ExecutionModel::MeshNV &&
+          execution_model != spv::ExecutionModel::TaskEXT &&
+          execution_model != spv::ExecutionModel::MeshEXT) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4425)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
                                                 decoration.params()[0])
-               << " to be used only with GLCompute, MeshNV, or TaskNV execution model. "
+               << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or "
+               << "TaskEXT execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
       }
@@ -3190,7 +3219,7 @@
             decoration, inst,
             [this, &inst,
              &decoration](const std::string& message) -> spv_result_t {
-              uint32_t vuid = (decoration.params()[0] == SpvBuiltInBaseInstance)
+              uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::BaseInstance)
                                   ? 4183
                                   : 4186;
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
@@ -3214,10 +3243,10 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
-      uint32_t vuid = (operand == SpvBuiltInBaseInstance) ? 4182 : 4185;
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
+      uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::BaseInstance) ? 4182 : 4185;
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3228,9 +3257,9 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelVertex) {
-        uint32_t vuid = (operand == SpvBuiltInBaseInstance) ? 4181 : 4184;
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Vertex) {
+        uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::BaseInstance) ? 4181 : 4184;
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3281,9 +3310,9 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4208) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3294,15 +3323,18 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelVertex &&
-          execution_model != SpvExecutionModelMeshNV &&
-          execution_model != SpvExecutionModelTaskNV) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Vertex &&
+          execution_model != spv::ExecutionModel::MeshNV &&
+          execution_model != spv::ExecutionModel::TaskNV &&
+          execution_model != spv::ExecutionModel::MeshEXT &&
+          execution_model != spv::ExecutionModel::TaskEXT) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4207) << "Vulkan spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
                                                 operand)
-               << " to be used only with Vertex, MeshNV, or TaskNV execution "
+               << " to be used only with Vertex, MeshNV, TaskNV , MeshEXT or"
+               << " TaskEXT execution "
                   "model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3348,9 +3380,9 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4402) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3361,8 +3393,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model == SpvExecutionModelGLCompute) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model == spv::ExecutionModel::GLCompute) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4401) << "Vulkan spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3412,9 +3444,9 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4205) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3440,7 +3472,7 @@
                                             const Instruction& inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI32(
             decoration, inst,
             [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@@ -3450,7 +3482,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a 32-bit int scalar. "
                      << message;
             })) {
@@ -3467,29 +3499,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3510,7 +3542,7 @@
 spv_result_t BuiltInsValidator::ValidateFragSizeAtDefinition(const Decoration& decoration,
                                             const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI32Vec(
             decoration, inst, 2,
             [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@@ -3520,7 +3552,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a 2-component 32-bit int vector. "
                      << message;
             })) {
@@ -3537,29 +3569,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3580,7 +3612,7 @@
 spv_result_t BuiltInsValidator::ValidateFragStencilRefAtDefinition(const Decoration& decoration,
                                             const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI(
             decoration, inst,
             [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@@ -3590,7 +3622,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a int scalar. "
                      << message;
             })) {
@@ -3607,29 +3639,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Output) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Output storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3650,7 +3682,7 @@
 spv_result_t BuiltInsValidator::ValidateFullyCoveredAtDefinition(const Decoration& decoration,
                                                const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateBool(
             decoration, inst,
             [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@@ -3660,7 +3692,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a bool scalar. "
                      << message;
             })) {
@@ -3677,29 +3709,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3717,7 +3749,7 @@
   return SPV_SUCCESS;
 }
 
-spv_result_t BuiltInsValidator::ValidateSMBuiltinsAtDefinition(
+spv_result_t BuiltInsValidator::ValidateNVSMOrARMCoreBuiltinsAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
     if (spv_result_t error = ValidateI32(
@@ -3738,17 +3770,17 @@
   }
 
   // Seed at reference checks with this built-in.
-  return ValidateSMBuiltinsAtReference(decoration, inst, inst, inst);
+  return ValidateNVSMOrARMCoreBuiltinsAtReference(decoration, inst, inst, inst);
 }
 
-spv_result_t BuiltInsValidator::ValidateSMBuiltinsAtReference(
+spv_result_t BuiltInsValidator::ValidateNVSMOrARMCoreBuiltinsAtReference(
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
@@ -3765,7 +3797,7 @@
   if (function_id_ == 0) {
     // Propagate this rule to all dependant ids in the global scope.
     id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
-        &BuiltInsValidator::ValidateSMBuiltinsAtReference, this, decoration,
+        &BuiltInsValidator::ValidateNVSMOrARMCoreBuiltinsAtReference, this, decoration,
         built_in_inst, referenced_from_inst, std::placeholders::_1));
   }
 
@@ -3800,9 +3832,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4485) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3813,11 +3845,12 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelVertex:
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelMeshNV:
+        case spv::ExecutionModel::Vertex:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT:
           break;
         default: {
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@@ -3872,9 +3905,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4491) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3885,8 +3918,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4490) << "Vulkan spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3911,11 +3944,11 @@
 spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     switch (builtin) {
-      case SpvBuiltInHitTNV:
-      case SpvBuiltInRayTminKHR:
-      case SpvBuiltInRayTmaxKHR:
+      case spv::BuiltIn::HitTNV:
+      case spv::BuiltIn::RayTminKHR:
+      case spv::BuiltIn::RayTmaxKHR:
         // f32 scalar
         if (spv_result_t error = ValidateF32(
                 decoration, inst,
@@ -3926,19 +3959,19 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a 32-bit float scalar. "
                          << message;
                 })) {
           return error;
         }
         break;
-      case SpvBuiltInHitKindKHR:
-      case SpvBuiltInInstanceCustomIndexKHR:
-      case SpvBuiltInInstanceId:
-      case SpvBuiltInRayGeometryIndexKHR:
-      case SpvBuiltInIncomingRayFlagsKHR:
-      case SpvBuiltInCullMaskKHR:
+      case spv::BuiltIn::HitKindKHR:
+      case spv::BuiltIn::InstanceCustomIndexKHR:
+      case spv::BuiltIn::InstanceId:
+      case spv::BuiltIn::RayGeometryIndexKHR:
+      case spv::BuiltIn::IncomingRayFlagsKHR:
+      case spv::BuiltIn::CullMaskKHR:
         // i32 scalar
         if (spv_result_t error = ValidateI32(
                 decoration, inst,
@@ -3949,17 +3982,17 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a 32-bit int scalar. "
                          << message;
                 })) {
           return error;
         }
         break;
-      case SpvBuiltInObjectRayDirectionKHR:
-      case SpvBuiltInObjectRayOriginKHR:
-      case SpvBuiltInWorldRayDirectionKHR:
-      case SpvBuiltInWorldRayOriginKHR:
+      case spv::BuiltIn::ObjectRayDirectionKHR:
+      case spv::BuiltIn::ObjectRayOriginKHR:
+      case spv::BuiltIn::WorldRayDirectionKHR:
+      case spv::BuiltIn::WorldRayOriginKHR:
         // f32 vec3
         if (spv_result_t error = ValidateF32Vec(
                 decoration, inst, 3,
@@ -3970,7 +4003,7 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a 3-component 32-bit float "
                             "vector. "
                          << message;
@@ -3978,8 +4011,8 @@
           return error;
         }
         break;
-      case SpvBuiltInLaunchIdKHR:
-      case SpvBuiltInLaunchSizeKHR:
+      case spv::BuiltIn::LaunchIdKHR:
+      case spv::BuiltIn::LaunchSizeKHR:
         // i32 vec3
         if (spv_result_t error = ValidateI32Vec(
                 decoration, inst, 3,
@@ -3990,7 +4023,7 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a 3-component 32-bit int "
                             "vector. "
                          << message;
@@ -3998,8 +4031,8 @@
           return error;
         }
         break;
-      case SpvBuiltInObjectToWorldKHR:
-      case SpvBuiltInWorldToObjectKHR:
+      case spv::BuiltIn::ObjectToWorldKHR:
+      case spv::BuiltIn::WorldToObjectKHR:
         // f32 mat4x3
         if (spv_result_t error = ValidateF32Mat(
                 decoration, inst, 3, 4,
@@ -4010,7 +4043,7 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a matrix with"
                          << " 4 columns of 3-component vectors of 32-bit "
                             "floats. "
@@ -4034,10 +4067,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
@@ -4049,7 +4082,7 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       if (!IsExecutionModelValidForRtBuiltIn(builtin, execution_model)) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@@ -4058,7 +4091,7 @@
                                                 decoration.params()[0])
                << " to be used with the execution model "
                << _.grammar().lookupOperandName(
-                      SPV_OPERAND_TYPE_EXECUTION_MODEL, execution_model)
+                      SPV_OPERAND_TYPE_EXECUTION_MODEL, uint32_t(execution_model))
                << ".\n"
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -4079,7 +4112,7 @@
 
 spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  const SpvBuiltIn label = SpvBuiltIn(decoration.params()[0]);
+  const spv::BuiltIn label = spv::BuiltIn(decoration.params()[0]);
 
   if (!spvIsVulkanEnv(_.context()->target_env)) {
     // Early return. All currently implemented rules are based on Vulkan spec.
@@ -4096,195 +4129,171 @@
   // If the newly added enum has validation rules associated with it
   // consider leaving a TODO and/or creating an issue.
   switch (label) {
-    case SpvBuiltInClipDistance:
-    case SpvBuiltInCullDistance: {
+    case spv::BuiltIn::ClipDistance:
+    case spv::BuiltIn::CullDistance: {
       return ValidateClipOrCullDistanceAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragCoord: {
+    case spv::BuiltIn::FragCoord: {
       return ValidateFragCoordAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragDepth: {
+    case spv::BuiltIn::FragDepth: {
       return ValidateFragDepthAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFrontFacing: {
+    case spv::BuiltIn::FrontFacing: {
       return ValidateFrontFacingAtDefinition(decoration, inst);
     }
-    case SpvBuiltInGlobalInvocationId:
-    case SpvBuiltInLocalInvocationId:
-    case SpvBuiltInNumWorkgroups:
-    case SpvBuiltInWorkgroupId: {
+    case spv::BuiltIn::GlobalInvocationId:
+    case spv::BuiltIn::LocalInvocationId:
+    case spv::BuiltIn::NumWorkgroups:
+    case spv::BuiltIn::WorkgroupId: {
       return ValidateComputeShaderI32Vec3InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInBaryCoordKHR:
-    case SpvBuiltInBaryCoordNoPerspKHR: {
+    case spv::BuiltIn::BaryCoordKHR:
+    case spv::BuiltIn::BaryCoordNoPerspKHR: {
       return ValidateFragmentShaderF32Vec3InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInHelperInvocation: {
+    case spv::BuiltIn::HelperInvocation: {
       return ValidateHelperInvocationAtDefinition(decoration, inst);
     }
-    case SpvBuiltInInvocationId: {
+    case spv::BuiltIn::InvocationId: {
       return ValidateInvocationIdAtDefinition(decoration, inst);
     }
-    case SpvBuiltInInstanceIndex: {
+    case spv::BuiltIn::InstanceIndex: {
       return ValidateInstanceIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInLayer:
-    case SpvBuiltInViewportIndex: {
+    case spv::BuiltIn::Layer:
+    case spv::BuiltIn::ViewportIndex: {
       return ValidateLayerOrViewportIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPatchVertices: {
+    case spv::BuiltIn::PatchVertices: {
       return ValidatePatchVerticesAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPointCoord: {
+    case spv::BuiltIn::PointCoord: {
       return ValidatePointCoordAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPointSize: {
+    case spv::BuiltIn::PointSize: {
       return ValidatePointSizeAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPosition: {
+    case spv::BuiltIn::Position: {
       return ValidatePositionAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPrimitiveId: {
+    case spv::BuiltIn::PrimitiveId: {
       return ValidatePrimitiveIdAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSampleId: {
+    case spv::BuiltIn::SampleId: {
       return ValidateSampleIdAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSampleMask: {
+    case spv::BuiltIn::SampleMask: {
       return ValidateSampleMaskAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSamplePosition: {
+    case spv::BuiltIn::SamplePosition: {
       return ValidateSamplePositionAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSubgroupId:
-    case SpvBuiltInNumSubgroups: {
+    case spv::BuiltIn::SubgroupId:
+    case spv::BuiltIn::NumSubgroups: {
       return ValidateComputeI32InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSubgroupLocalInvocationId:
-    case SpvBuiltInSubgroupSize: {
+    case spv::BuiltIn::SubgroupLocalInvocationId:
+    case spv::BuiltIn::SubgroupSize: {
       return ValidateI32InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSubgroupEqMask:
-    case SpvBuiltInSubgroupGeMask:
-    case SpvBuiltInSubgroupGtMask:
-    case SpvBuiltInSubgroupLeMask:
-    case SpvBuiltInSubgroupLtMask: {
+    case spv::BuiltIn::SubgroupEqMask:
+    case spv::BuiltIn::SubgroupGeMask:
+    case spv::BuiltIn::SubgroupGtMask:
+    case spv::BuiltIn::SubgroupLeMask:
+    case spv::BuiltIn::SubgroupLtMask: {
       return ValidateI32Vec4InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInTessCoord: {
+    case spv::BuiltIn::TessCoord: {
       return ValidateTessCoordAtDefinition(decoration, inst);
     }
-    case SpvBuiltInTessLevelOuter: {
+    case spv::BuiltIn::TessLevelOuter: {
       return ValidateTessLevelOuterAtDefinition(decoration, inst);
     }
-    case SpvBuiltInTessLevelInner: {
+    case spv::BuiltIn::TessLevelInner: {
       return ValidateTessLevelInnerAtDefinition(decoration, inst);
     }
-    case SpvBuiltInVertexIndex: {
+    case spv::BuiltIn::VertexIndex: {
       return ValidateVertexIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInWorkgroupSize: {
+    case spv::BuiltIn::WorkgroupSize: {
       return ValidateWorkgroupSizeAtDefinition(decoration, inst);
     }
-    case SpvBuiltInVertexId: {
+    case spv::BuiltIn::VertexId: {
       return ValidateVertexIdAtDefinition(decoration, inst);
     }
-    case SpvBuiltInLocalInvocationIndex: {
+    case spv::BuiltIn::LocalInvocationIndex: {
       return ValidateLocalInvocationIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInWarpsPerSMNV:
-    case SpvBuiltInSMCountNV:
-    case SpvBuiltInWarpIDNV:
-    case SpvBuiltInSMIDNV: {
-      return ValidateSMBuiltinsAtDefinition(decoration, inst);
+    case spv::BuiltIn::CoreIDARM:
+    case spv::BuiltIn::CoreCountARM:
+    case spv::BuiltIn::CoreMaxIDARM:
+    case spv::BuiltIn::WarpIDARM:
+    case spv::BuiltIn::WarpMaxIDARM:
+    case spv::BuiltIn::WarpsPerSMNV:
+    case spv::BuiltIn::SMCountNV:
+    case spv::BuiltIn::WarpIDNV:
+    case spv::BuiltIn::SMIDNV: {
+      return ValidateNVSMOrARMCoreBuiltinsAtDefinition(decoration, inst);
     }
-    case SpvBuiltInBaseInstance:
-    case SpvBuiltInBaseVertex: {
+    case spv::BuiltIn::BaseInstance:
+    case spv::BuiltIn::BaseVertex: {
       return ValidateBaseInstanceOrVertexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInDrawIndex: {
+    case spv::BuiltIn::DrawIndex: {
       return ValidateDrawIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInViewIndex: {
+    case spv::BuiltIn::ViewIndex: {
       return ValidateViewIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInDeviceIndex: {
+    case spv::BuiltIn::DeviceIndex: {
       return ValidateDeviceIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragInvocationCountEXT: {
-      // alias SpvBuiltInInvocationsPerPixelNV
+    case spv::BuiltIn::FragInvocationCountEXT: {
+      // alias spv::BuiltIn::InvocationsPerPixelNV
       return ValidateFragInvocationCountAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragSizeEXT: {
-      // alias SpvBuiltInFragmentSizeNV
+    case spv::BuiltIn::FragSizeEXT: {
+      // alias spv::BuiltIn::FragmentSizeNV
       return ValidateFragSizeAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragStencilRefEXT: {
+    case spv::BuiltIn::FragStencilRefEXT: {
       return ValidateFragStencilRefAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFullyCoveredEXT:{
+    case spv::BuiltIn::FullyCoveredEXT:{
       return ValidateFullyCoveredAtDefinition(decoration, inst);
     }
     // Ray tracing builtins
-    case SpvBuiltInHitKindKHR:  // alias SpvBuiltInHitKindNV
-    case SpvBuiltInHitTNV:      // NOT present in KHR
-    case SpvBuiltInInstanceId:
-    case SpvBuiltInLaunchIdKHR:           // alias SpvBuiltInLaunchIdNV
-    case SpvBuiltInLaunchSizeKHR:         // alias SpvBuiltInLaunchSizeNV
-    case SpvBuiltInWorldRayOriginKHR:     // alias SpvBuiltInWorldRayOriginNV
-    case SpvBuiltInWorldRayDirectionKHR:  // alias SpvBuiltInWorldRayDirectionNV
-    case SpvBuiltInObjectRayOriginKHR:    // alias SpvBuiltInObjectRayOriginNV
-    case SpvBuiltInObjectRayDirectionKHR:   // alias
-                                            // SpvBuiltInObjectRayDirectionNV
-    case SpvBuiltInRayTminKHR:              // alias SpvBuiltInRayTminNV
-    case SpvBuiltInRayTmaxKHR:              // alias SpvBuiltInRayTmaxNV
-    case SpvBuiltInInstanceCustomIndexKHR:  // alias
-                                            // SpvBuiltInInstanceCustomIndexNV
-    case SpvBuiltInObjectToWorldKHR:        // alias SpvBuiltInObjectToWorldNV
-    case SpvBuiltInWorldToObjectKHR:        // alias SpvBuiltInWorldToObjectNV
-    case SpvBuiltInIncomingRayFlagsKHR:    // alias SpvBuiltInIncomingRayFlagsNV
-    case SpvBuiltInRayGeometryIndexKHR:    // NOT present in NV
-    case SpvBuiltInCullMaskKHR: {
+    case spv::BuiltIn::HitKindKHR:  // alias spv::BuiltIn::HitKindNV
+    case spv::BuiltIn::HitTNV:      // NOT present in KHR
+    case spv::BuiltIn::InstanceId:
+    case spv::BuiltIn::LaunchIdKHR:           // alias spv::BuiltIn::LaunchIdNV
+    case spv::BuiltIn::LaunchSizeKHR:         // alias spv::BuiltIn::LaunchSizeNV
+    case spv::BuiltIn::WorldRayOriginKHR:     // alias spv::BuiltIn::WorldRayOriginNV
+    case spv::BuiltIn::WorldRayDirectionKHR:  // alias spv::BuiltIn::WorldRayDirectionNV
+    case spv::BuiltIn::ObjectRayOriginKHR:    // alias spv::BuiltIn::ObjectRayOriginNV
+    case spv::BuiltIn::ObjectRayDirectionKHR:   // alias
+                                            // spv::BuiltIn::ObjectRayDirectionNV
+    case spv::BuiltIn::RayTminKHR:              // alias spv::BuiltIn::RayTminNV
+    case spv::BuiltIn::RayTmaxKHR:              // alias spv::BuiltIn::RayTmaxNV
+    case spv::BuiltIn::InstanceCustomIndexKHR:  // alias
+                                            // spv::BuiltIn::InstanceCustomIndexNV
+    case spv::BuiltIn::ObjectToWorldKHR:        // alias spv::BuiltIn::ObjectToWorldNV
+    case spv::BuiltIn::WorldToObjectKHR:        // alias spv::BuiltIn::WorldToObjectNV
+    case spv::BuiltIn::IncomingRayFlagsKHR:    // alias spv::BuiltIn::IncomingRayFlagsNV
+    case spv::BuiltIn::RayGeometryIndexKHR:    // NOT present in NV
+    case spv::BuiltIn::CullMaskKHR: {
       return ValidateRayTracingBuiltinsAtDefinition(decoration, inst);
     }
-    case SpvBuiltInWorkDim:
-    case SpvBuiltInGlobalSize:
-    case SpvBuiltInEnqueuedWorkgroupSize:
-    case SpvBuiltInGlobalOffset:
-    case SpvBuiltInGlobalLinearId:
-    case SpvBuiltInSubgroupMaxSize:
-    case SpvBuiltInNumEnqueuedSubgroups:
-    case SpvBuiltInBaryCoordNoPerspAMD:
-    case SpvBuiltInBaryCoordNoPerspCentroidAMD:
-    case SpvBuiltInBaryCoordNoPerspSampleAMD:
-    case SpvBuiltInBaryCoordSmoothAMD:
-    case SpvBuiltInBaryCoordSmoothCentroidAMD:
-    case SpvBuiltInBaryCoordSmoothSampleAMD:
-    case SpvBuiltInBaryCoordPullModelAMD:
-    case SpvBuiltInViewportMaskNV:
-    case SpvBuiltInSecondaryPositionNV:
-    case SpvBuiltInSecondaryViewportMaskNV:
-    case SpvBuiltInPositionPerViewNV:
-    case SpvBuiltInViewportMaskPerViewNV:
-    case SpvBuiltInMax:
-    case SpvBuiltInTaskCountNV:
-    case SpvBuiltInPrimitiveCountNV:
-    case SpvBuiltInPrimitiveIndicesNV:
-    case SpvBuiltInClipDistancePerViewNV:
-    case SpvBuiltInCullDistancePerViewNV:
-    case SpvBuiltInLayerPerViewNV:
-    case SpvBuiltInMeshViewCountNV:
-    case SpvBuiltInMeshViewIndicesNV:
-    case SpvBuiltInCurrentRayTimeNV:
-      // No validation rules (for the moment).
-      break;
-
-    case SpvBuiltInPrimitiveShadingRateKHR: {
+    case spv::BuiltIn::PrimitiveShadingRateKHR: {
       return ValidatePrimitiveShadingRateAtDefinition(decoration, inst);
     }
-    case SpvBuiltInShadingRateKHR: {
+    case spv::BuiltIn::ShadingRateKHR: {
       return ValidateShadingRateAtDefinition(decoration, inst);
     }
+    default:
+      // No validation rules (for the moment).
+      break;
   }
   return SPV_SUCCESS;
 }
@@ -4301,7 +4310,7 @@
     assert(inst);
 
     for (const auto& decoration : kv.second) {
-      if (decoration.dec_type() != SpvDecorationBuiltIn) {
+      if (decoration.dec_type() != spv::Decoration::BuiltIn) {
         continue;
       }
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_capability.cpp b/third_party/SPIRV-Tools/source/val/validate_capability.cpp
index 8efd554..d70c827 100644
--- a/third_party/SPIRV-Tools/source/val/validate_capability.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_capability.cpp
@@ -29,74 +29,82 @@
 namespace {
 
 bool IsSupportGuaranteedVulkan_1_0(uint32_t capability) {
-  switch (capability) {
-    case SpvCapabilityMatrix:
-    case SpvCapabilityShader:
-    case SpvCapabilityInputAttachment:
-    case SpvCapabilitySampled1D:
-    case SpvCapabilityImage1D:
-    case SpvCapabilitySampledBuffer:
-    case SpvCapabilityImageBuffer:
-    case SpvCapabilityImageQuery:
-    case SpvCapabilityDerivativeControl:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::Matrix:
+    case spv::Capability::Shader:
+    case spv::Capability::InputAttachment:
+    case spv::Capability::Sampled1D:
+    case spv::Capability::Image1D:
+    case spv::Capability::SampledBuffer:
+    case spv::Capability::ImageBuffer:
+    case spv::Capability::ImageQuery:
+    case spv::Capability::DerivativeControl:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportGuaranteedVulkan_1_1(uint32_t capability) {
   if (IsSupportGuaranteedVulkan_1_0(capability)) return true;
-  switch (capability) {
-    case SpvCapabilityDeviceGroup:
-    case SpvCapabilityMultiView:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::DeviceGroup:
+    case spv::Capability::MultiView:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportGuaranteedVulkan_1_2(uint32_t capability) {
   if (IsSupportGuaranteedVulkan_1_1(capability)) return true;
-  switch (capability) {
-    case SpvCapabilityShaderNonUniform:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::ShaderNonUniform:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportOptionalVulkan_1_0(uint32_t capability) {
-  switch (capability) {
-    case SpvCapabilityGeometry:
-    case SpvCapabilityTessellation:
-    case SpvCapabilityFloat64:
-    case SpvCapabilityInt64:
-    case SpvCapabilityInt16:
-    case SpvCapabilityTessellationPointSize:
-    case SpvCapabilityGeometryPointSize:
-    case SpvCapabilityImageGatherExtended:
-    case SpvCapabilityStorageImageMultisample:
-    case SpvCapabilityUniformBufferArrayDynamicIndexing:
-    case SpvCapabilitySampledImageArrayDynamicIndexing:
-    case SpvCapabilityStorageBufferArrayDynamicIndexing:
-    case SpvCapabilityStorageImageArrayDynamicIndexing:
-    case SpvCapabilityClipDistance:
-    case SpvCapabilityCullDistance:
-    case SpvCapabilityImageCubeArray:
-    case SpvCapabilitySampleRateShading:
-    case SpvCapabilitySparseResidency:
-    case SpvCapabilityMinLod:
-    case SpvCapabilitySampledCubeArray:
-    case SpvCapabilityImageMSArray:
-    case SpvCapabilityStorageImageExtendedFormats:
-    case SpvCapabilityInterpolationFunction:
-    case SpvCapabilityStorageImageReadWithoutFormat:
-    case SpvCapabilityStorageImageWriteWithoutFormat:
-    case SpvCapabilityMultiViewport:
-    case SpvCapabilityInt64Atomics:
-    case SpvCapabilityTransformFeedback:
-    case SpvCapabilityGeometryStreams:
-    case SpvCapabilityFloat16:
-    case SpvCapabilityInt8:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::Geometry:
+    case spv::Capability::Tessellation:
+    case spv::Capability::Float64:
+    case spv::Capability::Int64:
+    case spv::Capability::Int16:
+    case spv::Capability::TessellationPointSize:
+    case spv::Capability::GeometryPointSize:
+    case spv::Capability::ImageGatherExtended:
+    case spv::Capability::StorageImageMultisample:
+    case spv::Capability::UniformBufferArrayDynamicIndexing:
+    case spv::Capability::SampledImageArrayDynamicIndexing:
+    case spv::Capability::StorageBufferArrayDynamicIndexing:
+    case spv::Capability::StorageImageArrayDynamicIndexing:
+    case spv::Capability::ClipDistance:
+    case spv::Capability::CullDistance:
+    case spv::Capability::ImageCubeArray:
+    case spv::Capability::SampleRateShading:
+    case spv::Capability::SparseResidency:
+    case spv::Capability::MinLod:
+    case spv::Capability::SampledCubeArray:
+    case spv::Capability::ImageMSArray:
+    case spv::Capability::StorageImageExtendedFormats:
+    case spv::Capability::InterpolationFunction:
+    case spv::Capability::StorageImageReadWithoutFormat:
+    case spv::Capability::StorageImageWriteWithoutFormat:
+    case spv::Capability::MultiViewport:
+    case spv::Capability::Int64Atomics:
+    case spv::Capability::TransformFeedback:
+    case spv::Capability::GeometryStreams:
+    case spv::Capability::Float16:
+    case spv::Capability::Int8:
       return true;
+    default:
+      break;
   }
   return false;
 }
@@ -104,27 +112,29 @@
 bool IsSupportOptionalVulkan_1_1(uint32_t capability) {
   if (IsSupportOptionalVulkan_1_0(capability)) return true;
 
-  switch (capability) {
-    case SpvCapabilityGroupNonUniform:
-    case SpvCapabilityGroupNonUniformVote:
-    case SpvCapabilityGroupNonUniformArithmetic:
-    case SpvCapabilityGroupNonUniformBallot:
-    case SpvCapabilityGroupNonUniformShuffle:
-    case SpvCapabilityGroupNonUniformShuffleRelative:
-    case SpvCapabilityGroupNonUniformClustered:
-    case SpvCapabilityGroupNonUniformQuad:
-    case SpvCapabilityDrawParameters:
-    // Alias SpvCapabilityStorageBuffer16BitAccess.
-    case SpvCapabilityStorageUniformBufferBlock16:
-    // Alias SpvCapabilityUniformAndStorageBuffer16BitAccess.
-    case SpvCapabilityStorageUniform16:
-    case SpvCapabilityStoragePushConstant16:
-    case SpvCapabilityStorageInputOutput16:
-    case SpvCapabilityDeviceGroup:
-    case SpvCapabilityMultiView:
-    case SpvCapabilityVariablePointersStorageBuffer:
-    case SpvCapabilityVariablePointers:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::GroupNonUniform:
+    case spv::Capability::GroupNonUniformVote:
+    case spv::Capability::GroupNonUniformArithmetic:
+    case spv::Capability::GroupNonUniformBallot:
+    case spv::Capability::GroupNonUniformShuffle:
+    case spv::Capability::GroupNonUniformShuffleRelative:
+    case spv::Capability::GroupNonUniformClustered:
+    case spv::Capability::GroupNonUniformQuad:
+    case spv::Capability::DrawParameters:
+    // Alias spv::Capability::StorageBuffer16BitAccess.
+    case spv::Capability::StorageUniformBufferBlock16:
+    // Alias spv::Capability::UniformAndStorageBuffer16BitAccess.
+    case spv::Capability::StorageUniform16:
+    case spv::Capability::StoragePushConstant16:
+    case spv::Capability::StorageInputOutput16:
+    case spv::Capability::DeviceGroup:
+    case spv::Capability::MultiView:
+    case spv::Capability::VariablePointersStorageBuffer:
+    case spv::Capability::VariablePointers:
       return true;
+    default:
+      break;
   }
   return false;
 }
@@ -132,47 +142,51 @@
 bool IsSupportOptionalVulkan_1_2(uint32_t capability) {
   if (IsSupportOptionalVulkan_1_1(capability)) return true;
 
-  switch (capability) {
-    case SpvCapabilityDenormPreserve:
-    case SpvCapabilityDenormFlushToZero:
-    case SpvCapabilitySignedZeroInfNanPreserve:
-    case SpvCapabilityRoundingModeRTE:
-    case SpvCapabilityRoundingModeRTZ:
-    case SpvCapabilityVulkanMemoryModel:
-    case SpvCapabilityVulkanMemoryModelDeviceScope:
-    case SpvCapabilityStorageBuffer8BitAccess:
-    case SpvCapabilityUniformAndStorageBuffer8BitAccess:
-    case SpvCapabilityStoragePushConstant8:
-    case SpvCapabilityShaderViewportIndex:
-    case SpvCapabilityShaderLayer:
-    case SpvCapabilityPhysicalStorageBufferAddresses:
-    case SpvCapabilityRuntimeDescriptorArray:
-    case SpvCapabilityUniformTexelBufferArrayDynamicIndexing:
-    case SpvCapabilityStorageTexelBufferArrayDynamicIndexing:
-    case SpvCapabilityUniformBufferArrayNonUniformIndexing:
-    case SpvCapabilitySampledImageArrayNonUniformIndexing:
-    case SpvCapabilityStorageBufferArrayNonUniformIndexing:
-    case SpvCapabilityStorageImageArrayNonUniformIndexing:
-    case SpvCapabilityInputAttachmentArrayNonUniformIndexing:
-    case SpvCapabilityUniformTexelBufferArrayNonUniformIndexing:
-    case SpvCapabilityStorageTexelBufferArrayNonUniformIndexing:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::DenormPreserve:
+    case spv::Capability::DenormFlushToZero:
+    case spv::Capability::SignedZeroInfNanPreserve:
+    case spv::Capability::RoundingModeRTE:
+    case spv::Capability::RoundingModeRTZ:
+    case spv::Capability::VulkanMemoryModel:
+    case spv::Capability::VulkanMemoryModelDeviceScope:
+    case spv::Capability::StorageBuffer8BitAccess:
+    case spv::Capability::UniformAndStorageBuffer8BitAccess:
+    case spv::Capability::StoragePushConstant8:
+    case spv::Capability::ShaderViewportIndex:
+    case spv::Capability::ShaderLayer:
+    case spv::Capability::PhysicalStorageBufferAddresses:
+    case spv::Capability::RuntimeDescriptorArray:
+    case spv::Capability::UniformTexelBufferArrayDynamicIndexing:
+    case spv::Capability::StorageTexelBufferArrayDynamicIndexing:
+    case spv::Capability::UniformBufferArrayNonUniformIndexing:
+    case spv::Capability::SampledImageArrayNonUniformIndexing:
+    case spv::Capability::StorageBufferArrayNonUniformIndexing:
+    case spv::Capability::StorageImageArrayNonUniformIndexing:
+    case spv::Capability::InputAttachmentArrayNonUniformIndexing:
+    case spv::Capability::UniformTexelBufferArrayNonUniformIndexing:
+    case spv::Capability::StorageTexelBufferArrayNonUniformIndexing:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportGuaranteedOpenCL_1_2(uint32_t capability, bool embedded_profile) {
-  switch (capability) {
-    case SpvCapabilityAddresses:
-    case SpvCapabilityFloat16Buffer:
-    case SpvCapabilityInt16:
-    case SpvCapabilityInt8:
-    case SpvCapabilityKernel:
-    case SpvCapabilityLinkage:
-    case SpvCapabilityVector16:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::Addresses:
+    case spv::Capability::Float16Buffer:
+    case spv::Capability::Int16:
+    case spv::Capability::Int8:
+    case spv::Capability::Kernel:
+    case spv::Capability::Linkage:
+    case spv::Capability::Vector16:
       return true;
-    case SpvCapabilityInt64:
+    case spv::Capability::Int64:
       return !embedded_profile;
+    default:
+      break;
   }
   return false;
 }
@@ -180,12 +194,14 @@
 bool IsSupportGuaranteedOpenCL_2_0(uint32_t capability, bool embedded_profile) {
   if (IsSupportGuaranteedOpenCL_1_2(capability, embedded_profile)) return true;
 
-  switch (capability) {
-    case SpvCapabilityDeviceEnqueue:
-    case SpvCapabilityGenericPointer:
-    case SpvCapabilityGroups:
-    case SpvCapabilityPipes:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::DeviceEnqueue:
+    case spv::Capability::GenericPointer:
+    case spv::Capability::Groups:
+    case spv::Capability::Pipes:
       return true;
+    default:
+      break;
   }
   return false;
 }
@@ -193,19 +209,23 @@
 bool IsSupportGuaranteedOpenCL_2_2(uint32_t capability, bool embedded_profile) {
   if (IsSupportGuaranteedOpenCL_2_0(capability, embedded_profile)) return true;
 
-  switch (capability) {
-    case SpvCapabilitySubgroupDispatch:
-    case SpvCapabilityPipeStorage:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::SubgroupDispatch:
+    case spv::Capability::PipeStorage:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportOptionalOpenCL_1_2(uint32_t capability) {
-  switch (capability) {
-    case SpvCapabilityImageBasic:
-    case SpvCapabilityFloat64:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::ImageBasic:
+    case spv::Capability::Float64:
       return true;
+    default:
+      break;
   }
   return false;
 }
@@ -229,14 +249,16 @@
 
 bool IsEnabledByCapabilityOpenCL_1_2(ValidationState_t& _,
                                      uint32_t capability) {
-  if (_.HasCapability(SpvCapabilityImageBasic)) {
-    switch (capability) {
-      case SpvCapabilityLiteralSampler:
-      case SpvCapabilitySampled1D:
-      case SpvCapabilityImage1D:
-      case SpvCapabilitySampledBuffer:
-      case SpvCapabilityImageBuffer:
+  if (_.HasCapability(spv::Capability::ImageBasic)) {
+    switch (spv::Capability(capability)) {
+      case spv::Capability::LiteralSampler:
+      case spv::Capability::Sampled1D:
+      case spv::Capability::Image1D:
+      case spv::Capability::SampledBuffer:
+      case spv::Capability::ImageBuffer:
         return true;
+      default:
+        break;
     }
     return false;
   }
@@ -245,15 +267,17 @@
 
 bool IsEnabledByCapabilityOpenCL_2_0(ValidationState_t& _,
                                      uint32_t capability) {
-  if (_.HasCapability(SpvCapabilityImageBasic)) {
-    switch (capability) {
-      case SpvCapabilityImageReadWrite:
-      case SpvCapabilityLiteralSampler:
-      case SpvCapabilitySampled1D:
-      case SpvCapabilityImage1D:
-      case SpvCapabilitySampledBuffer:
-      case SpvCapabilityImageBuffer:
+  if (_.HasCapability(spv::Capability::ImageBasic)) {
+    switch (spv::Capability(capability)) {
+      case spv::Capability::ImageReadWrite:
+      case spv::Capability::LiteralSampler:
+      case spv::Capability::Sampled1D:
+      case spv::Capability::Image1D:
+      case spv::Capability::SampledBuffer:
+      case spv::Capability::ImageBuffer:
         return true;
+      default:
+        break;
     }
     return false;
   }
@@ -265,7 +289,7 @@
 // Validates that capability declarations use operands allowed in the current
 // context.
 spv_result_t CapabilityPass(ValidationState_t& _, const Instruction* inst) {
-  if (inst->opcode() != SpvOpCapability) return SPV_SUCCESS;
+  if (inst->opcode() != spv::Op::OpCapability) return SPV_SUCCESS;
 
   assert(inst->operands().size() == 1);
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_cfg.cpp b/third_party/SPIRV-Tools/source/val/validate_cfg.cpp
index 0220fcd..06e4d67 100644
--- a/third_party/SPIRV-Tools/source/val/validate_cfg.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_cfg.cpp
@@ -54,7 +54,7 @@
            << "OpPhi must not have void result type";
   }
   if (_.IsPointerType(inst->type_id()) &&
-      _.addressing_model() == SpvAddressingModelLogical) {
+      _.addressing_model() == spv::AddressingModel::Logical) {
     if (!_.features().variable_pointers) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Using pointers with OpPhi requires capability "
@@ -64,13 +64,14 @@
 
   const Instruction* type_inst = _.FindDef(inst->type_id());
   assert(type_inst);
-  const SpvOp type_opcode = type_inst->opcode();
+  const spv::Op type_opcode = type_inst->opcode();
 
   if (!_.options()->before_hlsl_legalization &&
-      !_.HasCapability(SpvCapabilityBindlessTextureNV)) {
-    if (type_opcode == SpvOpTypeSampledImage ||
-        (_.HasCapability(SpvCapabilityShader) &&
-         (type_opcode == SpvOpTypeImage || type_opcode == SpvOpTypeSampler))) {
+      !_.HasCapability(spv::Capability::BindlessTextureNV)) {
+    if (type_opcode == spv::Op::OpTypeSampledImage ||
+        (_.HasCapability(spv::Capability::Shader) &&
+         (type_opcode == spv::Op::OpTypeImage ||
+          type_opcode == spv::Op::OpTypeSampler))) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Result type cannot be Op" << spvOpcodeString(type_opcode);
     }
@@ -108,7 +109,7 @@
                << " type <id> " << _.getIdName(inc_type_id) << ".";
       }
     } else {
-      if (_.GetIdOpcode(inc_id) != SpvOpLabel) {
+      if (_.GetIdOpcode(inc_id) != spv::Op::OpLabel) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "OpPhi's incoming basic block <id> " << _.getIdName(inc_id)
                << " is not an OpLabel.";
@@ -143,7 +144,7 @@
   // target operands must be OpLabel
   const auto id = inst->GetOperandAs<uint32_t>(0);
   const auto target = _.FindDef(id);
-  if (!target || SpvOpLabel != target->opcode()) {
+  if (!target || spv::Op::OpLabel != target->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "'Target Label' operands for OpBranch must be the ID "
               "of an OpLabel instruction";
@@ -178,7 +179,7 @@
   // PerformCfgChecks already checks for that
   const auto true_id = inst->GetOperandAs<uint32_t>(1);
   const auto true_target = _.FindDef(true_id);
-  if (!true_target || SpvOpLabel != true_target->opcode()) {
+  if (!true_target || spv::Op::OpLabel != true_target->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The 'True Label' operand for OpBranchConditional must be the "
               "ID of an OpLabel instruction";
@@ -186,7 +187,7 @@
 
   const auto false_id = inst->GetOperandAs<uint32_t>(2);
   const auto false_target = _.FindDef(false_id);
-  if (!false_target || SpvOpLabel != false_target->opcode()) {
+  if (!false_target || spv::Op::OpLabel != false_target->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The 'False Label' operand for OpBranchConditional must be the "
               "ID of an OpLabel instruction";
@@ -213,7 +214,7 @@
   }
 
   const auto default_label = _.FindDef(inst->GetOperandAs<uint32_t>(1));
-  if (default_label->opcode() != SpvOpLabel) {
+  if (default_label->opcode() != spv::Op::OpLabel) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Default must be an OpLabel instruction";
   }
@@ -223,7 +224,7 @@
     // literal, id
     const auto id = inst->GetOperandAs<uint32_t>(i + 1);
     const auto target = _.FindDef(id);
-    if (!target || SpvOpLabel != target->opcode()) {
+    if (!target || spv::Op::OpLabel != target->opcode()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "'Target Label' operands for OpSwitch must be IDs of an "
                 "OpLabel instruction";
@@ -239,23 +240,23 @@
   const auto value = _.FindDef(value_id);
   if (!value || !value->type_id()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpReturnValue Value <id> '" << _.getIdName(value_id)
-           << "' does not represent a value.";
+           << "OpReturnValue Value <id> " << _.getIdName(value_id)
+           << " does not represent a value.";
   }
   auto value_type = _.FindDef(value->type_id());
-  if (!value_type || SpvOpTypeVoid == value_type->opcode()) {
+  if (!value_type || spv::Op::OpTypeVoid == value_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpReturnValue value's type <id> '"
-           << _.getIdName(value->type_id()) << "' is missing or void.";
+           << "OpReturnValue value's type <id> "
+           << _.getIdName(value->type_id()) << " is missing or void.";
   }
 
-  if (_.addressing_model() == SpvAddressingModelLogical &&
-      SpvOpTypePointer == value_type->opcode() &&
+  if (_.addressing_model() == spv::AddressingModel::Logical &&
+      spv::Op::OpTypePointer == value_type->opcode() &&
       !_.features().variable_pointers && !_.options()->relax_logical_pointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpReturnValue value's type <id> '"
+           << "OpReturnValue value's type <id> "
            << _.getIdName(value->type_id())
-           << "' is a pointer, which is invalid in the Logical addressing "
+           << " is a pointer, which is invalid in the Logical addressing "
               "model.";
   }
 
@@ -263,17 +264,22 @@
   const auto return_type = _.FindDef(function->GetResultTypeId());
   if (!return_type || return_type->id() != value_type->id()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpReturnValue Value <id> '" << _.getIdName(value_id)
-           << "'s type does not match OpFunction's return type.";
+           << "OpReturnValue Value <id> " << _.getIdName(value_id)
+           << "s type does not match OpFunction's return type.";
   }
 
   return SPV_SUCCESS;
 }
 
+uint32_t operator>>(const spv::LoopControlShift& lhs,
+                    const spv::LoopControlShift& rhs) {
+  return uint32_t(lhs) >> uint32_t(rhs);
+}
+
 spv_result_t ValidateLoopMerge(ValidationState_t& _, const Instruction* inst) {
   const auto merge_id = inst->GetOperandAs<uint32_t>(0);
   const auto merge = _.FindDef(merge_id);
-  if (!merge || merge->opcode() != SpvOpLabel) {
+  if (!merge || merge->opcode() != spv::Op::OpLabel) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Merge Block " << _.getIdName(merge_id) << " must be an OpLabel";
   }
@@ -284,7 +290,7 @@
 
   const auto continue_id = inst->GetOperandAs<uint32_t>(1);
   const auto continue_target = _.FindDef(continue_id);
-  if (!continue_target || continue_target->opcode() != SpvOpLabel) {
+  if (!continue_target || continue_target->opcode() != spv::Op::OpLabel) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Continue Target " << _.getIdName(continue_id)
            << " must be an OpLabel";
@@ -295,36 +301,36 @@
            << "Merge Block and Continue Target must be different ids";
   }
 
-  const auto loop_control = inst->GetOperandAs<uint32_t>(2);
-  if ((loop_control >> SpvLoopControlUnrollShift) & 0x1 &&
-      (loop_control >> SpvLoopControlDontUnrollShift) & 0x1) {
+  const auto loop_control = inst->GetOperandAs<spv::LoopControlShift>(2);
+  if ((loop_control >> spv::LoopControlShift::Unroll) & 0x1 &&
+      (loop_control >> spv::LoopControlShift::DontUnroll) & 0x1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Unroll and DontUnroll loop controls must not both be specified";
   }
-  if ((loop_control >> SpvLoopControlDontUnrollShift) & 0x1 &&
-      (loop_control >> SpvLoopControlPeelCountShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::DontUnroll) & 0x1 &&
+      (loop_control >> spv::LoopControlShift::PeelCount) & 0x1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "PeelCount and DontUnroll "
                                                    "loop controls must not "
                                                    "both be specified";
   }
-  if ((loop_control >> SpvLoopControlDontUnrollShift) & 0x1 &&
-      (loop_control >> SpvLoopControlPartialCountShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::DontUnroll) & 0x1 &&
+      (loop_control >> spv::LoopControlShift::PartialCount) & 0x1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "PartialCount and "
                                                    "DontUnroll loop controls "
                                                    "must not both be specified";
   }
 
   uint32_t operand = 3;
-  if ((loop_control >> SpvLoopControlDependencyLengthShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::DependencyLength) & 0x1) {
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlMinIterationsShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::MinIterations) & 0x1) {
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlMaxIterationsShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::MaxIterations) & 0x1) {
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlIterationMultipleShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::IterationMultiple) & 0x1) {
     if (inst->operands().size() < operand ||
         inst->GetOperandAs<uint32_t>(operand) == 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst) << "IterationMultiple loop "
@@ -333,10 +339,10 @@
     }
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlPeelCountShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::PeelCount) & 0x1) {
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlPartialCountShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::PartialCount) & 0x1) {
     ++operand;
   }
 
@@ -644,9 +650,9 @@
     const auto index = terminator - &_.ordered_instructions()[0];
     auto* merge = &_.ordered_instructions()[index - 1];
     // Marks merges and continues as seen.
-    if (merge->opcode() == SpvOpSelectionMerge) {
+    if (merge->opcode() == spv::Op::OpSelectionMerge) {
       seen.insert(merge->GetOperandAs<uint32_t>(0));
-    } else if (merge->opcode() == SpvOpLoopMerge) {
+    } else if (merge->opcode() == spv::Op::OpLoopMerge) {
       seen.insert(merge->GetOperandAs<uint32_t>(0));
       seen.insert(merge->GetOperandAs<uint32_t>(1));
     } else {
@@ -657,7 +663,7 @@
     // Skip unreachable blocks.
     if (!block->structurally_reachable()) continue;
 
-    if (terminator->opcode() == SpvOpBranchConditional) {
+    if (terminator->opcode() == spv::Op::OpBranchConditional) {
       const auto true_label = terminator->GetOperandAs<uint32_t>(1);
       const auto false_label = terminator->GetOperandAs<uint32_t>(2);
       // Mark the upcoming blocks as seen now, but only error out if this block
@@ -669,7 +675,7 @@
         return _.diag(SPV_ERROR_INVALID_CFG, terminator)
                << "Selection must be structured";
       }
-    } else if (terminator->opcode() == SpvOpSwitch) {
+    } else if (terminator->opcode() == spv::Op::OpSwitch) {
       if (!merge) {
         return _.diag(SPV_ERROR_INVALID_CFG, terminator)
                << "OpSwitch must be preceded by an OpSelectionMerge "
@@ -798,8 +804,8 @@
           block->is_type(BlockType::kBlockTypeLoop)) {
         size_t index = (block->terminator() - &_.ordered_instructions()[0]) - 1;
         const auto& merge_inst = _.ordered_instructions()[index];
-        if (merge_inst.opcode() == SpvOpSelectionMerge ||
-            merge_inst.opcode() == SpvOpLoopMerge) {
+        if (merge_inst.opcode() == spv::Op::OpSelectionMerge ||
+            merge_inst.opcode() == spv::Op::OpLoopMerge) {
           uint32_t merge_id = merge_inst.GetOperandAs<uint32_t>(0);
           auto merge_block = function->GetBlock(merge_id).first;
           if (merge_block->structurally_reachable() &&
@@ -854,7 +860,7 @@
 
     // Checks rules for case constructs.
     if (construct.type() == ConstructType::kSelection &&
-        header->terminator()->opcode() == SpvOpSwitch) {
+        header->terminator()->opcode() == spv::Op::OpSwitch) {
       const auto terminator = header->terminator();
       if (auto error =
               StructuredSwitchChecks(_, function, terminator, header, merge)) {
@@ -896,14 +902,13 @@
     // CFG to ensure we cover all the blocks.
     std::vector<const BasicBlock*> postorder;
     auto ignore_block = [](const BasicBlock*) {};
-    auto ignore_edge = [](const BasicBlock*, const BasicBlock*) {};
     auto no_terminal_blocks = [](const BasicBlock*) { return false; };
     if (!function.ordered_blocks().empty()) {
       /// calculate dominators
       CFA<BasicBlock>::DepthFirstTraversal(
           function.first_block(), function.AugmentedCFGSuccessorsFunction(),
           ignore_block, [&](const BasicBlock* b) { postorder.push_back(b); },
-          ignore_edge, no_terminal_blocks);
+          no_terminal_blocks);
       auto edges = CFA<BasicBlock>::CalculateDominators(
           postorder, function.AugmentedCFGPredecessorsFunction());
       for (auto edge : edges) {
@@ -929,7 +934,7 @@
       }
       // If we have structured control flow, check that no block has a control
       // flow nesting depth larger than the limit.
-      if (_.HasCapability(SpvCapabilityShader)) {
+      if (_.HasCapability(spv::Capability::Shader)) {
         const int control_flow_nesting_depth_limit =
             _.options()->universal_limits_.max_control_flow_nesting_depth;
         for (auto block = begin(blocks); block != end(blocks); ++block) {
@@ -943,7 +948,7 @@
     }
 
     /// Structured control flow checks are only required for shader capabilities
-    if (_.HasCapability(SpvCapabilityShader)) {
+    if (_.HasCapability(spv::Capability::Shader)) {
       // Calculate structural dominance.
       postorder.clear();
       std::vector<const BasicBlock*> postdom_postorder;
@@ -953,7 +958,7 @@
         CFA<BasicBlock>::DepthFirstTraversal(
             function.first_block(),
             function.AugmentedStructuralCFGSuccessorsFunction(), ignore_block,
-            [&](const BasicBlock* b) { postorder.push_back(b); }, ignore_edge,
+            [&](const BasicBlock* b) { postorder.push_back(b); },
             no_terminal_blocks);
         auto edges = CFA<BasicBlock>::CalculateDominators(
             postorder, function.AugmentedStructuralCFGPredecessorsFunction());
@@ -967,7 +972,7 @@
             function.pseudo_exit_block(),
             function.AugmentedStructuralCFGPredecessorsFunction(), ignore_block,
             [&](const BasicBlock* b) { postdom_postorder.push_back(b); },
-            ignore_edge, no_terminal_blocks);
+            no_terminal_blocks);
         auto postdom_edges = CFA<BasicBlock>::CalculateDominators(
             postdom_postorder,
             function.AugmentedStructuralCFGSuccessorsFunction());
@@ -999,9 +1004,9 @@
 }
 
 spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst) {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   switch (opcode) {
-    case SpvOpLabel:
+    case spv::Op::OpLabel:
       if (auto error = _.current_function().RegisterBlock(inst->id()))
         return error;
 
@@ -1010,7 +1015,7 @@
       // passes the OpLabel ends up not being part of the basic block it starts.
       _.current_function().current_block()->set_label(inst);
       break;
-    case SpvOpLoopMerge: {
+    case spv::Op::OpLoopMerge: {
       uint32_t merge_block = inst->GetOperandAs<uint32_t>(0);
       uint32_t continue_block = inst->GetOperandAs<uint32_t>(1);
       CFG_ASSERT(MergeBlockAssert, merge_block);
@@ -1019,20 +1024,20 @@
                                                               continue_block))
         return error;
     } break;
-    case SpvOpSelectionMerge: {
+    case spv::Op::OpSelectionMerge: {
       uint32_t merge_block = inst->GetOperandAs<uint32_t>(0);
       CFG_ASSERT(MergeBlockAssert, merge_block);
 
       if (auto error = _.current_function().RegisterSelectionMerge(merge_block))
         return error;
     } break;
-    case SpvOpBranch: {
+    case spv::Op::OpBranch: {
       uint32_t target = inst->GetOperandAs<uint32_t>(0);
       CFG_ASSERT(FirstBlockAssert, target);
 
       _.current_function().RegisterBlockEnd({target});
     } break;
-    case SpvOpBranchConditional: {
+    case spv::Op::OpBranchConditional: {
       uint32_t tlabel = inst->GetOperandAs<uint32_t>(1);
       uint32_t flabel = inst->GetOperandAs<uint32_t>(2);
       CFG_ASSERT(FirstBlockAssert, tlabel);
@@ -1041,7 +1046,7 @@
       _.current_function().RegisterBlockEnd({tlabel, flabel});
     } break;
 
-    case SpvOpSwitch: {
+    case spv::Op::OpSwitch: {
       std::vector<uint32_t> cases;
       for (size_t i = 1; i < inst->operands().size(); i += 2) {
         uint32_t target = inst->GetOperandAs<uint32_t>(i);
@@ -1050,43 +1055,45 @@
       }
       _.current_function().RegisterBlockEnd({cases});
     } break;
-    case SpvOpReturn: {
+    case spv::Op::OpReturn: {
       const uint32_t return_type = _.current_function().GetResultTypeId();
       const Instruction* return_type_inst = _.FindDef(return_type);
       assert(return_type_inst);
-      if (return_type_inst->opcode() != SpvOpTypeVoid)
+      if (return_type_inst->opcode() != spv::Op::OpTypeVoid)
         return _.diag(SPV_ERROR_INVALID_CFG, inst)
                << "OpReturn can only be called from a function with void "
                << "return type.";
       _.current_function().RegisterBlockEnd(std::vector<uint32_t>());
       break;
     }
-    case SpvOpKill:
-    case SpvOpReturnValue:
-    case SpvOpUnreachable:
-    case SpvOpTerminateInvocation:
-    case SpvOpIgnoreIntersectionKHR:
-    case SpvOpTerminateRayKHR:
+    case spv::Op::OpKill:
+    case spv::Op::OpReturnValue:
+    case spv::Op::OpUnreachable:
+    case spv::Op::OpTerminateInvocation:
+    case spv::Op::OpIgnoreIntersectionKHR:
+    case spv::Op::OpTerminateRayKHR:
+    case spv::Op::OpEmitMeshTasksEXT:
       _.current_function().RegisterBlockEnd(std::vector<uint32_t>());
-      if (opcode == SpvOpKill) {
+      // Ops with dedicated passes check for the Execution Model there
+      if (opcode == spv::Op::OpKill) {
         _.current_function().RegisterExecutionModelLimitation(
-            SpvExecutionModelFragment,
+            spv::ExecutionModel::Fragment,
             "OpKill requires Fragment execution model");
       }
-      if (opcode == SpvOpTerminateInvocation) {
+      if (opcode == spv::Op::OpTerminateInvocation) {
         _.current_function().RegisterExecutionModelLimitation(
-            SpvExecutionModelFragment,
+            spv::ExecutionModel::Fragment,
             "OpTerminateInvocation requires Fragment execution model");
       }
-      if (opcode == SpvOpIgnoreIntersectionKHR) {
+      if (opcode == spv::Op::OpIgnoreIntersectionKHR) {
         _.current_function().RegisterExecutionModelLimitation(
-            SpvExecutionModelAnyHitKHR,
-            "OpIgnoreIntersectionKHR requires AnyHit execution model");
+            spv::ExecutionModel::AnyHitKHR,
+            "OpIgnoreIntersectionKHR requires AnyHitKHR execution model");
       }
-      if (opcode == SpvOpTerminateRayKHR) {
+      if (opcode == spv::Op::OpTerminateRayKHR) {
         _.current_function().RegisterExecutionModelLimitation(
-            SpvExecutionModelAnyHitKHR,
-            "OpTerminateRayKHR requires AnyHit execution model");
+            spv::ExecutionModel::AnyHitKHR,
+            "OpTerminateRayKHR requires AnyHitKHR execution model");
       }
 
       break;
@@ -1139,22 +1146,22 @@
 
 spv_result_t ControlFlowPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpPhi:
+    case spv::Op::OpPhi:
       if (auto error = ValidatePhi(_, inst)) return error;
       break;
-    case SpvOpBranch:
+    case spv::Op::OpBranch:
       if (auto error = ValidateBranch(_, inst)) return error;
       break;
-    case SpvOpBranchConditional:
+    case spv::Op::OpBranchConditional:
       if (auto error = ValidateBranchConditional(_, inst)) return error;
       break;
-    case SpvOpReturnValue:
+    case spv::Op::OpReturnValue:
       if (auto error = ValidateReturnValue(_, inst)) return error;
       break;
-    case SpvOpSwitch:
+    case spv::Op::OpSwitch:
       if (auto error = ValidateSwitch(_, inst)) return error;
       break;
-    case SpvOpLoopMerge:
+    case spv::Op::OpLoopMerge:
       if (auto error = ValidateLoopMerge(_, inst)) return error;
       break;
     default:
diff --git a/third_party/SPIRV-Tools/source/val/validate_composites.cpp b/third_party/SPIRV-Tools/source/val/validate_composites.cpp
index 5d6c5e3..e777f16 100644
--- a/third_party/SPIRV-Tools/source/val/validate_composites.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_composites.cpp
@@ -35,9 +35,10 @@
 spv_result_t GetExtractInsertValueType(ValidationState_t& _,
                                        const Instruction* inst,
                                        uint32_t* member_type) {
-  const SpvOp opcode = inst->opcode();
-  assert(opcode == SpvOpCompositeExtract || opcode == SpvOpCompositeInsert);
-  uint32_t word_index = opcode == SpvOpCompositeExtract ? 4 : 5;
+  const spv::Op opcode = inst->opcode();
+  assert(opcode == spv::Op::OpCompositeExtract ||
+         opcode == spv::Op::OpCompositeInsert);
+  uint32_t word_index = opcode == spv::Op::OpCompositeExtract ? 4 : 5;
   const uint32_t num_words = static_cast<uint32_t>(inst->words().size());
   const uint32_t composite_id_index = word_index - 1;
   const uint32_t num_indices = num_words - word_index;
@@ -66,7 +67,7 @@
     const Instruction* const type_inst = _.FindDef(*member_type);
     assert(type_inst);
     switch (type_inst->opcode()) {
-      case SpvOpTypeVector: {
+      case spv::Op::OpTypeVector: {
         *member_type = type_inst->word(2);
         const uint32_t vector_size = type_inst->word(3);
         if (component_index >= vector_size) {
@@ -76,7 +77,7 @@
         }
         break;
       }
-      case SpvOpTypeMatrix: {
+      case spv::Op::OpTypeMatrix: {
         *member_type = type_inst->word(2);
         const uint32_t num_cols = type_inst->word(3);
         if (component_index >= num_cols) {
@@ -86,7 +87,7 @@
         }
         break;
       }
-      case SpvOpTypeArray: {
+      case spv::Op::OpTypeArray: {
         uint64_t array_size = 0;
         auto size = _.FindDef(type_inst->word(3));
         *member_type = type_inst->word(2);
@@ -105,12 +106,12 @@
         }
         break;
       }
-      case SpvOpTypeRuntimeArray: {
+      case spv::Op::OpTypeRuntimeArray: {
         *member_type = type_inst->word(2);
         // Array size is unknown.
         break;
       }
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         const size_t num_struct_members = type_inst->words().size() - 2;
         if (component_index >= num_struct_members) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -123,7 +124,7 @@
         *member_type = type_inst->word(component_index + 2);
         break;
       }
-      case SpvOpTypeCooperativeMatrixNV: {
+      case spv::Op::OpTypeCooperativeMatrixNV: {
         *member_type = type_inst->word(2);
         break;
       }
@@ -140,15 +141,15 @@
 spv_result_t ValidateVectorExtractDynamic(ValidationState_t& _,
                                           const Instruction* inst) {
   const uint32_t result_type = inst->type_id();
-  const SpvOp result_opcode = _.GetIdOpcode(result_type);
+  const spv::Op result_opcode = _.GetIdOpcode(result_type);
   if (!spvOpcodeIsScalarType(result_opcode)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be a scalar type";
   }
 
   const uint32_t vector_type = _.GetOperandTypeId(inst, 2);
-  const SpvOp vector_opcode = _.GetIdOpcode(vector_type);
-  if (vector_opcode != SpvOpTypeVector) {
+  const spv::Op vector_opcode = _.GetIdOpcode(vector_type);
+  if (vector_opcode != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Vector type to be OpTypeVector";
   }
@@ -164,7 +165,7 @@
            << "Expected Index to be int scalar";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot extract from a vector of 8- or 16-bit types";
@@ -175,8 +176,8 @@
 spv_result_t ValidateVectorInsertDyanmic(ValidationState_t& _,
                                          const Instruction* inst) {
   const uint32_t result_type = inst->type_id();
-  const SpvOp result_opcode = _.GetIdOpcode(result_type);
-  if (result_opcode != SpvOpTypeVector) {
+  const spv::Op result_opcode = _.GetIdOpcode(result_type);
+  if (result_opcode != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypeVector";
   }
@@ -200,7 +201,7 @@
            << "Expected Index to be int scalar";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot insert into a vector of 8- or 16-bit types";
@@ -212,9 +213,9 @@
                                         const Instruction* inst) {
   const uint32_t num_operands = static_cast<uint32_t>(inst->operands().size());
   const uint32_t result_type = inst->type_id();
-  const SpvOp result_opcode = _.GetIdOpcode(result_type);
+  const spv::Op result_opcode = _.GetIdOpcode(result_type);
   switch (result_opcode) {
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       const uint32_t num_result_components = _.GetDimension(result_type);
       const uint32_t result_component_type = _.GetComponentType(result_type);
       uint32_t given_component_count = 0;
@@ -230,7 +231,7 @@
         if (operand_type == result_component_type) {
           ++given_component_count;
         } else {
-          if (_.GetIdOpcode(operand_type) != SpvOpTypeVector ||
+          if (_.GetIdOpcode(operand_type) != spv::Op::OpTypeVector ||
               _.GetComponentType(operand_type) != result_component_type) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << "Expected Constituents to be scalars or vectors of"
@@ -249,7 +250,7 @@
 
       break;
     }
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       uint32_t result_num_rows = 0;
       uint32_t result_num_cols = 0;
       uint32_t result_col_type = 0;
@@ -277,10 +278,10 @@
 
       break;
     }
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       const Instruction* const array_inst = _.FindDef(result_type);
       assert(array_inst);
-      assert(array_inst->opcode() == SpvOpTypeArray);
+      assert(array_inst->opcode() == spv::Op::OpTypeArray);
 
       auto size = _.FindDef(array_inst->word(3));
       if (spvOpcodeIsSpecConstant(size->opcode())) {
@@ -312,10 +313,10 @@
 
       break;
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const Instruction* const struct_inst = _.FindDef(result_type);
       assert(struct_inst);
-      assert(struct_inst->opcode() == SpvOpTypeStruct);
+      assert(struct_inst->opcode() == spv::Op::OpTypeStruct);
 
       if (struct_inst->operands().size() + 1 != num_operands) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -336,7 +337,7 @@
 
       break;
     }
-    case SpvOpTypeCooperativeMatrixNV: {
+    case spv::Op::OpTypeCooperativeMatrixNV: {
       const auto result_type_inst = _.FindDef(result_type);
       assert(result_type_inst);
       const auto component_type_id =
@@ -362,7 +363,7 @@
     }
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot create a composite containing 8- or 16-bit types";
@@ -386,7 +387,7 @@
            << spvOpcodeString(_.GetIdOpcode(member_type)) << ").";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot extract from a composite of 8- or 16-bit types";
@@ -421,7 +422,7 @@
            << spvOpcodeString(_.GetIdOpcode(member_type)) << ").";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot insert into a composite of 8- or 16-bit types";
@@ -480,7 +481,7 @@
            << "to be the reverse of those of Result Type";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot transpose matrices of 16-bit floats";
@@ -491,11 +492,12 @@
 spv_result_t ValidateVectorShuffle(ValidationState_t& _,
                                    const Instruction* inst) {
   auto resultType = _.FindDef(inst->type_id());
-  if (!resultType || resultType->opcode() != SpvOpTypeVector) {
+  if (!resultType || resultType->opcode() != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The Result Type of OpVectorShuffle must be"
            << " OpTypeVector. Found Op"
-           << spvOpcodeString(static_cast<SpvOp>(resultType->opcode())) << ".";
+           << spvOpcodeString(static_cast<spv::Op>(resultType->opcode()))
+           << ".";
   }
 
   // The number of components in Result Type must be the same as the number of
@@ -505,8 +507,8 @@
   if (componentCount != resultVectorDimension) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpVectorShuffle component literals count does not match "
-              "Result Type <id> '"
-           << _.getIdName(resultType->id()) << "'s vector component count.";
+              "Result Type <id> "
+           << _.getIdName(resultType->id()) << "s vector component count.";
   }
 
   // Vector 1 and Vector 2 must both have vector types, with the same Component
@@ -515,11 +517,11 @@
   auto vector1Type = _.FindDef(vector1Object->type_id());
   auto vector2Object = _.FindDef(inst->GetOperandAs<uint32_t>(3));
   auto vector2Type = _.FindDef(vector2Object->type_id());
-  if (!vector1Type || vector1Type->opcode() != SpvOpTypeVector) {
+  if (!vector1Type || vector1Type->opcode() != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The type of Vector 1 must be OpTypeVector.";
   }
-  if (!vector2Type || vector2Type->opcode() != SpvOpTypeVector) {
+  if (!vector2Type || vector2Type->opcode() != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The type of Vector 2 must be OpTypeVector.";
   }
@@ -548,7 +550,7 @@
     }
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot shuffle a vector of 8- or 16-bit types";
@@ -572,7 +574,7 @@
            << "Result Type does not logically match the Operand type";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot copy composites of 8- or 16-bit types";
@@ -586,23 +588,23 @@
 // Validates correctness of composite instructions.
 spv_result_t CompositesPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpVectorExtractDynamic:
+    case spv::Op::OpVectorExtractDynamic:
       return ValidateVectorExtractDynamic(_, inst);
-    case SpvOpVectorInsertDynamic:
+    case spv::Op::OpVectorInsertDynamic:
       return ValidateVectorInsertDyanmic(_, inst);
-    case SpvOpVectorShuffle:
+    case spv::Op::OpVectorShuffle:
       return ValidateVectorShuffle(_, inst);
-    case SpvOpCompositeConstruct:
+    case spv::Op::OpCompositeConstruct:
       return ValidateCompositeConstruct(_, inst);
-    case SpvOpCompositeExtract:
+    case spv::Op::OpCompositeExtract:
       return ValidateCompositeExtract(_, inst);
-    case SpvOpCompositeInsert:
+    case spv::Op::OpCompositeInsert:
       return ValidateCompositeInsert(_, inst);
-    case SpvOpCopyObject:
+    case spv::Op::OpCopyObject:
       return ValidateCopyObject(_, inst);
-    case SpvOpTranspose:
+    case spv::Op::OpTranspose:
       return ValidateTranspose(_, inst);
-    case SpvOpCopyLogical:
+    case spv::Op::OpCopyLogical:
       return ValidateCopyLogical(_, inst);
     default:
       break;
diff --git a/third_party/SPIRV-Tools/source/val/validate_constants.cpp b/third_party/SPIRV-Tools/source/val/validate_constants.cpp
index dea95c8..a8ee5a6 100644
--- a/third_party/SPIRV-Tools/source/val/validate_constants.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_constants.cpp
@@ -24,10 +24,10 @@
 spv_result_t ValidateConstantBool(ValidationState_t& _,
                                   const Instruction* inst) {
   auto type = _.FindDef(inst->type_id());
-  if (!type || type->opcode() != SpvOpTypeBool) {
+  if (!type || type->opcode() != spv::Op::OpTypeBool) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Op" << spvOpcodeString(inst->opcode()) << " Result Type <id> '"
-           << _.getIdName(inst->type_id()) << "' is not a boolean type.";
+           << "Op" << spvOpcodeString(inst->opcode()) << " Result Type <id> "
+           << _.getIdName(inst->type_id()) << " is not a boolean type.";
   }
 
   return SPV_SUCCESS;
@@ -40,22 +40,21 @@
   const auto result_type = _.FindDef(inst->type_id());
   if (!result_type || !spvOpcodeIsComposite(result_type->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << opcode_name << " Result Type <id> '"
-           << _.getIdName(inst->type_id()) << "' is not a composite type.";
+           << opcode_name << " Result Type <id> "
+           << _.getIdName(inst->type_id()) << " is not a composite type.";
   }
 
   const auto constituent_count = inst->words().size() - 3;
   switch (result_type->opcode()) {
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       const auto component_count = result_type->GetOperandAs<uint32_t>(2);
       if (component_count != constituent_count) {
         // TODO: Output ID's on diagnostic
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << opcode_name
                << " Constituent <id> count does not match "
-                  "Result Type <id> '"
-               << _.getIdName(result_type->id())
-               << "'s vector component count.";
+                  "Result Type <id> "
+               << _.getIdName(result_type->id()) << "s vector component count.";
       }
       const auto component_type =
           _.FindDef(result_type->GetOperandAs<uint32_t>(1));
@@ -71,30 +70,30 @@
         if (!constituent ||
             !spvOpcodeIsConstantOrUndef(constituent->opcode())) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "' is not a constant or undef.";
+                 << " is not a constant or undef.";
         }
         const auto constituent_result_type = _.FindDef(constituent->type_id());
         if (!constituent_result_type ||
             component_type->opcode() != constituent_result_type->opcode()) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "'s type does not match Result Type <id> '"
-                 << _.getIdName(result_type->id()) << "'s vector element type.";
+                 << "s type does not match Result Type <id> "
+                 << _.getIdName(result_type->id()) << "s vector element type.";
         }
       }
     } break;
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       const auto column_count = result_type->GetOperandAs<uint32_t>(2);
       if (column_count != constituent_count) {
         // TODO: Output ID's on diagnostic
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << opcode_name
                << " Constituent <id> count does not match "
-                  "Result Type <id> '"
-               << _.getIdName(result_type->id()) << "'s matrix column count.";
+                  "Result Type <id> "
+               << _.getIdName(result_type->id()) << "s matrix column count.";
       }
 
       const auto column_type = _.FindDef(result_type->words()[2]);
@@ -120,9 +119,9 @@
           // The message says "... or undef" because the spec does not say
           // undef is a constant.
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "' is not a constant or undef.";
+                 << " is not a constant or undef.";
         }
         const auto vector = _.FindDef(constituent->type_id());
         if (!vector) {
@@ -131,32 +130,32 @@
         }
         if (column_type->opcode() != vector->opcode()) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "' type does not match Result Type <id> '"
-                 << _.getIdName(result_type->id()) << "'s matrix column type.";
+                 << " type does not match Result Type <id> "
+                 << _.getIdName(result_type->id()) << "s matrix column type.";
         }
         const auto vector_component_type =
             _.FindDef(vector->GetOperandAs<uint32_t>(1));
         if (component_type->id() != vector_component_type->id()) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "' component type does not match Result Type <id> '"
+                 << " component type does not match Result Type <id> "
                  << _.getIdName(result_type->id())
-                 << "'s matrix column component type.";
+                 << "s matrix column component type.";
         }
         if (component_count != vector->words()[3]) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "' vector component count does not match Result Type <id> '"
+                 << " vector component count does not match Result Type <id> "
                  << _.getIdName(result_type->id())
-                 << "'s vector component count.";
+                 << "s vector component count.";
         }
       }
     } break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       auto element_type = _.FindDef(result_type->GetOperandAs<uint32_t>(1));
       if (!element_type) {
         return _.diag(SPV_ERROR_INVALID_ID, result_type)
@@ -175,8 +174,8 @@
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << opcode_name
                << " Constituent count does not match "
-                  "Result Type <id> '"
-               << _.getIdName(result_type->id()) << "'s array length.";
+                  "Result Type <id> "
+               << _.getIdName(result_type->id()) << "s array length.";
       }
       for (size_t constituent_index = 2;
            constituent_index < inst->operands().size(); constituent_index++) {
@@ -186,9 +185,9 @@
         if (!constituent ||
             !spvOpcodeIsConstantOrUndef(constituent->opcode())) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "' is not a constant or undef.";
+                 << " is not a constant or undef.";
         }
         const auto constituent_type = _.FindDef(constituent->type_id());
         if (!constituent_type) {
@@ -197,21 +196,21 @@
         }
         if (element_type->id() != constituent_type->id()) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "'s type does not match Result Type <id> '"
-                 << _.getIdName(result_type->id()) << "'s array element type.";
+                 << "s type does not match Result Type <id> "
+                 << _.getIdName(result_type->id()) << "s array element type.";
         }
       }
     } break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const auto member_count = result_type->words().size() - 2;
       if (member_count != constituent_count) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << opcode_name << " Constituent <id> '"
+               << opcode_name << " Constituent <id> "
                << _.getIdName(inst->type_id())
-               << "' count does not match Result Type <id> '"
-               << _.getIdName(result_type->id()) << "'s struct member count.";
+               << " count does not match Result Type <id> "
+               << _.getIdName(result_type->id()) << "s struct member count.";
       }
       for (uint32_t constituent_index = 2, member_index = 1;
            constituent_index < inst->operands().size();
@@ -222,9 +221,9 @@
         if (!constituent ||
             !spvOpcodeIsConstantOrUndef(constituent->opcode())) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "' is not a constant or undef.";
+                 << " is not a constant or undef.";
         }
         const auto constituent_type = _.FindDef(constituent->type_id());
         if (!constituent_type) {
@@ -237,26 +236,25 @@
         const auto member_type = _.FindDef(member_type_id);
         if (!member_type || member_type->id() != constituent_type->id()) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << opcode_name << " Constituent <id> '"
+                 << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)
-                 << "' type does not match the Result Type <id> '"
-                 << _.getIdName(result_type->id()) << "'s member type.";
+                 << " type does not match the Result Type <id> "
+                 << _.getIdName(result_type->id()) << "s member type.";
         }
       }
     } break;
-    case SpvOpTypeCooperativeMatrixNV: {
+    case spv::Op::OpTypeCooperativeMatrixNV: {
       if (1 != constituent_count) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << opcode_name << " Constituent <id> '"
-               << _.getIdName(inst->type_id()) << "' count must be one.";
+               << opcode_name << " Constituent <id> "
+               << _.getIdName(inst->type_id()) << " count must be one.";
       }
       const auto constituent_id = inst->GetOperandAs<uint32_t>(2);
       const auto constituent = _.FindDef(constituent_id);
       if (!constituent || !spvOpcodeIsConstantOrUndef(constituent->opcode())) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << opcode_name << " Constituent <id> '"
-               << _.getIdName(constituent_id)
-               << "' is not a constant or undef.";
+               << opcode_name << " Constituent <id> "
+               << _.getIdName(constituent_id) << " is not a constant or undef.";
       }
       const auto constituent_type = _.FindDef(constituent->type_id());
       if (!constituent_type) {
@@ -268,10 +266,10 @@
       const auto component_type = _.FindDef(component_type_id);
       if (!component_type || component_type->id() != constituent_type->id()) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << opcode_name << " Constituent <id> '"
+               << opcode_name << " Constituent <id> "
                << _.getIdName(constituent_id)
-               << "' type does not match the Result Type <id> '"
-               << _.getIdName(result_type->id()) << "'s component type.";
+               << " type does not match the Result Type <id> "
+               << _.getIdName(result_type->id()) << "s component type.";
       }
     } break;
     default:
@@ -283,10 +281,10 @@
 spv_result_t ValidateConstantSampler(ValidationState_t& _,
                                      const Instruction* inst) {
   const auto result_type = _.FindDef(inst->type_id());
-  if (!result_type || result_type->opcode() != SpvOpTypeSampler) {
+  if (!result_type || result_type->opcode() != spv::Op::OpTypeSampler) {
     return _.diag(SPV_ERROR_INVALID_ID, result_type)
-           << "OpConstantSampler Result Type <id> '"
-           << _.getIdName(inst->type_id()) << "' is not a sampler type.";
+           << "OpConstantSampler Result Type <id> "
+           << _.getIdName(inst->type_id()) << " is not a sampler type.";
   }
 
   return SPV_SUCCESS;
@@ -300,23 +298,23 @@
   uint16_t opcode;
   uint16_t word_count;
   spvOpcodeSplit(instruction[0], &word_count, &opcode);
-  switch (static_cast<SpvOp>(opcode)) {
-    case SpvOpTypeBool:
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeEvent:
-    case SpvOpTypeDeviceEvent:
-    case SpvOpTypeReserveId:
-    case SpvOpTypeQueue:
+  switch (static_cast<spv::Op>(opcode)) {
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeEvent:
+    case spv::Op::OpTypeDeviceEvent:
+    case spv::Op::OpTypeReserveId:
+    case spv::Op::OpTypeQueue:
       return true;
-    case SpvOpTypeArray:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeCooperativeMatrixNV:
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeVector: {
       auto base_type = _.FindDef(instruction[2]);
       return base_type && IsTypeNullable(base_type->words(), _);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       for (size_t elementIndex = 2; elementIndex < instruction.size();
            ++elementIndex) {
         auto element = _.FindDef(instruction[elementIndex]);
@@ -324,8 +322,9 @@
       }
       return true;
     }
-    case SpvOpTypePointer:
-      if (instruction[2] == SpvStorageClassPhysicalStorageBuffer) {
+    case spv::Op::OpTypePointer:
+      if (spv::StorageClass(instruction[2]) ==
+          spv::StorageClass::PhysicalStorageBuffer) {
         return false;
       }
       return true;
@@ -339,8 +338,8 @@
   const auto result_type = _.FindDef(inst->type_id());
   if (!result_type || !IsTypeNullable(result_type->words(), _)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpConstantNull Result Type <id> '"
-           << _.getIdName(inst->type_id()) << "' cannot have a null value.";
+           << "OpConstantNull Result Type <id> " << _.getIdName(inst->type_id())
+           << " cannot have a null value.";
   }
 
   return SPV_SUCCESS;
@@ -353,7 +352,8 @@
   auto type_id = inst->GetOperandAs<const uint32_t>(0);
   auto type_instruction = _.FindDef(type_id);
   auto type_opcode = type_instruction->opcode();
-  if (type_opcode != SpvOpTypeInt && type_opcode != SpvOpTypeFloat) {
+  if (type_opcode != spv::Op::OpTypeInt &&
+      type_opcode != spv::Op::OpTypeFloat) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Specialization constant "
                                                    "must be an integer or "
                                                    "floating-point number.";
@@ -363,22 +363,22 @@
 
 spv_result_t ValidateSpecConstantOp(ValidationState_t& _,
                                     const Instruction* inst) {
-  const auto op = inst->GetOperandAs<SpvOp>(2);
+  const auto op = inst->GetOperandAs<spv::Op>(2);
 
   // The binary parser already ensures that the op is valid for *some*
   // environment.  Here we check restrictions.
   switch (op) {
-    case SpvOpQuantizeToF16:
-      if (!_.HasCapability(SpvCapabilityShader)) {
+    case spv::Op::OpQuantizeToF16:
+      if (!_.HasCapability(spv::Capability::Shader)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Specialization constant operation " << spvOpcodeString(op)
                << " requires Shader capability";
       }
       break;
 
-    case SpvOpUConvert:
+    case spv::Op::OpUConvert:
       if (!_.features().uconvert_spec_constant_op &&
-          !_.HasCapability(SpvCapabilityKernel)) {
+          !_.HasCapability(spv::Capability::Kernel)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Prior to SPIR-V 1.4, specialization constant operation "
                   "UConvert requires Kernel capability or extension "
@@ -386,27 +386,27 @@
       }
       break;
 
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertFToU:
-    case SpvOpConvertUToF:
-    case SpvOpConvertPtrToU:
-    case SpvOpConvertUToPtr:
-    case SpvOpGenericCastToPtr:
-    case SpvOpPtrCastToGeneric:
-    case SpvOpBitcast:
-    case SpvOpFNegate:
-    case SpvOpFAdd:
-    case SpvOpFSub:
-    case SpvOpFMul:
-    case SpvOpFDiv:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
-      if (!_.HasCapability(SpvCapabilityKernel)) {
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpConvertPtrToU:
+    case spv::Op::OpConvertUToPtr:
+    case spv::Op::OpGenericCastToPtr:
+    case spv::Op::OpPtrCastToGeneric:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpFSub:
+    case spv::Op::OpFMul:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
+      if (!_.HasCapability(spv::Capability::Kernel)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Specialization constant operation " << spvOpcodeString(op)
                << " requires Kernel capability";
@@ -425,26 +425,26 @@
 
 spv_result_t ConstantPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpConstantTrue:
-    case SpvOpConstantFalse:
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstantFalse:
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
       if (auto error = ValidateConstantBool(_, inst)) return error;
       break;
-    case SpvOpConstantComposite:
-    case SpvOpSpecConstantComposite:
+    case spv::Op::OpConstantComposite:
+    case spv::Op::OpSpecConstantComposite:
       if (auto error = ValidateConstantComposite(_, inst)) return error;
       break;
-    case SpvOpConstantSampler:
+    case spv::Op::OpConstantSampler:
       if (auto error = ValidateConstantSampler(_, inst)) return error;
       break;
-    case SpvOpConstantNull:
+    case spv::Op::OpConstantNull:
       if (auto error = ValidateConstantNull(_, inst)) return error;
       break;
-    case SpvOpSpecConstant:
+    case spv::Op::OpSpecConstant:
       if (auto error = ValidateSpecConstant(_, inst)) return error;
       break;
-    case SpvOpSpecConstantOp:
+    case spv::Op::OpSpecConstantOp:
       if (auto error = ValidateSpecConstantOp(_, inst)) return error;
       break;
     default:
@@ -454,7 +454,7 @@
   // Generally disallow creating 8- or 16-bit constants unless the full
   // capabilities are present.
   if (spvOpcodeIsConstant(inst->opcode()) &&
-      _.HasCapability(SpvCapabilityShader) &&
+      _.HasCapability(spv::Capability::Shader) &&
       !_.IsPointerType(inst->type_id()) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
diff --git a/third_party/SPIRV-Tools/source/val/validate_conversion.cpp b/third_party/SPIRV-Tools/source/val/validate_conversion.cpp
index dc6b151..c67b196 100644
--- a/third_party/SPIRV-Tools/source/val/validate_conversion.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_conversion.cpp
@@ -27,11 +27,11 @@
 
 // Validates correctness of conversion instructions.
 spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpConvertFToU: {
+    case spv::Op::OpConvertFToU: {
       if (!_.IsUnsignedIntScalarType(result_type) &&
           !_.IsUnsignedIntVectorType(result_type) &&
           !_.IsUnsignedIntCooperativeMatrixType(result_type))
@@ -62,7 +62,7 @@
       break;
     }
 
-    case SpvOpConvertFToS: {
+    case spv::Op::OpConvertFToS: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
           !_.IsIntCooperativeMatrixType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -92,8 +92,8 @@
       break;
     }
 
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF: {
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF: {
       if (!_.IsFloatScalarType(result_type) &&
           !_.IsFloatVectorType(result_type) &&
           !_.IsFloatCooperativeMatrixType(result_type))
@@ -124,7 +124,7 @@
       break;
     }
 
-    case SpvOpUConvert: {
+    case spv::Op::OpUConvert: {
       if (!_.IsUnsignedIntScalarType(result_type) &&
           !_.IsUnsignedIntVectorType(result_type) &&
           !_.IsUnsignedIntCooperativeMatrixType(result_type))
@@ -160,7 +160,7 @@
       break;
     }
 
-    case SpvOpSConvert: {
+    case spv::Op::OpSConvert: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
           !_.IsIntCooperativeMatrixType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -195,7 +195,7 @@
       break;
     }
 
-    case SpvOpFConvert: {
+    case spv::Op::OpFConvert: {
       if (!_.IsFloatScalarType(result_type) &&
           !_.IsFloatVectorType(result_type) &&
           !_.IsFloatCooperativeMatrixType(result_type))
@@ -231,7 +231,7 @@
       break;
     }
 
-    case SpvOpQuantizeToF16: {
+    case spv::Op::OpQuantizeToF16: {
       if ((!_.IsFloatScalarType(result_type) &&
            !_.IsFloatVectorType(result_type)) ||
           _.GetBitWidth(result_type) != 32)
@@ -247,7 +247,7 @@
       break;
     }
 
-    case SpvOpConvertPtrToU: {
+    case spv::Op::OpConvertPtrToU: {
       if (!_.IsUnsignedIntScalarType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected unsigned int scalar type as Result Type: "
@@ -258,17 +258,18 @@
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
 
-      if (_.addressing_model() == SpvAddressingModelLogical)
+      if (_.addressing_model() == spv::AddressingModel::Logical)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Logical addressing not supported: "
                << spvOpcodeString(opcode);
 
-      if (_.addressing_model() == SpvAddressingModelPhysicalStorageBuffer64) {
-        uint32_t input_storage_class = 0;
+      if (_.addressing_model() ==
+          spv::AddressingModel::PhysicalStorageBuffer64) {
+        spv::StorageClass input_storage_class;
         uint32_t input_data_type = 0;
         _.GetPointerTypeInfo(input_type, &input_data_type,
                              &input_storage_class);
-        if (input_storage_class != SpvStorageClassPhysicalStorageBuffer)
+        if (input_storage_class != spv::StorageClass::PhysicalStorageBuffer)
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Pointer storage class must be PhysicalStorageBuffer: "
                  << spvOpcodeString(opcode);
@@ -286,8 +287,8 @@
       break;
     }
 
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS: {
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar or vector type as Result Type: "
@@ -307,7 +308,7 @@
       break;
     }
 
-    case SpvOpConvertUToPtr: {
+    case spv::Op::OpConvertUToPtr: {
       if (!_.IsPointerType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to be a pointer: "
@@ -318,17 +319,18 @@
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar as input: " << spvOpcodeString(opcode);
 
-      if (_.addressing_model() == SpvAddressingModelLogical)
+      if (_.addressing_model() == spv::AddressingModel::Logical)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Logical addressing not supported: "
                << spvOpcodeString(opcode);
 
-      if (_.addressing_model() == SpvAddressingModelPhysicalStorageBuffer64) {
-        uint32_t result_storage_class = 0;
+      if (_.addressing_model() ==
+          spv::AddressingModel::PhysicalStorageBuffer64) {
+        spv::StorageClass result_storage_class;
         uint32_t result_data_type = 0;
         _.GetPointerTypeInfo(result_type, &result_data_type,
                              &result_storage_class);
-        if (result_storage_class != SpvStorageClassPhysicalStorageBuffer)
+        if (result_storage_class != spv::StorageClass::PhysicalStorageBuffer)
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Pointer storage class must be PhysicalStorageBuffer: "
                  << spvOpcodeString(opcode);
@@ -346,8 +348,8 @@
       break;
     }
 
-    case SpvOpPtrCastToGeneric: {
-      uint32_t result_storage_class = 0;
+    case spv::Op::OpPtrCastToGeneric: {
+      spv::StorageClass result_storage_class;
       uint32_t result_data_type = 0;
       if (!_.GetPointerTypeInfo(result_type, &result_data_type,
                                 &result_storage_class))
@@ -355,22 +357,22 @@
                << "Expected Result Type to be a pointer: "
                << spvOpcodeString(opcode);
 
-      if (result_storage_class != SpvStorageClassGeneric)
+      if (result_storage_class != spv::StorageClass::Generic)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to have storage class Generic: "
                << spvOpcodeString(opcode);
 
       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
-      uint32_t input_storage_class = 0;
+      spv::StorageClass input_storage_class;
       uint32_t input_data_type = 0;
       if (!_.GetPointerTypeInfo(input_type, &input_data_type,
                                 &input_storage_class))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
 
-      if (input_storage_class != SpvStorageClassWorkgroup &&
-          input_storage_class != SpvStorageClassCrossWorkgroup &&
-          input_storage_class != SpvStorageClassFunction)
+      if (input_storage_class != spv::StorageClass::Workgroup &&
+          input_storage_class != spv::StorageClass::CrossWorkgroup &&
+          input_storage_class != spv::StorageClass::Function)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to have storage class Workgroup, "
                << "CrossWorkgroup or Function: " << spvOpcodeString(opcode);
@@ -382,8 +384,8 @@
       break;
     }
 
-    case SpvOpGenericCastToPtr: {
-      uint32_t result_storage_class = 0;
+    case spv::Op::OpGenericCastToPtr: {
+      spv::StorageClass result_storage_class;
       uint32_t result_data_type = 0;
       if (!_.GetPointerTypeInfo(result_type, &result_data_type,
                                 &result_storage_class))
@@ -391,22 +393,22 @@
                << "Expected Result Type to be a pointer: "
                << spvOpcodeString(opcode);
 
-      if (result_storage_class != SpvStorageClassWorkgroup &&
-          result_storage_class != SpvStorageClassCrossWorkgroup &&
-          result_storage_class != SpvStorageClassFunction)
+      if (result_storage_class != spv::StorageClass::Workgroup &&
+          result_storage_class != spv::StorageClass::CrossWorkgroup &&
+          result_storage_class != spv::StorageClass::Function)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to have storage class Workgroup, "
                << "CrossWorkgroup or Function: " << spvOpcodeString(opcode);
 
       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
-      uint32_t input_storage_class = 0;
+      spv::StorageClass input_storage_class;
       uint32_t input_data_type = 0;
       if (!_.GetPointerTypeInfo(input_type, &input_data_type,
                                 &input_storage_class))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
 
-      if (input_storage_class != SpvStorageClassGeneric)
+      if (input_storage_class != spv::StorageClass::Generic)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to have storage class Generic: "
                << spvOpcodeString(opcode);
@@ -418,8 +420,8 @@
       break;
     }
 
-    case SpvOpGenericCastToPtrExplicit: {
-      uint32_t result_storage_class = 0;
+    case spv::Op::OpGenericCastToPtrExplicit: {
+      spv::StorageClass result_storage_class;
       uint32_t result_data_type = 0;
       if (!_.GetPointerTypeInfo(result_type, &result_data_type,
                                 &result_storage_class))
@@ -427,21 +429,22 @@
                << "Expected Result Type to be a pointer: "
                << spvOpcodeString(opcode);
 
-      const uint32_t target_storage_class = inst->word(4);
+      const auto target_storage_class =
+          inst->GetOperandAs<spv::StorageClass>(3);
       if (result_storage_class != target_storage_class)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to be of target storage class: "
                << spvOpcodeString(opcode);
 
       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
-      uint32_t input_storage_class = 0;
+      spv::StorageClass input_storage_class;
       uint32_t input_data_type = 0;
       if (!_.GetPointerTypeInfo(input_type, &input_data_type,
                                 &input_storage_class))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
 
-      if (input_storage_class != SpvStorageClassGeneric)
+      if (input_storage_class != spv::StorageClass::Generic)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to have storage class Generic: "
                << spvOpcodeString(opcode);
@@ -451,16 +454,16 @@
                << "Expected input and Result Type to point to the same type: "
                << spvOpcodeString(opcode);
 
-      if (target_storage_class != SpvStorageClassWorkgroup &&
-          target_storage_class != SpvStorageClassCrossWorkgroup &&
-          target_storage_class != SpvStorageClassFunction)
+      if (target_storage_class != spv::StorageClass::Workgroup &&
+          target_storage_class != spv::StorageClass::CrossWorkgroup &&
+          target_storage_class != spv::StorageClass::Function)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected target storage class to be Workgroup, "
                << "CrossWorkgroup or Function: " << spvOpcodeString(opcode);
       break;
     }
 
-    case SpvOpBitcast: {
+    case spv::Op::OpBitcast: {
       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
       if (!input_type)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -490,10 +493,10 @@
           _.HasExtension(kSPV_KHR_physical_storage_buffer)) {
         const bool result_is_int_vector = _.IsIntVectorType(result_type);
         const bool result_has_int32 =
-            _.ContainsSizedIntOrFloatType(result_type, SpvOpTypeInt, 32);
+            _.ContainsSizedIntOrFloatType(result_type, spv::Op::OpTypeInt, 32);
         const bool input_is_int_vector = _.IsIntVectorType(input_type);
         const bool input_has_int32 =
-            _.ContainsSizedIntOrFloatType(input_type, SpvOpTypeInt, 32);
+            _.ContainsSizedIntOrFloatType(input_type, spv::Op::OpTypeInt, 32);
         if (result_is_pointer && !input_is_pointer && !input_is_int_scalar &&
             !(input_is_int_vector && input_has_int32))
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -534,7 +537,7 @@
       break;
     }
 
-    case SpvOpConvertUToAccelerationStructureKHR: {
+    case spv::Op::OpConvertUToAccelerationStructureKHR: {
       if (!_.IsAccelerationStructureType(result_type)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to be a Acceleration Structure: "
@@ -556,13 +559,13 @@
       break;
   }
 
-  if (_.HasCapability(SpvCapabilityShader)) {
+  if (_.HasCapability(spv::Capability::Shader)) {
     switch (inst->opcode()) {
-      case SpvOpConvertFToU:
-      case SpvOpConvertFToS:
-      case SpvOpConvertSToF:
-      case SpvOpConvertUToF:
-      case SpvOpBitcast:
+      case spv::Op::OpConvertFToU:
+      case spv::Op::OpConvertFToS:
+      case spv::Op::OpConvertSToF:
+      case spv::Op::OpConvertUToF:
+      case spv::Op::OpBitcast:
         if (_.ContainsLimitedUseIntOrFloatType(inst->type_id()) ||
             _.ContainsLimitedUseIntOrFloatType(_.GetOperandTypeId(inst, 2u))) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
diff --git a/third_party/SPIRV-Tools/source/val/validate_debug.cpp b/third_party/SPIRV-Tools/source/val/validate_debug.cpp
index 0a25d8a..c433c93 100644
--- a/third_party/SPIRV-Tools/source/val/validate_debug.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_debug.cpp
@@ -26,18 +26,18 @@
 spv_result_t ValidateMemberName(ValidationState_t& _, const Instruction* inst) {
   const auto type_id = inst->GetOperandAs<uint32_t>(0);
   const auto type = _.FindDef(type_id);
-  if (!type || SpvOpTypeStruct != type->opcode()) {
+  if (!type || spv::Op::OpTypeStruct != type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpMemberName Type <id> '" << _.getIdName(type_id)
-           << "' is not a struct type.";
+           << "OpMemberName Type <id> " << _.getIdName(type_id)
+           << " is not a struct type.";
   }
   const auto member_id = inst->GetOperandAs<uint32_t>(1);
   const auto member_count = (uint32_t)(type->words().size() - 2);
   if (member_count <= member_id) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpMemberName Member <id> '" << _.getIdName(member_id)
-           << "' index is larger than Type <id> '" << _.getIdName(type->id())
-           << "'s member count.";
+           << "OpMemberName Member <id> " << _.getIdName(member_id)
+           << " index is larger than Type <id> " << _.getIdName(type->id())
+           << "s member count.";
   }
   return SPV_SUCCESS;
 }
@@ -45,10 +45,10 @@
 spv_result_t ValidateLine(ValidationState_t& _, const Instruction* inst) {
   const auto file_id = inst->GetOperandAs<uint32_t>(0);
   const auto file = _.FindDef(file_id);
-  if (!file || SpvOpString != file->opcode()) {
+  if (!file || spv::Op::OpString != file->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpLine Target <id> '" << _.getIdName(file_id)
-           << "' is not an OpString.";
+           << "OpLine Target <id> " << _.getIdName(file_id)
+           << " is not an OpString.";
   }
   return SPV_SUCCESS;
 }
@@ -57,10 +57,10 @@
 
 spv_result_t DebugPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpMemberName:
+    case spv::Op::OpMemberName:
       if (auto error = ValidateMemberName(_, inst)) return error;
       break;
-    case SpvOpLine:
+    case spv::Op::OpLine:
       if (auto error = ValidateLine(_, inst)) return error;
       break;
     default:
diff --git a/third_party/SPIRV-Tools/source/val/validate_decorations.cpp b/third_party/SPIRV-Tools/source/val/validate_decorations.cpp
index 4e4f108..ef9753d 100644
--- a/third_party/SPIRV-Tools/source/val/validate_decorations.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_decorations.cpp
@@ -50,7 +50,7 @@
 
 // A functor for hashing decoration types.
 struct SpvDecorationHash {
-  std::size_t operator()(SpvDecoration dec) const {
+  std::size_t operator()(spv::Decoration dec) const {
     return static_cast<std::size_t>(dec);
   }
 };
@@ -72,7 +72,7 @@
 // Returns the array stride of the given array type.
 uint32_t GetArrayStride(uint32_t array_id, ValidationState_t& vstate) {
   for (auto& decoration : vstate.id_decorations(array_id)) {
-    if (SpvDecorationArrayStride == decoration.dec_type()) {
+    if (spv::Decoration::ArrayStride == decoration.dec_type()) {
       return decoration.params()[0];
     }
   }
@@ -82,9 +82,10 @@
 // Returns true if the given variable has a BuiltIn decoration.
 bool isBuiltInVar(uint32_t var_id, ValidationState_t& vstate) {
   const auto& decorations = vstate.id_decorations(var_id);
-  return std::any_of(
-      decorations.begin(), decorations.end(),
-      [](const Decoration& d) { return SpvDecorationBuiltIn == d.dec_type(); });
+  return std::any_of(decorations.begin(), decorations.end(),
+                     [](const Decoration& d) {
+                       return spv::Decoration::BuiltIn == d.dec_type();
+                     });
 }
 
 // Returns true if the given structure type has any members with BuiltIn
@@ -93,7 +94,7 @@
   const auto& decorations = vstate.id_decorations(struct_id);
   return std::any_of(
       decorations.begin(), decorations.end(), [](const Decoration& d) {
-        return SpvDecorationBuiltIn == d.dec_type() &&
+        return spv::Decoration::BuiltIn == d.dec_type() &&
                Decoration::kInvalidMember != d.struct_member_index();
       });
 }
@@ -101,20 +102,21 @@
 // Returns true if the given structure type has a Block decoration.
 bool isBlock(uint32_t struct_id, ValidationState_t& vstate) {
   const auto& decorations = vstate.id_decorations(struct_id);
-  return std::any_of(
-      decorations.begin(), decorations.end(),
-      [](const Decoration& d) { return SpvDecorationBlock == d.dec_type(); });
+  return std::any_of(decorations.begin(), decorations.end(),
+                     [](const Decoration& d) {
+                       return spv::Decoration::Block == d.dec_type();
+                     });
 }
 
 // Returns true if the given ID has the Import LinkageAttributes decoration.
 bool hasImportLinkageAttribute(uint32_t id, ValidationState_t& vstate) {
   const auto& decorations = vstate.id_decorations(id);
-  return std::any_of(decorations.begin(), decorations.end(),
-                     [](const Decoration& d) {
-                       return SpvDecorationLinkageAttributes == d.dec_type() &&
-                              d.params().size() >= 2u &&
-                              d.params().back() == SpvLinkageTypeImport;
-                     });
+  return std::any_of(
+      decorations.begin(), decorations.end(), [](const Decoration& d) {
+        return spv::Decoration::LinkageAttributes == d.dec_type() &&
+               d.params().size() >= 2u &&
+               spv::LinkageType(d.params().back()) == spv::LinkageType::Import;
+      });
 }
 
 // Returns a vector of all members of a structure.
@@ -125,7 +127,7 @@
 }
 
 // Returns a vector of all members of a structure that have specific type.
-std::vector<uint32_t> getStructMembers(uint32_t struct_id, SpvOp type,
+std::vector<uint32_t> getStructMembers(uint32_t struct_id, spv::Op type,
                                        ValidationState_t& vstate) {
   std::vector<uint32_t> members;
   for (auto id : getStructMembers(struct_id, vstate)) {
@@ -142,21 +144,21 @@
   const auto* inst = vstate.FindDef(struct_id);
   std::vector<bool> hasOffset;
   std::vector<uint32_t> struct_members;
-  if (inst->opcode() == SpvOpTypeStruct) {
+  if (inst->opcode() == spv::Op::OpTypeStruct) {
     // Check offsets of member decorations.
     struct_members = getStructMembers(struct_id, vstate);
     hasOffset.resize(struct_members.size(), false);
 
     for (auto& decoration : vstate.id_decorations(struct_id)) {
-      if (SpvDecorationOffset == decoration.dec_type() &&
+      if (spv::Decoration::Offset == decoration.dec_type() &&
           Decoration::kInvalidMember != decoration.struct_member_index()) {
         // Offset 0xffffffff is not valid so ignore it for simplicity's sake.
         if (decoration.params()[0] == 0xffffffff) return true;
         hasOffset[decoration.struct_member_index()] = true;
       }
     }
-  } else if (inst->opcode() == SpvOpTypeArray ||
-             inst->opcode() == SpvOpTypeRuntimeArray) {
+  } else if (inst->opcode() == spv::Op::OpTypeArray ||
+             inst->opcode() == spv::Op::OpTypeRuntimeArray) {
     hasOffset.resize(1, true);
     struct_members.push_back(inst->GetOperandAs<uint32_t>(1u));
   }
@@ -179,8 +181,9 @@
 }
 
 // Returns base alignment of struct member. If |roundUp| is true, also
-// ensure that structs and arrays are aligned at least to a multiple of 16
-// bytes.
+// ensure that structs, arrays, and matrices are aligned at least to a
+// multiple of 16 bytes.  (That is, when roundUp is true, this function
+// returns the *extended* alignment as it's called by the Vulkan spec.)
 uint32_t getBaseAlignment(uint32_t member_id, bool roundUp,
                           const LayoutConstraints& inherited,
                           MemberConstraints& constraints,
@@ -190,18 +193,18 @@
   // Minimal alignment is byte-aligned.
   uint32_t baseAlignment = 1;
   switch (inst->opcode()) {
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeImage:
-      if (vstate.HasCapability(SpvCapabilityBindlessTextureNV))
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeImage:
+      if (vstate.HasCapability(spv::Capability::BindlessTextureNV))
         return baseAlignment = vstate.samplerimage_variable_address_mode() / 8;
       assert(0);
       return 0;
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       baseAlignment = words[2] / 8;
       break;
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       const auto componentId = words[2];
       const auto numComponents = words[3];
       const auto componentAlignment = getBaseAlignment(
@@ -210,7 +213,7 @@
           componentAlignment * (numComponents == 3 ? 4 : numComponents);
       break;
     }
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       const auto column_type = words[2];
       if (inherited.majorness == kColumnMajor) {
         baseAlignment = getBaseAlignment(column_type, roundUp, inherited,
@@ -228,13 +231,13 @@
       }
       if (roundUp) baseAlignment = align(baseAlignment, 16u);
     } break;
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       baseAlignment =
           getBaseAlignment(words[2], roundUp, inherited, constraints, vstate);
       if (roundUp) baseAlignment = align(baseAlignment, 16u);
       break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const auto members = getStructMembers(member_id, vstate);
       for (uint32_t memberIdx = 0, numMembers = uint32_t(members.size());
            memberIdx < numMembers; ++memberIdx) {
@@ -248,7 +251,7 @@
       if (roundUp) baseAlignment = align(baseAlignment, 16u);
       break;
     }
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       baseAlignment = vstate.pointer_size_and_alignment();
       break;
     default:
@@ -264,24 +267,24 @@
   const auto inst = vstate.FindDef(type_id);
   const auto& words = inst->words();
   switch (inst->opcode()) {
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeImage:
-      if (vstate.HasCapability(SpvCapabilityBindlessTextureNV))
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeImage:
+      if (vstate.HasCapability(spv::Capability::BindlessTextureNV))
         return vstate.samplerimage_variable_address_mode() / 8;
       assert(0);
       return 0;
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       return words[2] / 8;
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray: {
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray: {
       const auto compositeMemberTypeId = words[2];
       return getScalarAlignment(compositeMemberTypeId, vstate);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const auto members = getStructMembers(type_id, vstate);
       uint32_t max_member_alignment = 1;
       for (uint32_t memberIdx = 0, numMembers = uint32_t(members.size());
@@ -294,7 +297,7 @@
       }
       return max_member_alignment;
     } break;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       return vstate.pointer_size_and_alignment();
     default:
       assert(0);
@@ -311,17 +314,17 @@
   const auto inst = vstate.FindDef(member_id);
   const auto& words = inst->words();
   switch (inst->opcode()) {
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeImage:
-      if (vstate.HasCapability(SpvCapabilityBindlessTextureNV))
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeImage:
+      if (vstate.HasCapability(spv::Capability::BindlessTextureNV))
         return vstate.samplerimage_variable_address_mode() / 8;
       assert(0);
       return 0;
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       return words[2] / 8;
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       const auto componentId = words[2];
       const auto numComponents = words[3];
       const auto componentSize =
@@ -329,10 +332,10 @@
       const auto size = componentSize * numComponents;
       return size;
     }
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       const auto sizeInst = vstate.FindDef(words[3]);
       if (spvOpcodeIsSpecConstant(sizeInst->opcode())) return 0;
-      assert(SpvOpConstant == sizeInst->opcode());
+      assert(spv::Op::OpConstant == sizeInst->opcode());
       const uint32_t num_elem = sizeInst->words()[3];
       const uint32_t elem_type = words[2];
       const uint32_t elem_size =
@@ -343,9 +346,9 @@
           (num_elem - 1) * GetArrayStride(member_id, vstate) + elem_size;
       return size;
     }
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       return 0;
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       const auto num_columns = words[3];
       if (inherited.majorness == kColumnMajor) {
         return num_columns * inherited.matrix_stride;
@@ -361,7 +364,7 @@
                num_columns * scalar_elem_size;
       }
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const auto& members = getStructMembers(member_id, vstate);
       if (members.empty()) return 0;
       const auto lastIdx = uint32_t(members.size() - 1);
@@ -373,7 +376,7 @@
       for (auto decoration = member_decorations.begin;
            decoration != member_decorations.end; ++decoration) {
         assert(decoration->struct_member_index() == (int)lastIdx);
-        if (SpvDecorationOffset == decoration->dec_type()) {
+        if (spv::Decoration::Offset == decoration->dec_type()) {
           offset = decoration->params()[0];
         }
       }
@@ -383,7 +386,7 @@
       const auto& constraint = constraints[std::make_pair(lastMember, lastIdx)];
       return offset + getSize(lastMember, constraint, constraints, vstate);
     }
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       return vstate.pointer_size_and_alignment();
     default:
       assert(0);
@@ -476,7 +479,7 @@
          decoration != member_decorations.end; ++decoration) {
       assert(decoration->struct_member_index() == (int)memberIdx);
       switch (decoration->dec_type()) {
-        case SpvDecorationOffset:
+        case spv::Decoration::Offset:
           offset = decoration->params()[0];
           break;
         default:
@@ -516,7 +519,7 @@
     if (offset == 0xffffffff)
       return fail(memberIdx) << "is missing an Offset decoration";
     if (!scalar_block_layout && relaxed_block_layout &&
-        opcode == SpvOpTypeVector) {
+        opcode == spv::Op::OpTypeVector) {
       // In relaxed block layout, the vector offset must be aligned to the
       // vector's scalar element type.
       const auto componentId = inst->words()[2];
@@ -540,21 +543,20 @@
                              << nextValidOffset - 1;
     if (!scalar_block_layout && relaxed_block_layout) {
       // Check improper straddle of vectors.
-      if (SpvOpTypeVector == opcode &&
+      if (spv::Op::OpTypeVector == opcode &&
           hasImproperStraddle(id, offset, constraint, constraints, vstate))
         return fail(memberIdx)
                << "is an improperly straddling vector at offset " << offset;
     }
     // Check struct members recursively.
     spv_result_t recursive_status = SPV_SUCCESS;
-    if (SpvOpTypeStruct == opcode &&
+    if (spv::Op::OpTypeStruct == opcode &&
         SPV_SUCCESS != (recursive_status = checkLayout(
                             id, storage_class_str, decoration_str, blockRules,
-                            scalar_block_layout,
-                            offset, constraints, vstate)))
+                            scalar_block_layout, offset, constraints, vstate)))
       return recursive_status;
     // Check matrix stride.
-    if (SpvOpTypeMatrix == opcode) {
+    if (spv::Op::OpTypeMatrix == opcode) {
       const auto stride = constraint.matrix_stride;
       if (!IsAlignedTo(stride, alignment)) {
         return fail(memberIdx) << "is a matrix with stride " << stride
@@ -565,14 +567,14 @@
     // Check arrays and runtime arrays recursively.
     auto array_inst = inst;
     auto array_alignment = alignment;
-    while (array_inst->opcode() == SpvOpTypeArray ||
-           array_inst->opcode() == SpvOpTypeRuntimeArray) {
+    while (array_inst->opcode() == spv::Op::OpTypeArray ||
+           array_inst->opcode() == spv::Op::OpTypeRuntimeArray) {
       const auto typeId = array_inst->word(2);
       const auto element_inst = vstate.FindDef(typeId);
       // Check array stride.
       uint32_t array_stride = 0;
       for (auto& decoration : vstate.id_decorations(array_inst->id())) {
-        if (SpvDecorationArrayStride == decoration.dec_type()) {
+        if (spv::Decoration::ArrayStride == decoration.dec_type()) {
           array_stride = decoration.params()[0];
           if (array_stride == 0) {
             return fail(memberIdx) << "contains an array with stride 0";
@@ -587,7 +589,7 @@
       bool is_int32 = false;
       bool is_const = false;
       uint32_t num_elements = 0;
-      if (array_inst->opcode() == SpvOpTypeArray) {
+      if (array_inst->opcode() == spv::Op::OpTypeArray) {
         std::tie(is_int32, is_const, num_elements) =
             vstate.EvalInt32IfConst(array_inst->word(3));
       }
@@ -596,7 +598,7 @@
       // limitation to this check if the array size is a spec constant or is a
       // runtime array then we will only check a single element. This means
       // some improper straddles might be missed.
-      if (SpvOpTypeStruct == element_inst->opcode()) {
+      if (spv::Op::OpTypeStruct == element_inst->opcode()) {
         std::vector<bool> seen(16, false);
         for (uint32_t i = 0; i < num_elements; ++i) {
           uint32_t next_offset = i * array_stride + offset;
@@ -632,7 +634,7 @@
     }
     nextValidOffset = offset + size;
     if (!scalar_block_layout && blockRules &&
-        (SpvOpTypeArray == opcode || SpvOpTypeStruct == opcode)) {
+        (spv::Op::OpTypeArray == opcode || spv::Op::OpTypeStruct == opcode)) {
       // Uniform block rules don't permit anything in the padding of a struct
       // or array.
       nextValidOffset = align(nextValidOffset, alignment);
@@ -643,15 +645,15 @@
 
 // Returns true if variable or structure id has given decoration. Handles also
 // nested structures.
-bool hasDecoration(uint32_t id, SpvDecoration decoration,
+bool hasDecoration(uint32_t id, spv::Decoration decoration,
                    ValidationState_t& vstate) {
   for (auto& dec : vstate.id_decorations(id)) {
     if (decoration == dec.dec_type()) return true;
   }
-  if (SpvOpTypeStruct != vstate.FindDef(id)->opcode()) {
+  if (spv::Op::OpTypeStruct != vstate.FindDef(id)->opcode()) {
     return false;
   }
-  for (auto member_id : getStructMembers(id, SpvOpTypeStruct, vstate)) {
+  for (auto member_id : getStructMembers(id, spv::Op::OpTypeStruct, vstate)) {
     if (hasDecoration(member_id, decoration, vstate)) {
       return true;
     }
@@ -661,8 +663,8 @@
 
 // Returns true if all ids of given type have a specified decoration.
 bool checkForRequiredDecoration(uint32_t struct_id,
-                                std::function<bool(SpvDecoration)> checker,
-                                SpvOp type, ValidationState_t& vstate) {
+                                std::function<bool(spv::Decoration)> checker,
+                                spv::Op type, ValidationState_t& vstate) {
   const auto& members = getStructMembers(struct_id, vstate);
   for (size_t memberIdx = 0; memberIdx < members.size(); memberIdx++) {
     const auto id = members[memberIdx];
@@ -681,7 +683,7 @@
       return false;
     }
   }
-  for (auto id : getStructMembers(struct_id, SpvOpTypeStruct, vstate)) {
+  for (auto id : getStructMembers(struct_id, spv::Op::OpTypeStruct, vstate)) {
     if (!checkForRequiredDecoration(id, checker, type, vstate)) {
       return false;
     }
@@ -737,8 +739,8 @@
   const auto& decorations = vstate.id_decorations(var_id);
   for (const auto& d : decorations) {
     if (spvIsVulkanEnv(vstate.context()->target_env)) {
-      if (d.dec_type() == SpvDecorationLocation ||
-          d.dec_type() == SpvDecorationComponent) {
+      if (d.dec_type() == spv::Decoration::Location ||
+          d.dec_type() == spv::Decoration::Component) {
         return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                << vstate.VkErrorID(4915) << "A BuiltIn variable (id " << var_id
                << ") cannot have any Location or Component decorations";
@@ -761,18 +763,18 @@
       std::unordered_set<Instruction*> seen_vars;
       for (auto interface : desc.interfaces) {
         Instruction* var_instr = vstate.FindDef(interface);
-        if (!var_instr || SpvOpVariable != var_instr->opcode()) {
+        if (!var_instr || spv::Op::OpVariable != var_instr->opcode()) {
           return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                  << "Interfaces passed to OpEntryPoint must be of type "
                     "OpTypeVariable. Found Op"
                  << spvOpcodeString(var_instr->opcode()) << ".";
         }
-        const SpvStorageClass storage_class =
-            var_instr->GetOperandAs<SpvStorageClass>(2);
+        const spv::StorageClass storage_class =
+            var_instr->GetOperandAs<spv::StorageClass>(2);
         if (vstate.version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
           // Starting in 1.4, OpEntryPoint must list all global variables
           // it statically uses and those interfaces must be unique.
-          if (storage_class == SpvStorageClassFunction) {
+          if (storage_class == spv::StorageClass::Function) {
             return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                    << "OpEntryPoint interfaces should only list global "
                       "variables";
@@ -784,14 +786,14 @@
                    << vstate.getIdName(interface) << " is disallowed";
           }
         } else {
-          if (storage_class != SpvStorageClassInput &&
-              storage_class != SpvStorageClassOutput) {
+          if (storage_class != spv::StorageClass::Input &&
+              storage_class != spv::StorageClass::Output) {
             return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                    << "OpEntryPoint interfaces must be OpVariables with "
                       "Storage Class of Input(1) or Output(3). Found Storage "
                       "Class "
-                   << storage_class << " for Entry Point id " << entry_point
-                   << ".";
+                   << uint32_t(storage_class) << " for Entry Point id "
+                   << entry_point << ".";
           }
         }
 
@@ -802,7 +804,7 @@
         // to.
         const uint32_t type_id = ptr_instr->word(3);
         Instruction* type_instr = vstate.FindDef(type_id);
-        if (type_instr && SpvOpTypeStruct == type_instr->opcode() &&
+        if (type_instr && spv::Op::OpTypeStruct == type_instr->opcode() &&
             isBuiltInStruct(type_id, vstate)) {
           if (!isBlock(type_id, vstate)) {
             return vstate.diag(SPV_ERROR_INVALID_DATA, vstate.FindDef(type_id))
@@ -813,8 +815,9 @@
                       "OpVariable with a structure type that is a block not "
                       "decorated with Location.";
           }
-          if (storage_class == SpvStorageClassInput) ++num_builtin_block_inputs;
-          if (storage_class == SpvStorageClassOutput)
+          if (storage_class == spv::StorageClass::Input)
+            ++num_builtin_block_inputs;
+          if (storage_class == spv::StorageClass::Output)
             ++num_builtin_block_outputs;
           if (num_builtin_block_inputs > 1 || num_builtin_block_outputs > 1)
             break;
@@ -825,12 +828,13 @@
             return error;
         }
 
-        if (storage_class == SpvStorageClassWorkgroup) {
+        if (storage_class == spv::StorageClass::Workgroup) {
           ++num_workgroup_variables;
-          if (type_instr && SpvOpTypeStruct == type_instr->opcode()) {
-            if (hasDecoration(type_id, SpvDecorationBlock, vstate))
+          if (type_instr && spv::Op::OpTypeStruct == type_instr->opcode()) {
+            if (hasDecoration(type_id, spv::Decoration::Block, vstate))
               ++num_workgroup_variables_with_block;
-            if (hasDecoration(var_instr->id(), SpvDecorationAliased, vstate))
+            if (hasDecoration(var_instr->id(), spv::Decoration::Aliased,
+                              vstate))
               ++num_workgroup_variables_with_aliased;
           }
         }
@@ -838,31 +842,32 @@
         if (spvIsVulkanEnv(vstate.context()->target_env)) {
           const auto* models = vstate.GetExecutionModels(entry_point);
           const bool has_frag =
-              models->find(SpvExecutionModelFragment) != models->end();
+              models->find(spv::ExecutionModel::Fragment) != models->end();
           const bool has_vert =
-              models->find(SpvExecutionModelVertex) != models->end();
+              models->find(spv::ExecutionModel::Vertex) != models->end();
           for (const auto& decoration :
                vstate.id_decorations(var_instr->id())) {
-            if (decoration == SpvDecorationFlat ||
-                decoration == SpvDecorationNoPerspective ||
-                decoration == SpvDecorationSample ||
-                decoration == SpvDecorationCentroid) {
+            if (decoration == spv::Decoration::Flat ||
+                decoration == spv::Decoration::NoPerspective ||
+                decoration == spv::Decoration::Sample ||
+                decoration == spv::Decoration::Centroid) {
               // VUID 04670 already validates these decorations are input/output
-              if (storage_class == SpvStorageClassInput &&
+              if (storage_class == spv::StorageClass::Input &&
                   (models->size() > 1 || has_vert)) {
                 return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                        << vstate.VkErrorID(6202)
-                       << "OpEntryPoint interfaces variable must not be vertex "
-                          "execution model with an input storage class for "
-                          "Entry Point id "
+                       << vstate.SpvDecorationString(decoration.dec_type())
+                       << " decorated variable must not be used in vertex "
+                          "execution model as an Input storage class for Entry "
+                          "Point id "
                        << entry_point << ".";
-              } else if (storage_class == SpvStorageClassOutput &&
+              } else if (storage_class == spv::StorageClass::Output &&
                          (models->size() > 1 || has_frag)) {
                 return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                        << vstate.VkErrorID(6201)
-                       << "OpEntryPoint interfaces variable must not be "
-                          "fragment "
-                          "execution model with an output storage class for "
+                       << vstate.SpvDecorationString(decoration.dec_type())
+                       << " decorated variable must not be used in fragment "
+                          "execution model as an Output storage class for "
                           "Entry Point id "
                        << entry_point << ".";
               }
@@ -870,8 +875,9 @@
           }
 
           const bool has_flat =
-              hasDecoration(var_instr->id(), SpvDecorationFlat, vstate);
-          if (has_frag && storage_class == SpvStorageClassInput && !has_flat &&
+              hasDecoration(var_instr->id(), spv::Decoration::Flat, vstate);
+          if (has_frag && storage_class == spv::StorageClass::Input &&
+              !has_flat &&
               ((vstate.IsFloatScalarType(type_id) &&
                 vstate.GetBitWidth(type_id) == 64) ||
                vstate.IsIntScalarOrVectorType(type_id))) {
@@ -896,7 +902,7 @@
       // The LinkageAttributes Decoration cannot be applied to functions
       // targeted by an OpEntryPoint instruction
       for (auto& decoration : vstate.id_decorations(entry_point)) {
-        if (SpvDecorationLinkageAttributes == decoration.dec_type()) {
+        if (spv::Decoration::LinkageAttributes == decoration.dec_type()) {
           const std::string linkage_name =
               spvtools::utils::MakeString(decoration.params());
           return vstate.diag(SPV_ERROR_INVALID_BINARY,
@@ -908,7 +914,8 @@
         }
       }
 
-      if (vstate.HasCapability(SpvCapabilityWorkgroupMemoryExplicitLayoutKHR) &&
+      if (vstate.HasCapability(
+              spv::Capability::WorkgroupMemoryExplicitLayoutKHR) &&
           num_workgroup_variables > 0 &&
           num_workgroup_variables_with_block > 0) {
         if (num_workgroup_variables != num_workgroup_variables_with_block) {
@@ -962,13 +969,13 @@
          decoration != member_decorations.end; ++decoration) {
       assert(decoration->struct_member_index() == (int)memberIdx);
       switch (decoration->dec_type()) {
-        case SpvDecorationRowMajor:
+        case spv::Decoration::RowMajor:
           constraint.majorness = kRowMajor;
           break;
-        case SpvDecorationColMajor:
+        case spv::Decoration::ColMajor:
           constraint.majorness = kColumnMajor;
           break;
-        case SpvDecorationMatrixStride:
+        case spv::Decoration::MatrixStride:
           constraint.matrix_stride = decoration->params()[0];
           break;
         default:
@@ -981,12 +988,12 @@
     const auto member_type_inst = vstate.FindDef(member_type_id);
     const auto opcode = member_type_inst->opcode();
     switch (opcode) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
         ComputeMemberConstraintsForArray(constraints, member_type_id, inherited,
                                          vstate);
         break;
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         ComputeMemberConstraintsForStruct(constraints, member_type_id,
                                           inherited, vstate);
         break;
@@ -1005,12 +1012,12 @@
   const auto elem_type_inst = vstate.FindDef(elem_type_id);
   const auto opcode = elem_type_inst->opcode();
   switch (opcode) {
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       ComputeMemberConstraintsForArray(constraints, elem_type_id, inherited,
                                        vstate);
       break;
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       ComputeMemberConstraintsForStruct(constraints, elem_type_id, inherited,
                                         vstate);
       break;
@@ -1024,16 +1031,18 @@
   std::unordered_set<uint32_t> uses_push_constant;
   for (const auto& inst : vstate.ordered_instructions()) {
     const auto& words = inst.words();
-    if (SpvOpVariable == inst.opcode()) {
+    if (spv::Op::OpVariable == inst.opcode()) {
       const auto var_id = inst.id();
       // For storage class / decoration combinations, see Vulkan 14.5.4 "Offset
       // and Stride Assignment".
-      const auto storageClass = words[3];
-      const bool uniform = storageClass == SpvStorageClassUniform;
+      const auto storageClass = inst.GetOperandAs<spv::StorageClass>(2);
+      const bool uniform = storageClass == spv::StorageClass::Uniform;
       const bool uniform_constant =
-          storageClass == SpvStorageClassUniformConstant;
-      const bool push_constant = storageClass == SpvStorageClassPushConstant;
-      const bool storage_buffer = storageClass == SpvStorageClassStorageBuffer;
+          storageClass == spv::StorageClass::UniformConstant;
+      const bool push_constant =
+          storageClass == spv::StorageClass::PushConstant;
+      const bool storage_buffer =
+          storageClass == spv::StorageClass::StorageBuffer;
 
       if (spvIsVulkanEnv(vstate.context()->target_env)) {
         // Vulkan: There must be no more than one PushConstant block per entry
@@ -1057,7 +1066,7 @@
         if (uniform_constant) {
           auto entry_points = vstate.EntryPointReferences(var_id);
           if (!entry_points.empty() &&
-              !hasDecoration(var_id, SpvDecorationDescriptorSet, vstate)) {
+              !hasDecoration(var_id, spv::Decoration::DescriptorSet, vstate)) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                    << vstate.VkErrorID(6677) << "UniformConstant id '" << var_id
                    << "' is missing DescriptorSet decoration.\n"
@@ -1066,7 +1075,7 @@
                       "decorations specified";
           }
           if (!entry_points.empty() &&
-              !hasDecoration(var_id, SpvDecorationBinding, vstate)) {
+              !hasDecoration(var_id, spv::Decoration::Binding, vstate)) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                    << vstate.VkErrorID(6677) << "UniformConstant id '" << var_id
                    << "' is missing Binding decoration.\n"
@@ -1078,14 +1087,14 @@
       }
 
       if (spvIsOpenGLEnv(vstate.context()->target_env)) {
-        bool has_block = hasDecoration(var_id, SpvDecorationBlock, vstate);
+        bool has_block = hasDecoration(var_id, spv::Decoration::Block, vstate);
         bool has_buffer_block =
-            hasDecoration(var_id, SpvDecorationBufferBlock, vstate);
+            hasDecoration(var_id, spv::Decoration::BufferBlock, vstate);
         if ((uniform && (has_block || has_buffer_block)) ||
             (storage_buffer && has_block)) {
           auto entry_points = vstate.EntryPointReferences(var_id);
           if (!entry_points.empty() &&
-              !hasDecoration(var_id, SpvDecorationBinding, vstate)) {
+              !hasDecoration(var_id, spv::Decoration::Binding, vstate)) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                    << (uniform ? "Uniform" : "Storage Buffer") << " id '"
                    << var_id << "' is missing Binding decoration.\n"
@@ -1097,24 +1106,25 @@
       }
 
       const bool phys_storage_buffer =
-          storageClass == SpvStorageClassPhysicalStorageBuffer;
+          storageClass == spv::StorageClass::PhysicalStorageBuffer;
       const bool workgroup =
-          storageClass == SpvStorageClassWorkgroup &&
-          vstate.HasCapability(SpvCapabilityWorkgroupMemoryExplicitLayoutKHR);
+          storageClass == spv::StorageClass::Workgroup &&
+          vstate.HasCapability(
+              spv::Capability::WorkgroupMemoryExplicitLayoutKHR);
       if (uniform || push_constant || storage_buffer || phys_storage_buffer ||
           workgroup) {
         const auto ptrInst = vstate.FindDef(words[1]);
-        assert(SpvOpTypePointer == ptrInst->opcode());
+        assert(spv::Op::OpTypePointer == ptrInst->opcode());
         auto id = ptrInst->words()[3];
         auto id_inst = vstate.FindDef(id);
         // Jump through one level of arraying.
-        if (!workgroup && (id_inst->opcode() == SpvOpTypeArray ||
-                           id_inst->opcode() == SpvOpTypeRuntimeArray)) {
+        if (!workgroup && (id_inst->opcode() == spv::Op::OpTypeArray ||
+                           id_inst->opcode() == spv::Op::OpTypeRuntimeArray)) {
           id = id_inst->GetOperandAs<uint32_t>(1u);
           id_inst = vstate.FindDef(id);
         }
         // Struct requirement is checked on variables so just move on here.
-        if (SpvOpTypeStruct != id_inst->opcode()) continue;
+        if (spv::Op::OpTypeStruct != id_inst->opcode()) continue;
         MemberConstraints constraints;
         ComputeMemberConstraintsForStruct(&constraints, id, LayoutConstraints(),
                                           vstate);
@@ -1126,9 +1136,9 @@
                                                   : "StorageBuffer"));
 
         if (spvIsVulkanEnv(vstate.context()->target_env)) {
-          const bool block = hasDecoration(id, SpvDecorationBlock, vstate);
+          const bool block = hasDecoration(id, spv::Decoration::Block, vstate);
           const bool buffer_block =
-              hasDecoration(id, SpvDecorationBufferBlock, vstate);
+              hasDecoration(id, spv::Decoration::BufferBlock, vstate);
           if (storage_buffer && buffer_block) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                    << vstate.VkErrorID(6675) << "Storage buffer id '" << var_id
@@ -1166,7 +1176,8 @@
           if (uniform || storage_buffer) {
             auto entry_points = vstate.EntryPointReferences(var_id);
             if (!entry_points.empty() &&
-                !hasDecoration(var_id, SpvDecorationDescriptorSet, vstate)) {
+                !hasDecoration(var_id, spv::Decoration::DescriptorSet,
+                               vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                      << vstate.VkErrorID(6677) << sc_str << " id '" << var_id
                      << "' is missing DescriptorSet decoration.\n"
@@ -1175,7 +1186,7 @@
                         "decorations specified";
             }
             if (!entry_points.empty() &&
-                !hasDecoration(var_id, SpvDecorationBinding, vstate)) {
+                !hasDecoration(var_id, spv::Decoration::Binding, vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                      << vstate.VkErrorID(6677) << sc_str << " id '" << var_id
                      << "' is missing Binding decoration.\n"
@@ -1187,8 +1198,9 @@
         }
 
         for (const auto& dec : vstate.id_decorations(id)) {
-          const bool blockDeco = SpvDecorationBlock == dec.dec_type();
-          const bool bufferDeco = SpvDecorationBufferBlock == dec.dec_type();
+          const bool blockDeco = spv::Decoration::Block == dec.dec_type();
+          const bool bufferDeco =
+              spv::Decoration::BufferBlock == dec.dec_type();
           const bool blockRules = uniform && blockDeco;
           const bool bufferRules =
               (uniform && bufferDeco) ||
@@ -1216,57 +1228,58 @@
                      << "Structure id " << id << " decorated as " << deco_str
                      << " must be explicitly laid out with Offset "
                         "decorations.";
-            } else if (hasDecoration(id, SpvDecorationGLSLShared, vstate)) {
-              return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
-                     << "Structure id " << id << " decorated as " << deco_str
-                     << " must not use GLSLShared decoration.";
-            } else if (hasDecoration(id, SpvDecorationGLSLPacked, vstate)) {
-              return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
-                     << "Structure id " << id << " decorated as " << deco_str
-                     << " must not use GLSLPacked decoration.";
-            } else if (!checkForRequiredDecoration(
-                           id,
-                           [](SpvDecoration d) {
-                             return d == SpvDecorationArrayStride;
-                           },
-                           SpvOpTypeArray, vstate)) {
+            }
+
+            if (!checkForRequiredDecoration(
+                    id,
+                    [](spv::Decoration d) {
+                      return d == spv::Decoration::ArrayStride;
+                    },
+                    spv::Op::OpTypeArray, vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                      << "Structure id " << id << " decorated as " << deco_str
                      << " must be explicitly laid out with ArrayStride "
                         "decorations.";
-            } else if (!checkForRequiredDecoration(
-                           id,
-                           [](SpvDecoration d) {
-                             return d == SpvDecorationMatrixStride;
-                           },
-                           SpvOpTypeMatrix, vstate)) {
+            }
+
+            if (!checkForRequiredDecoration(
+                    id,
+                    [](spv::Decoration d) {
+                      return d == spv::Decoration::MatrixStride;
+                    },
+                    spv::Op::OpTypeMatrix, vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                      << "Structure id " << id << " decorated as " << deco_str
                      << " must be explicitly laid out with MatrixStride "
                         "decorations.";
-            } else if (!checkForRequiredDecoration(
-                           id,
-                           [](SpvDecoration d) {
-                             return d == SpvDecorationRowMajor ||
-                                    d == SpvDecorationColMajor;
-                           },
-                           SpvOpTypeMatrix, vstate)) {
+            }
+
+            if (!checkForRequiredDecoration(
+                    id,
+                    [](spv::Decoration d) {
+                      return d == spv::Decoration::RowMajor ||
+                             d == spv::Decoration::ColMajor;
+                    },
+                    spv::Op::OpTypeMatrix, vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                      << "Structure id " << id << " decorated as " << deco_str
                      << " must be explicitly laid out with RowMajor or "
                         "ColMajor decorations.";
-            } else if (blockRules &&
-                       (SPV_SUCCESS !=
-                        (recursive_status = checkLayout(
-                             id, sc_str, deco_str, true, scalar_block_layout, 0,
-                             constraints, vstate)))) {
-              return recursive_status;
-            } else if (bufferRules &&
-                       (SPV_SUCCESS !=
-                        (recursive_status = checkLayout(
-                             id, sc_str, deco_str, false, scalar_block_layout,
-                             0, constraints, vstate)))) {
-              return recursive_status;
+            }
+
+            if (spvIsVulkanEnv(vstate.context()->target_env)) {
+              if (blockRules && (SPV_SUCCESS != (recursive_status = checkLayout(
+                                                     id, sc_str, deco_str, true,
+                                                     scalar_block_layout, 0,
+                                                     constraints, vstate)))) {
+                return recursive_status;
+              } else if (bufferRules &&
+                         (SPV_SUCCESS !=
+                          (recursive_status = checkLayout(
+                               id, sc_str, deco_str, false, scalar_block_layout,
+                               0, constraints, vstate)))) {
+                return recursive_status;
+              }
             }
           }
         }
@@ -1277,90 +1290,64 @@
 }
 
 // Returns true if |decoration| cannot be applied to the same id more than once.
-bool AtMostOncePerId(SpvDecoration decoration) {
-  return decoration == SpvDecorationArrayStride;
+bool AtMostOncePerId(spv::Decoration decoration) {
+  return decoration == spv::Decoration::ArrayStride;
 }
 
 // Returns true if |decoration| cannot be applied to the same member more than
 // once.
-bool AtMostOncePerMember(SpvDecoration decoration) {
+bool AtMostOncePerMember(spv::Decoration decoration) {
   switch (decoration) {
-    case SpvDecorationOffset:
-    case SpvDecorationMatrixStride:
-    case SpvDecorationRowMajor:
-    case SpvDecorationColMajor:
+    case spv::Decoration::Offset:
+    case spv::Decoration::MatrixStride:
+    case spv::Decoration::RowMajor:
+    case spv::Decoration::ColMajor:
       return true;
     default:
       return false;
   }
 }
 
-// Returns the string name for |decoration|.
-const char* GetDecorationName(SpvDecoration decoration) {
-  switch (decoration) {
-    case SpvDecorationAliased:
-      return "Aliased";
-    case SpvDecorationRestrict:
-      return "Restrict";
-    case SpvDecorationArrayStride:
-      return "ArrayStride";
-    case SpvDecorationOffset:
-      return "Offset";
-    case SpvDecorationMatrixStride:
-      return "MatrixStride";
-    case SpvDecorationRowMajor:
-      return "RowMajor";
-    case SpvDecorationColMajor:
-      return "ColMajor";
-    case SpvDecorationBlock:
-      return "Block";
-    case SpvDecorationBufferBlock:
-      return "BufferBlock";
-    default:
-      return "";
-  }
-}
-
 spv_result_t CheckDecorationsCompatibility(ValidationState_t& vstate) {
-  using PerIDKey = std::tuple<SpvDecoration, uint32_t>;
-  using PerMemberKey = std::tuple<SpvDecoration, uint32_t, uint32_t>;
+  using PerIDKey = std::tuple<spv::Decoration, uint32_t>;
+  using PerMemberKey = std::tuple<spv::Decoration, uint32_t, uint32_t>;
 
   // An Array of pairs where the decorations in the pair cannot both be applied
   // to the same id.
-  static const SpvDecoration mutually_exclusive_per_id[][2] = {
-      {SpvDecorationBlock, SpvDecorationBufferBlock},
-      {SpvDecorationRestrict, SpvDecorationAliased}};
+  static const spv::Decoration mutually_exclusive_per_id[][2] = {
+      {spv::Decoration::Block, spv::Decoration::BufferBlock},
+      {spv::Decoration::Restrict, spv::Decoration::Aliased}};
   static const auto num_mutually_exclusive_per_id_pairs =
-      sizeof(mutually_exclusive_per_id) / (2 * sizeof(SpvDecoration));
+      sizeof(mutually_exclusive_per_id) / (2 * sizeof(spv::Decoration));
 
   // An Array of pairs where the decorations in the pair cannot both be applied
   // to the same member.
-  static const SpvDecoration mutually_exclusive_per_member[][2] = {
-      {SpvDecorationRowMajor, SpvDecorationColMajor}};
+  static const spv::Decoration mutually_exclusive_per_member[][2] = {
+      {spv::Decoration::RowMajor, spv::Decoration::ColMajor}};
   static const auto num_mutually_exclusive_per_mem_pairs =
-      sizeof(mutually_exclusive_per_member) / (2 * sizeof(SpvDecoration));
+      sizeof(mutually_exclusive_per_member) / (2 * sizeof(spv::Decoration));
 
   std::set<PerIDKey> seen_per_id;
   std::set<PerMemberKey> seen_per_member;
 
   for (const auto& inst : vstate.ordered_instructions()) {
     const auto& words = inst.words();
-    if (SpvOpDecorate == inst.opcode()) {
+    if (spv::Op::OpDecorate == inst.opcode()) {
       const auto id = words[1];
-      const auto dec_type = static_cast<SpvDecoration>(words[2]);
+      const auto dec_type = static_cast<spv::Decoration>(words[2]);
       const auto k = PerIDKey(dec_type, id);
       const auto already_used = !seen_per_id.insert(k).second;
       if (already_used && AtMostOncePerId(dec_type)) {
         return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                << "ID '" << id << "' decorated with "
-               << GetDecorationName(dec_type)
+               << vstate.SpvDecorationString(dec_type)
                << " multiple times is not allowed.";
       }
       // Verify certain mutually exclusive decorations are not both applied on
       // an ID.
       for (uint32_t pair_idx = 0;
            pair_idx < num_mutually_exclusive_per_id_pairs; ++pair_idx) {
-        SpvDecoration excl_dec_type = SpvDecorationMax;
+        spv::Decoration excl_dec_type = spv::Decoration::Max;
         if (mutually_exclusive_per_id[pair_idx][0] == dec_type) {
           excl_dec_type = mutually_exclusive_per_id[pair_idx][1];
         } else if (mutually_exclusive_per_id[pair_idx][1] == dec_type) {
@@ -1373,27 +1360,28 @@
         if (seen_per_id.find(excl_k) != seen_per_id.end()) {
           return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                  << "ID '" << id << "' decorated with both "
-                 << GetDecorationName(dec_type) << " and "
-                 << GetDecorationName(excl_dec_type) << " is not allowed.";
+                 << vstate.SpvDecorationString(dec_type) << " and "
+                 << vstate.SpvDecorationString(excl_dec_type)
+                 << " is not allowed.";
         }
       }
-    } else if (SpvOpMemberDecorate == inst.opcode()) {
+    } else if (spv::Op::OpMemberDecorate == inst.opcode()) {
       const auto id = words[1];
       const auto member_id = words[2];
-      const auto dec_type = static_cast<SpvDecoration>(words[3]);
+      const auto dec_type = static_cast<spv::Decoration>(words[3]);
       const auto k = PerMemberKey(dec_type, id, member_id);
       const auto already_used = !seen_per_member.insert(k).second;
       if (already_used && AtMostOncePerMember(dec_type)) {
         return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                << "ID '" << id << "', member '" << member_id
-               << "' decorated with " << GetDecorationName(dec_type)
+               << "' decorated with " << vstate.SpvDecorationString(dec_type)
                << " multiple times is not allowed.";
       }
       // Verify certain mutually exclusive decorations are not both applied on
       // a (ID, member) tuple.
       for (uint32_t pair_idx = 0;
            pair_idx < num_mutually_exclusive_per_mem_pairs; ++pair_idx) {
-        SpvDecoration excl_dec_type = SpvDecorationMax;
+        spv::Decoration excl_dec_type = spv::Decoration::Max;
         if (mutually_exclusive_per_member[pair_idx][0] == dec_type) {
           excl_dec_type = mutually_exclusive_per_member[pair_idx][1];
         } else if (mutually_exclusive_per_member[pair_idx][1] == dec_type) {
@@ -1406,8 +1394,9 @@
         if (seen_per_member.find(excl_k) != seen_per_member.end()) {
           return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                  << "ID '" << id << "', member '" << member_id
-                 << "' decorated with both " << GetDecorationName(dec_type)
-                 << " and " << GetDecorationName(excl_dec_type)
+                 << "' decorated with both "
+                 << vstate.SpvDecorationString(dec_type) << " and "
+                 << vstate.SpvDecorationString(excl_dec_type)
                  << " is not allowed.";
         }
       }
@@ -1418,7 +1407,7 @@
 
 spv_result_t CheckVulkanMemoryModelDeprecatedDecorations(
     ValidationState_t& vstate) {
-  if (vstate.memory_model() != SpvMemoryModelVulkanKHR) return SPV_SUCCESS;
+  if (vstate.memory_model() != spv::MemoryModel::VulkanKHR) return SPV_SUCCESS;
 
   std::string msg;
   std::ostringstream str(msg);
@@ -1427,10 +1416,10 @@
     const auto id = inst->id();
     for (const auto& dec : vstate.id_decorations(id)) {
       const auto member = dec.struct_member_index();
-      if (dec.dec_type() == SpvDecorationCoherent ||
-          dec.dec_type() == SpvDecorationVolatile) {
-        str << (dec.dec_type() == SpvDecorationCoherent ? "Coherent"
-                                                        : "Volatile");
+      if (dec.dec_type() == spv::Decoration::Coherent ||
+          dec.dec_type() == spv::Decoration::Volatile) {
+        str << (dec.dec_type() == spv::Decoration::Coherent ? "Coherent"
+                                                            : "Volatile");
         str << " decoration targeting " << vstate.getIdName(id);
         if (member != Decoration::kInvalidMember) {
           str << " (member index " << member << ")";
@@ -1451,7 +1440,7 @@
                                            const Decoration& decoration) {
   // Validates width-only conversion instruction for floating-point object
   // i.e., OpFConvert
-  if (inst.opcode() != SpvOpFConvert) {
+  if (inst.opcode() != spv::Op::OpFConvert) {
     return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
            << "FPRoundingMode decoration can be applied only to a "
               "width-only conversion instruction for floating-point "
@@ -1459,8 +1448,9 @@
   }
 
   if (spvIsVulkanEnv(vstate.context()->target_env)) {
-    const auto mode = decoration.params()[0];
-    if ((mode != SpvFPRoundingModeRTE) && (mode != SpvFPRoundingModeRTZ)) {
+    const auto mode = spv::FPRoundingMode(decoration.params()[0]);
+    if ((mode != spv::FPRoundingMode::RTE) &&
+        (mode != spv::FPRoundingMode::RTZ)) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << vstate.VkErrorID(4675)
              << "In Vulkan, the FPRoundingMode mode must only by RTE or RTZ.";
@@ -1470,11 +1460,11 @@
   // Validates Object operand of an OpStore
   for (const auto& use : inst.uses()) {
     const auto store = use.first;
-    if (store->opcode() == SpvOpFConvert) continue;
+    if (store->opcode() == spv::Op::OpFConvert) continue;
     if (spvOpcodeIsDebug(store->opcode())) continue;
     if (store->IsNonSemantic()) continue;
     if (spvOpcodeIsDecoration(store->opcode())) continue;
-    if (store->opcode() != SpvOpStore) {
+    if (store->opcode() != spv::Op::OpStore) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "FPRoundingMode decoration can be applied only to the "
                 "Object operand of an OpStore.";
@@ -1500,12 +1490,13 @@
     }
 
     // Validates storage class of the pointer to the OpStore
-    const auto storage = ptr_type->GetOperandAs<uint32_t>(1);
-    if (storage != SpvStorageClassStorageBuffer &&
-        storage != SpvStorageClassUniform &&
-        storage != SpvStorageClassPushConstant &&
-        storage != SpvStorageClassInput && storage != SpvStorageClassOutput &&
-        storage != SpvStorageClassPhysicalStorageBuffer) {
+    const auto storage = ptr_type->GetOperandAs<spv::StorageClass>(1);
+    if (storage != spv::StorageClass::StorageBuffer &&
+        storage != spv::StorageClass::Uniform &&
+        storage != spv::StorageClass::PushConstant &&
+        storage != spv::StorageClass::Input &&
+        storage != spv::StorageClass::Output &&
+        storage != spv::StorageClass::PhysicalStorageBuffer) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "FPRoundingMode decoration can be applied only to the "
                 "Object operand of an OpStore in the StorageBuffer, "
@@ -1530,16 +1521,17 @@
     // First, it must be a variable or function parameter.
     const auto opcode = inst.opcode();
     const auto type_id = inst.type_id();
-    if (opcode != SpvOpVariable && opcode != SpvOpFunctionParameter) {
+    if (opcode != spv::Op::OpVariable &&
+        opcode != spv::Op::OpFunctionParameter) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "Target of NonWritable decoration must be a memory object "
                 "declaration (a variable or a function parameter)";
     }
-    const auto var_storage_class = opcode == SpvOpVariable
-                                       ? inst.GetOperandAs<SpvStorageClass>(2)
-                                       : SpvStorageClassMax;
-    if ((var_storage_class == SpvStorageClassFunction ||
-         var_storage_class == SpvStorageClassPrivate) &&
+    const auto var_storage_class = opcode == spv::Op::OpVariable
+                                       ? inst.GetOperandAs<spv::StorageClass>(2)
+                                       : spv::StorageClass::Max;
+    if ((var_storage_class == spv::StorageClass::Function ||
+         var_storage_class == spv::StorageClass::Private) &&
         vstate.features().nonwritable_var_in_function_or_private) {
       // New permitted feature in SPIR-V 1.4.
     } else if (
@@ -1569,8 +1561,9 @@
 spv_result_t CheckUniformDecoration(ValidationState_t& vstate,
                                     const Instruction& inst,
                                     const Decoration& decoration) {
-  const char* const dec_name =
-      decoration.dec_type() == SpvDecorationUniform ? "Uniform" : "UniformId";
+  const char* const dec_name = decoration.dec_type() == spv::Decoration::Uniform
+                                   ? "Uniform"
+                                   : "UniformId";
 
   // Uniform or UniformId must decorate an "object"
   //  - has a result ID
@@ -1584,7 +1577,7 @@
            << dec_name << " decoration applied to a non-object";
   }
   if (Instruction* type_inst = vstate.FindDef(inst.type_id())) {
-    if (type_inst->opcode() == SpvOpTypeVoid) {
+    if (type_inst->opcode() == spv::Op::OpTypeVoid) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << dec_name << " decoration applied to a value with void type";
     }
@@ -1598,7 +1591,7 @@
   // Use of Uniform with OpDecorate is checked elsewhere.
   // Use of UniformId with OpDecorateId is checked elsewhere.
 
-  if (decoration.dec_type() == SpvDecorationUniformId) {
+  if (decoration.dec_type() == spv::Decoration::UniformId) {
     assert(decoration.params().size() == 1 &&
            "Grammar ensures UniformId has one parameter");
 
@@ -1619,13 +1612,13 @@
                                         const Instruction& inst,
                                         const Decoration& decoration) {
   switch (inst.opcode()) {
-    case SpvOpIAdd:
-    case SpvOpISub:
-    case SpvOpIMul:
-    case SpvOpShiftLeftLogical:
-    case SpvOpSNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpSNegate:
       return SPV_SUCCESS;
-    case SpvOpExtInst:
+    case spv::Op::OpExtInst:
       // TODO(dneto): Only certain extended instructions allow these
       // decorations.  For now allow anything.
       return SPV_SUCCESS;
@@ -1634,7 +1627,7 @@
   }
 
   return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
-         << (decoration.dec_type() == SpvDecorationNoSignedWrap
+         << (decoration.dec_type() == spv::Decoration::NoSignedWrap
                  ? "NoSignedWrap"
                  : "NoUnsignedWrap")
          << " decoration may not be applied to "
@@ -1648,29 +1641,32 @@
                                       const Instruction& inst,
                                       const Decoration& decoration) {
   assert(inst.id() && "Parser ensures the target of the decoration has an ID");
+  assert(decoration.params().size() == 1 &&
+         "Grammar ensures Component has one parameter");
 
   uint32_t type_id;
   if (decoration.struct_member_index() == Decoration::kInvalidMember) {
     // The target must be a memory object declaration.
     const auto opcode = inst.opcode();
-    if (opcode != SpvOpVariable && opcode != SpvOpFunctionParameter) {
+    if (opcode != spv::Op::OpVariable &&
+        opcode != spv::Op::OpFunctionParameter) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "Target of Component decoration must be a memory object "
                 "declaration (a variable or a function parameter)";
     }
 
     // Only valid for the Input and Output Storage Classes.
-    const auto storage_class = opcode == SpvOpVariable
-                                   ? inst.GetOperandAs<SpvStorageClass>(2)
-                                   : SpvStorageClassMax;
-    if (storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput &&
-        storage_class != SpvStorageClassMax) {
+    const auto storage_class = opcode == spv::Op::OpVariable
+                                   ? inst.GetOperandAs<spv::StorageClass>(2)
+                                   : spv::StorageClass::Max;
+    if (storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output &&
+        storage_class != spv::StorageClass::Max) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "Target of Component decoration is invalid: must point to a "
                 "Storage Class of Input(1) or Output(3). Found Storage "
                 "Class "
-             << storage_class;
+             << uint32_t(storage_class);
     }
 
     type_id = inst.type_id();
@@ -1679,7 +1675,7 @@
       type_id = pointer->GetOperandAs<uint32_t>(2);
     }
   } else {
-    if (inst.opcode() != SpvOpTypeStruct) {
+    if (inst.opcode() != spv::Op::OpTypeStruct) {
       return vstate.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "Attempted to get underlying data type via member index for "
                 "non-struct type.";
@@ -1689,30 +1685,56 @@
 
   if (spvIsVulkanEnv(vstate.context()->target_env)) {
     // Strip the array, if present.
-    if (vstate.GetIdOpcode(type_id) == SpvOpTypeArray) {
+    if (vstate.GetIdOpcode(type_id) == spv::Op::OpTypeArray) {
       type_id = vstate.FindDef(type_id)->word(2u);
     }
 
     if (!vstate.IsIntScalarOrVectorType(type_id) &&
         !vstate.IsFloatScalarOrVectorType(type_id)) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
+             << vstate.VkErrorID(4924)
              << "Component decoration specified for type "
              << vstate.getIdName(type_id) << " that is not a scalar or vector";
     }
 
-    // For 16-, and 32-bit types, it is invalid if this sequence of components
-    // gets larger than 3.
+    const auto component = decoration.params()[0];
+    if (component > 3) {
+      return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
+             << vstate.VkErrorID(4920)
+             << "Component decoration value must not be greater than 3";
+    }
+
+    const auto dimension = vstate.GetDimension(type_id);
     const auto bit_width = vstate.GetBitWidth(type_id);
     if (bit_width == 16 || bit_width == 32) {
-      assert(decoration.params().size() == 1 &&
-             "Grammar ensures Component has one parameter");
-
-      const auto component = decoration.params()[0];
-      const auto last_component = component + vstate.GetDimension(type_id) - 1;
-      if (last_component > 3) {
+      const auto sum_component = component + dimension;
+      if (sum_component > 4) {
         return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
+               << vstate.VkErrorID(4921)
                << "Sequence of components starting with " << component
-               << " and ending with " << last_component
+               << " and ending with " << (sum_component - 1)
+               << " gets larger than 3";
+      }
+    } else if (bit_width == 64) {
+      if (dimension > 2) {
+        return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
+               << vstate.VkErrorID(7703)
+               << "Component decoration only allowed on 64-bit scalar and "
+                  "2-component vector";
+      }
+      if (component == 1 || component == 3) {
+        return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
+               << vstate.VkErrorID(4923)
+               << "Component decoration value must not be 1 or 3 for 64-bit "
+                  "data types";
+      }
+      // 64-bit is double per component dimension
+      const auto sum_component = component + (2 * dimension);
+      if (sum_component > 4) {
+        return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
+               << vstate.VkErrorID(4922)
+               << "Sequence of components starting with " << component
+               << " and ending with " << (sum_component - 1)
                << " gets larger than 3";
       }
     }
@@ -1728,9 +1750,10 @@
                                   const Instruction& inst,
                                   const Decoration& decoration) {
   assert(inst.id() && "Parser ensures the target of the decoration has an ID");
-  if (inst.opcode() != SpvOpTypeStruct) {
-    const char* const dec_name =
-        decoration.dec_type() == SpvDecorationBlock ? "Block" : "BufferBlock";
+  if (inst.opcode() != spv::Op::OpTypeStruct) {
+    const char* const dec_name = decoration.dec_type() == spv::Decoration::Block
+                                     ? "Block"
+                                     : "BufferBlock";
     return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
            << dec_name << " decoration on a non-struct type.";
   }
@@ -1740,10 +1763,10 @@
 spv_result_t CheckLocationDecoration(ValidationState_t& vstate,
                                      const Instruction& inst,
                                      const Decoration& decoration) {
-  if (inst.opcode() == SpvOpVariable) return SPV_SUCCESS;
+  if (inst.opcode() == spv::Op::OpVariable) return SPV_SUCCESS;
 
   if (decoration.struct_member_index() != Decoration::kInvalidMember &&
-      inst.opcode() == SpvOpTypeStruct) {
+      inst.opcode() == spv::Op::OpTypeStruct) {
     return SPV_SUCCESS;
   }
 
@@ -1763,7 +1786,7 @@
   }
 
   if (decoration.struct_member_index() != Decoration::kInvalidMember &&
-      inst.opcode() == SpvOpTypeStruct) {
+      inst.opcode() == spv::Op::OpTypeStruct) {
     return SPV_SUCCESS;
   }
   return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
@@ -1782,7 +1805,7 @@
 // propagated down to the group members.
 spv_result_t CheckDecorationsFromDecoration(ValidationState_t& vstate) {
   // Some rules are only checked for shaders.
-  const bool is_shader = vstate.HasCapability(SpvCapabilityShader);
+  const bool is_shader = vstate.HasCapability(spv::Capability::Shader);
 
   for (const auto& kv : vstate.id_decorations()) {
     const uint32_t id = kv.first;
@@ -1794,37 +1817,37 @@
 
     // We assume the decorations applied to a decoration group have already
     // been propagated down to the group members.
-    if (inst->opcode() == SpvOpDecorationGroup) continue;
+    if (inst->opcode() == spv::Op::OpDecorationGroup) continue;
 
     for (const auto& decoration : decorations) {
       switch (decoration.dec_type()) {
-        case SpvDecorationComponent:
+        case spv::Decoration::Component:
           PASS_OR_BAIL(CheckComponentDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationFPRoundingMode:
+        case spv::Decoration::FPRoundingMode:
           if (is_shader)
             PASS_OR_BAIL(
                 CheckFPRoundingModeForShaders(vstate, *inst, decoration));
           break;
-        case SpvDecorationNonWritable:
+        case spv::Decoration::NonWritable:
           PASS_OR_BAIL(CheckNonWritableDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationUniform:
-        case SpvDecorationUniformId:
+        case spv::Decoration::Uniform:
+        case spv::Decoration::UniformId:
           PASS_OR_BAIL(CheckUniformDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationNoSignedWrap:
-        case SpvDecorationNoUnsignedWrap:
+        case spv::Decoration::NoSignedWrap:
+        case spv::Decoration::NoUnsignedWrap:
           PASS_OR_BAIL(CheckIntegerWrapDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationBlock:
-        case SpvDecorationBufferBlock:
+        case spv::Decoration::Block:
+        case spv::Decoration::BufferBlock:
           PASS_OR_BAIL(CheckBlockDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationLocation:
+        case spv::Decoration::Location:
           PASS_OR_BAIL(CheckLocationDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationRelaxedPrecision:
+        case spv::Decoration::RelaxedPrecision:
           PASS_OR_BAIL(
               CheckRelaxPrecisionDecoration(vstate, *inst, decoration));
           break;
diff --git a/third_party/SPIRV-Tools/source/val/validate_derivatives.cpp b/third_party/SPIRV-Tools/source/val/validate_derivatives.cpp
index 25b941a..d87240f 100644
--- a/third_party/SPIRV-Tools/source/val/validate_derivatives.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_derivatives.cpp
@@ -28,25 +28,26 @@
 
 // Validates correctness of derivative instructions.
 spv_result_t DerivativesPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpDPdx:
-    case SpvOpDPdy:
-    case SpvOpFwidth:
-    case SpvOpDPdxFine:
-    case SpvOpDPdyFine:
-    case SpvOpFwidthFine:
-    case SpvOpDPdxCoarse:
-    case SpvOpDPdyCoarse:
-    case SpvOpFwidthCoarse: {
+    case spv::Op::OpDPdx:
+    case spv::Op::OpDPdy:
+    case spv::Op::OpFwidth:
+    case spv::Op::OpDPdxFine:
+    case spv::Op::OpDPdyFine:
+    case spv::Op::OpFwidthFine:
+    case spv::Op::OpDPdxCoarse:
+    case spv::Op::OpDPdyCoarse:
+    case spv::Op::OpFwidthCoarse: {
       if (!_.IsFloatScalarOrVectorType(result_type)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to be float scalar or vector type: "
                << spvOpcodeString(opcode);
       }
-      if (!_.ContainsSizedIntOrFloatType(result_type, SpvOpTypeFloat, 32)) {
+      if (!_.ContainsSizedIntOrFloatType(result_type, spv::Op::OpTypeFloat,
+                                         32)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Result type component width must be 32 bits";
       }
@@ -58,10 +59,10 @@
                << spvOpcodeString(opcode);
       }
       _.function(inst->function()->id())
-          ->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
+          ->RegisterExecutionModelLimitation([opcode](spv::ExecutionModel model,
                                                       std::string* message) {
-            if (model != SpvExecutionModelFragment &&
-                model != SpvExecutionModelGLCompute) {
+            if (model != spv::ExecutionModel::Fragment &&
+                model != spv::ExecutionModel::GLCompute) {
               if (message) {
                 *message =
                     std::string(
@@ -80,11 +81,11 @@
             const auto* models = state.GetExecutionModels(entry_point->id());
             const auto* modes = state.GetExecutionModes(entry_point->id());
             if (models &&
-                models->find(SpvExecutionModelGLCompute) != models->end() &&
+                models->find(spv::ExecutionModel::GLCompute) != models->end() &&
                 (!modes ||
-                 (modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
+                 (modes->find(spv::ExecutionMode::DerivativeGroupLinearNV) ==
                       modes->end() &&
-                  modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
+                  modes->find(spv::ExecutionMode::DerivativeGroupQuadsNV) ==
                       modes->end()))) {
               if (message) {
                 *message = std::string(
diff --git a/third_party/SPIRV-Tools/source/val/validate_execution_limitations.cpp b/third_party/SPIRV-Tools/source/val/validate_execution_limitations.cpp
index aac1c49..00c6603 100644
--- a/third_party/SPIRV-Tools/source/val/validate_execution_limitations.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_execution_limitations.cpp
@@ -22,7 +22,7 @@
 
 spv_result_t ValidateExecutionLimitations(ValidationState_t& _,
                                           const Instruction* inst) {
-  if (inst->opcode() != SpvOpFunction) {
+  if (inst->opcode() != spv::Op::OpFunction) {
     return SPV_SUCCESS;
   }
 
@@ -44,8 +44,8 @@
         std::string reason;
         if (!func->IsCompatibleWithExecutionModel(model, &reason)) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << "OpEntryPoint Entry Point <id> '" << _.getIdName(entry_id)
-                 << "'s callgraph contains function <id> "
+                 << "OpEntryPoint Entry Point <id> " << _.getIdName(entry_id)
+                 << "s callgraph contains function <id> "
                  << _.getIdName(inst->id())
                  << ", which cannot be used with the current execution "
                     "model:\n"
@@ -57,9 +57,8 @@
     std::string reason;
     if (!func->CheckLimitations(_, _.function(entry_id), &reason)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpEntryPoint Entry Point <id> '" << _.getIdName(entry_id)
-             << "'s callgraph contains function <id> "
-             << _.getIdName(inst->id())
+             << "OpEntryPoint Entry Point <id> " << _.getIdName(entry_id)
+             << "s callgraph contains function <id> " << _.getIdName(inst->id())
              << ", which cannot be used with the current execution "
                 "modes:\n"
              << reason;
diff --git a/third_party/SPIRV-Tools/source/val/validate_extensions.cpp b/third_party/SPIRV-Tools/source/val/validate_extensions.cpp
index fcf04e2..98c691b 100644
--- a/third_party/SPIRV-Tools/source/val/validate_extensions.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_extensions.cpp
@@ -40,9 +40,9 @@
 namespace {
 
 uint32_t GetSizeTBitWidth(const ValidationState_t& _) {
-  if (_.addressing_model() == SpvAddressingModelPhysical32) return 32;
+  if (_.addressing_model() == spv::AddressingModel::Physical32) return 32;
 
-  if (_.addressing_model() == SpvAddressingModelPhysical64) return 64;
+  if (_.addressing_model() == spv::AddressingModel::Physical64) return 64;
 
   return 0;
 }
@@ -50,7 +50,7 @@
 bool IsIntScalar(ValidationState_t& _, uint32_t id, bool must_len32,
                  bool must_unsigned) {
   auto type = _.FindDef(id);
-  if (!type || type->opcode() != SpvOpTypeInt) {
+  if (!type || type->opcode() != spv::Op::OpTypeInt) {
     return false;
   }
 
@@ -63,7 +63,7 @@
 
 bool IsUint32Constant(ValidationState_t& _, uint32_t id) {
   auto inst = _.FindDef(id);
-  if (!inst || inst->opcode() != SpvOpConstant) {
+  if (!inst || inst->opcode() != spv::Op::OpConstant) {
     return false;
   }
 
@@ -79,7 +79,7 @@
 // is a result id of an instruction with |expected_opcode|.
 spv_result_t ValidateOperandForDebugInfo(
     ValidationState_t& _, const std::string& operand_name,
-    SpvOp expected_opcode, const Instruction* inst, uint32_t word_index,
+    spv::Op expected_opcode, const Instruction* inst, uint32_t word_index,
     const std::function<std::string()>& ext_inst_name) {
   auto* operand = _.FindDef(inst->word(word_index));
   if (operand->opcode() != expected_opcode) {
@@ -137,7 +137,7 @@
     const Instruction* inst, uint32_t word_index) {
   if (inst->words().size() <= word_index) return false;
   auto* debug_inst = _.FindDef(inst->word(word_index));
-  if (debug_inst->opcode() != SpvOpExtInst ||
+  if (debug_inst->opcode() != spv::Op::OpExtInst ||
       (debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 &&
        debug_inst->ext_inst_type() !=
            SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
@@ -155,7 +155,7 @@
     const Instruction* inst, uint32_t word_index) {
   if (inst->words().size() <= word_index) return false;
   auto* debug_inst = _.FindDef(inst->word(word_index));
-  if (debug_inst->opcode() != SpvOpExtInst ||
+  if (debug_inst->opcode() != spv::Op::OpExtInst ||
       (debug_inst->ext_inst_type() !=
        SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
       !expectation(
@@ -276,7 +276,7 @@
                                            const Instruction* inst) {
   const auto kernel_id = inst->GetOperandAs<uint32_t>(4);
   const auto kernel = _.FindDef(kernel_id);
-  if (kernel->opcode() != SpvOpFunction) {
+  if (kernel->opcode() != spv::Op::OpFunction) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Kernel does not reference a function";
   }
@@ -299,14 +299,14 @@
            << "Kernel does not reference an entry-point";
   }
   for (auto exec_model : *exec_models) {
-    if (exec_model != SpvExecutionModelGLCompute) {
+    if (exec_model != spv::ExecutionModel::GLCompute) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Kernel must refer only to GLCompute entry-points";
     }
   }
 
   auto name = _.FindDef(inst->GetOperandAs<uint32_t>(5));
-  if (!name || name->opcode() != SpvOpString) {
+  if (!name || name->opcode() != spv::Op::OpString) {
     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Name must be an OpString";
   }
 
@@ -329,11 +329,11 @@
 spv_result_t ValidateClspvReflectionArgumentInfo(ValidationState_t& _,
                                                  const Instruction* inst) {
   const auto num_operands = inst->operands().size();
-  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(4)) != SpvOpString) {
+  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(4)) != spv::Op::OpString) {
     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Name must be an OpString";
   }
   if (num_operands > 5) {
-    if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(5)) != SpvOpString) {
+    if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(5)) != spv::Op::OpString) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "TypeName must be an OpString";
     }
@@ -366,7 +366,7 @@
 spv_result_t ValidateKernelDecl(ValidationState_t& _, const Instruction* inst) {
   const auto decl_id = inst->GetOperandAs<uint32_t>(4);
   const auto decl = _.FindDef(decl_id);
-  if (!decl || decl->opcode() != SpvOpExtInst) {
+  if (!decl || decl->opcode() != spv::Op::OpExtInst) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Kernel must be a Kernel extended instruction";
   }
@@ -389,7 +389,7 @@
 spv_result_t ValidateArgInfo(ValidationState_t& _, const Instruction* inst,
                              uint32_t info_index) {
   auto info = _.FindDef(inst->GetOperandAs<uint32_t>(info_index));
-  if (!info || info->opcode() != SpvOpExtInst) {
+  if (!info || info->opcode() != spv::Op::OpExtInst) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "ArgInfo must be an ArgumentInfo extended instruction";
   }
@@ -599,7 +599,7 @@
            << "Binding must be a 32-bit unsigned integer OpConstant";
   }
 
-  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != SpvOpString) {
+  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != spv::Op::OpString) {
     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Data must be an OpString";
   }
 
@@ -705,7 +705,7 @@
 
 bool IsConstIntScalarTypeWith32Or64Bits(ValidationState_t& _,
                                         Instruction* instr) {
-  if (instr->opcode() != SpvOpConstant) return false;
+  if (instr->opcode() != spv::Op::OpConstant) return false;
   if (!_.IsIntScalarType(instr->type_id())) return false;
   uint32_t size_in_bits = _.GetBitWidth(instr->type_id());
   return size_in_bits == 32 || size_in_bits == 64;
@@ -714,7 +714,7 @@
 bool IsConstWithIntScalarType(ValidationState_t& _, const Instruction* inst,
                               uint32_t word_index) {
   auto* int_scalar_const = _.FindDef(inst->word(word_index));
-  if (int_scalar_const->opcode() == SpvOpConstant &&
+  if (int_scalar_const->opcode() == spv::Op::OpConstant &&
       _.IsIntScalarType(int_scalar_const->type_id())) {
     return true;
   }
@@ -756,10 +756,10 @@
   if (_.version() < SPV_SPIRV_VERSION_WORD(1, 4)) {
     std::string extension = GetExtensionString(&(inst->c_inst()));
     if (extension ==
-        ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout)) {
+            ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout) ||
+        extension == ExtensionToString(kSPV_EXT_mesh_shader)) {
       return _.diag(SPV_ERROR_WRONG_VERSION, inst)
-             << "SPV_KHR_workgroup_memory_explicit_layout extension "
-                "requires SPIR-V version 1.4 or later.";
+             << extension << " extension requires SPIR-V version 1.4 or later.";
     }
   }
 
@@ -1020,7 +1020,7 @@
                  << "expected operand X type to be equal to Result Type";
         }
 
-        uint32_t i_storage_class = 0;
+        spv::StorageClass i_storage_class;
         uint32_t i_data_type = 0;
         if (!_.GetPointerTypeInfo(i_type, &i_data_type, &i_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1075,7 +1075,7 @@
                  << "expected operand X type to be equal to Result Type";
         }
 
-        uint32_t exp_storage_class = 0;
+        spv::StorageClass exp_storage_class;
         uint32_t exp_data_type = 0;
         if (!_.GetPointerTypeInfo(exp_type, &exp_data_type,
                                   &exp_storage_class)) {
@@ -1424,7 +1424,7 @@
       case GLSLstd450InterpolateAtCentroid:
       case GLSLstd450InterpolateAtSample:
       case GLSLstd450InterpolateAtOffset: {
-        if (!_.HasCapability(SpvCapabilityInterpolationFunction)) {
+        if (!_.HasCapability(spv::Capability::InterpolationFunction)) {
           return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst)
                  << ext_inst_name()
                  << " requires capability InterpolationFunction";
@@ -1444,11 +1444,11 @@
         uint32_t interp_id = inst->GetOperandAs<uint32_t>(4);
         auto* interp_inst = _.FindDef(interp_id);
         uint32_t interpolant_type = (_.options()->before_hlsl_legalization &&
-                                     interp_inst->opcode() == SpvOpLoad)
+                                     interp_inst->opcode() == spv::Op::OpLoad)
                                         ? _.GetOperandTypeId(interp_inst, 2)
                                         : _.GetOperandTypeId(inst, 4);
 
-        uint32_t interpolant_storage_class = 0;
+        spv::StorageClass interpolant_storage_class;
         uint32_t interpolant_data_type = 0;
         if (!_.GetPointerTypeInfo(interpolant_type, &interpolant_data_type,
                                   &interpolant_storage_class)) {
@@ -1463,7 +1463,7 @@
                  << "expected Interpolant data type to be equal to Result Type";
         }
 
-        if (interpolant_storage_class != SpvStorageClassInput) {
+        if (interpolant_storage_class != spv::StorageClass::Input) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected Interpolant storage class to be Input";
@@ -1492,7 +1492,7 @@
 
         _.function(inst->function()->id())
             ->RegisterExecutionModelLimitation(
-                SpvExecutionModelFragment,
+                spv::ExecutionModel::Fragment,
                 ext_inst_name() +
                     std::string(" requires Fragment execution model"));
         break;
@@ -1662,7 +1662,7 @@
         }
 
         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1670,10 +1670,10 @@
                  << "expected the last operand to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected storage class of the pointer to be Generic, "
@@ -1724,7 +1724,7 @@
         }
 
         const uint32_t p_type = _.GetOperandTypeId(inst, operand_index++);
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1732,10 +1732,10 @@
                  << "expected the last operand to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected storage class of the pointer to be Generic, "
@@ -2254,7 +2254,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2262,11 +2262,11 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassUniformConstant &&
-            p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::UniformConstant &&
+            p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be UniformConstant, "
@@ -2291,7 +2291,7 @@
       }
 
       case OpenCLLIB::Vstoren: {
-        if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
+        if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": expected Result Type to be void";
         }
@@ -2329,7 +2329,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2337,10 +2337,10 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be Generic, "
@@ -2382,7 +2382,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2390,11 +2390,11 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassUniformConstant &&
-            p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::UniformConstant &&
+            p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be UniformConstant, "
@@ -2444,7 +2444,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2452,11 +2452,11 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassUniformConstant &&
-            p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::UniformConstant &&
+            p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be UniformConstant, "
@@ -2486,7 +2486,7 @@
       case OpenCLLIB::Vstore_halfn_r:
       case OpenCLLIB::Vstorea_halfn:
       case OpenCLLIB::Vstorea_halfn_r: {
-        if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
+        if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": expected Result Type to be void";
         }
@@ -2537,7 +2537,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2545,10 +2545,10 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be Generic, "
@@ -2653,7 +2653,7 @@
         }
 
         const uint32_t format_type = _.GetOperandTypeId(inst, 4);
-        uint32_t format_storage_class = 0;
+        spv::StorageClass format_storage_class;
         uint32_t format_data_type = 0;
         if (!_.GetPointerTypeInfo(format_type, &format_data_type,
                                   &format_storage_class)) {
@@ -2662,7 +2662,7 @@
                  << "expected operand Format to be a pointer";
         }
 
-        if (format_storage_class != SpvStorageClassUniformConstant) {
+        if (format_storage_class != spv::StorageClass::UniformConstant) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected Format storage class to be UniformConstant";
@@ -2678,7 +2678,7 @@
       }
 
       case OpenCLLIB::Prefetch: {
-        if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
+        if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": expected Result Type to be void";
         }
@@ -2686,7 +2686,7 @@
         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
         const uint32_t num_elements_type = _.GetOperandTypeId(inst, 5);
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2694,7 +2694,7 @@
                  << "expected operand Ptr to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassCrossWorkgroup) {
+        if (p_storage_class != spv::StorageClass::CrossWorkgroup) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand Ptr storage class to be CrossWorkgroup";
@@ -2857,13 +2857,13 @@
           break;
         }
         case CommonDebugInfoDebugSource: {
-          CHECK_OPERAND("File", SpvOpString, 5);
-          if (num_words == 7) CHECK_OPERAND("Text", SpvOpString, 6);
+          CHECK_OPERAND("File", spv::Op::OpString, 5);
+          if (num_words == 7) CHECK_OPERAND("Text", spv::Op::OpString, 6);
           break;
         }
         case CommonDebugInfoDebugTypeBasic: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
-          CHECK_OPERAND("Size", SpvOpConstant, 6);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
+          CHECK_OPERAND("Size", spv::Op::OpConstant, 6);
           CHECK_CONST_UINT_OPERAND("Encoding", 7);
           break;
         }
@@ -2966,7 +2966,7 @@
           break;
         }
         case CommonDebugInfoDebugTypedef: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_base_type =
               ValidateOperandBaseType(_, inst, 6, ext_inst_name);
           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
@@ -2983,7 +2983,7 @@
           auto* return_type = _.FindDef(inst->word(6));
           // TODO: We need a spec discussion that we have to allow return and
           // parameter types of a DebugTypeFunction to have template parameter.
-          if (return_type->opcode() != SpvOpTypeVoid) {
+          if (return_type->opcode() != spv::Op::OpTypeVoid) {
             auto validate_return = ValidateOperandDebugType(
                 _, "Return Type", inst, 6, ext_inst_name, true);
             if (validate_return != SPV_SUCCESS) return validate_return;
@@ -2996,7 +2996,7 @@
           break;
         }
         case CommonDebugInfoDebugTypeEnum: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           if (!DoesDebugInfoOperandMatchExpectation(
                   _,
                   [](CommonDebugInfoInstructions dbg_inst) {
@@ -3014,7 +3014,7 @@
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          CHECK_OPERAND("Size", SpvOpConstant, 11);
+          CHECK_OPERAND("Size", spv::Op::OpConstant, 11);
           auto* size = _.FindDef(inst->word(11));
           if (!_.IsIntScalarType(size->type_id()) || !size->word(3)) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -3024,27 +3024,27 @@
           CHECK_CONST_UINT_OPERAND("Flags", 12);
           for (uint32_t word_index = 13; word_index + 1 < num_words;
                word_index += 2) {
-            CHECK_OPERAND("Value", SpvOpConstant, word_index);
-            CHECK_OPERAND("Name", SpvOpString, word_index + 1);
+            CHECK_OPERAND("Value", spv::Op::OpConstant, word_index);
+            CHECK_OPERAND("Name", spv::Op::OpString, word_index + 1);
           }
           break;
         }
         case CommonDebugInfoDebugTypeComposite: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
           CHECK_CONST_UINT_OPERAND("Line", 8);
           CHECK_CONST_UINT_OPERAND("Column", 9);
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          CHECK_OPERAND("Linkage Name", SpvOpString, 11);
+          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
           if (!DoesDebugInfoOperandMatchExpectation(
                   _,
                   [](CommonDebugInfoInstructions dbg_inst) {
                     return dbg_inst == CommonDebugInfoDebugInfoNone;
                   },
                   inst, 12)) {
-            CHECK_OPERAND("Size", SpvOpConstant, 12);
+            CHECK_OPERAND("Size", spv::Op::OpConstant, 12);
           }
           CHECK_CONST_UINT_OPERAND("Flags", 13);
           for (uint32_t word_index = 14; word_index < num_words; ++word_index) {
@@ -3066,7 +3066,7 @@
           break;
         }
         case CommonDebugInfoDebugTypeMember: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           // TODO: We need a spec discussion that we have to allow member types
           // to have template parameter.
           auto validate_type =
@@ -3077,17 +3077,19 @@
           CHECK_CONST_UINT_OPERAND("Column", 9);
           // NonSemantic.Shader.DebugInfo doesn't have the Parent operand
           if (vulkanDebugInfo) {
-            CHECK_OPERAND("Offset", SpvOpConstant, 10);
-            CHECK_OPERAND("Size", SpvOpConstant, 11);
+            CHECK_OPERAND("Offset", spv::Op::OpConstant, 10);
+            CHECK_OPERAND("Size", spv::Op::OpConstant, 11);
             CHECK_CONST_UINT_OPERAND("Flags", 12);
-            if (num_words == 14) CHECK_OPERAND("Value", SpvOpConstant, 13);
+            if (num_words == 14)
+              CHECK_OPERAND("Value", spv::Op::OpConstant, 13);
           } else {
             CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite,
                                 10);
-            CHECK_OPERAND("Offset", SpvOpConstant, 11);
-            CHECK_OPERAND("Size", SpvOpConstant, 12);
+            CHECK_OPERAND("Offset", spv::Op::OpConstant, 11);
+            CHECK_OPERAND("Size", spv::Op::OpConstant, 12);
             CHECK_CONST_UINT_OPERAND("Flags", 13);
-            if (num_words == 15) CHECK_OPERAND("Value", SpvOpConstant, 14);
+            if (num_words == 15)
+              CHECK_OPERAND("Value", spv::Op::OpConstant, 14);
           }
           break;
         }
@@ -3114,13 +3116,13 @@
                    << "expected operand Parent must be class or struct debug "
                       "type";
           }
-          CHECK_OPERAND("Offset", SpvOpConstant, 7);
-          CHECK_OPERAND("Size", SpvOpConstant, 8);
+          CHECK_OPERAND("Offset", spv::Op::OpConstant, 7);
+          CHECK_OPERAND("Size", spv::Op::OpConstant, 8);
           CHECK_CONST_UINT_OPERAND("Flags", 9);
           break;
         }
         case CommonDebugInfoDebugFunction: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
                                                         ext_inst_name, false);
           if (validate_type != SPV_SUCCESS) return validate_type;
@@ -3130,7 +3132,7 @@
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          CHECK_OPERAND("Linkage Name", SpvOpString, 11);
+          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
           CHECK_CONST_UINT_OPERAND("Flags", 12);
           CHECK_CONST_UINT_OPERAND("Scope Line", 13);
           // NonSemantic.Shader.DebugInfo.100 doesn't include a reference to the
@@ -3147,7 +3149,7 @@
                       return dbg_inst == CommonDebugInfoDebugInfoNone;
                     },
                     inst, 14)) {
-              CHECK_OPERAND("Function", SpvOpFunction, 14);
+              CHECK_OPERAND("Function", spv::Op::OpFunction, 14);
             }
             if (num_words == 16) {
               CHECK_DEBUG_OPERAND("Declaration",
@@ -3157,7 +3159,7 @@
           break;
         }
         case CommonDebugInfoDebugFunctionDeclaration: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
                                                         ext_inst_name, false);
           if (validate_type != SPV_SUCCESS) return validate_type;
@@ -3167,7 +3169,7 @@
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          CHECK_OPERAND("Linkage Name", SpvOpString, 11);
+          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
           CHECK_CONST_UINT_OPERAND("Flags", 12);
           break;
         }
@@ -3178,7 +3180,7 @@
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 8, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          if (num_words == 10) CHECK_OPERAND("Name", SpvOpString, 9);
+          if (num_words == 10) CHECK_OPERAND("Name", spv::Op::OpString, 9);
           break;
         }
         case CommonDebugInfoDebugScope: {
@@ -3191,7 +3193,7 @@
           break;
         }
         case CommonDebugInfoDebugLocalVariable: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           // TODO: We need a spec discussion that we have to allow local
           // variable types to have template parameter.
           auto validate_type =
@@ -3213,8 +3215,8 @@
           CHECK_DEBUG_OPERAND("Local Variable",
                               CommonDebugInfoDebugLocalVariable, 5);
           auto* operand = _.FindDef(inst->word(6));
-          if (operand->opcode() != SpvOpVariable &&
-              operand->opcode() != SpvOpFunctionParameter) {
+          if (operand->opcode() != spv::Op::OpVariable &&
+              operand->opcode() != spv::Op::OpFunctionParameter) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << ext_inst_name() << ": "
                    << "expected operand Variable must be a result id of "
@@ -3276,7 +3278,7 @@
           break;
         }
         case CommonDebugInfoDebugTypeTemplateParameter: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_actual_type = ValidateOperandDebugType(
               _, "Actual Type", inst, 6, ext_inst_name, false);
           if (validate_actual_type != SPV_SUCCESS) return validate_actual_type;
@@ -3286,7 +3288,7 @@
                     return dbg_inst == CommonDebugInfoDebugInfoNone;
                   },
                   inst, 7)) {
-            CHECK_OPERAND("Value", SpvOpConstant, 7);
+            CHECK_OPERAND("Value", spv::Op::OpConstant, 7);
           }
           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 8);
           CHECK_CONST_UINT_OPERAND("Line", 9);
@@ -3294,7 +3296,7 @@
           break;
         }
         case CommonDebugInfoDebugGlobalVariable: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
                                                         ext_inst_name, false);
           if (validate_type != SPV_SUCCESS) return validate_type;
@@ -3304,7 +3306,7 @@
           auto validate_scope =
               ValidateOperandLexicalScope(_, "Scope", inst, 10, ext_inst_name);
           if (validate_scope != SPV_SUCCESS) return validate_scope;
-          CHECK_OPERAND("Linkage Name", SpvOpString, 11);
+          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
           if (!DoesDebugInfoOperandMatchExpectation(
                   _,
                   [](CommonDebugInfoInstructions dbg_inst) {
@@ -3312,8 +3314,8 @@
                   },
                   inst, 12)) {
             auto* operand = _.FindDef(inst->word(12));
-            if (operand->opcode() != SpvOpVariable &&
-                operand->opcode() != SpvOpConstant) {
+            if (operand->opcode() != spv::Op::OpVariable &&
+                operand->opcode() != spv::Op::OpConstant) {
               return _.diag(SPV_ERROR_INVALID_DATA, inst)
                      << ext_inst_name() << ": "
                      << "expected operand Variable must be a result id of "
@@ -3401,10 +3403,10 @@
 }
 
 spv_result_t ExtensionPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
-  if (opcode == SpvOpExtension) return ValidateExtension(_, inst);
-  if (opcode == SpvOpExtInstImport) return ValidateExtInstImport(_, inst);
-  if (opcode == SpvOpExtInst) return ValidateExtInst(_, inst);
+  const spv::Op opcode = inst->opcode();
+  if (opcode == spv::Op::OpExtension) return ValidateExtension(_, inst);
+  if (opcode == spv::Op::OpExtInstImport) return ValidateExtInstImport(_, inst);
+  if (opcode == spv::Op::OpExtInst) return ValidateExtInst(_, inst);
 
   return SPV_SUCCESS;
 }
diff --git a/third_party/SPIRV-Tools/source/val/validate_function.cpp b/third_party/SPIRV-Tools/source/val/validate_function.cpp
index 2a5fed8..db402aa 100644
--- a/third_party/SPIRV-Tools/source/val/validate_function.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_function.cpp
@@ -28,7 +28,8 @@
 // of the decorations that apply to |a|.
 bool DoPointeesLogicallyMatch(val::Instruction* a, val::Instruction* b,
                               ValidationState_t& _) {
-  if (a->opcode() != SpvOpTypePointer || b->opcode() != SpvOpTypePointer) {
+  if (a->opcode() != spv::Op::OpTypePointer ||
+      b->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
@@ -56,35 +57,35 @@
 spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) {
   const auto function_type_id = inst->GetOperandAs<uint32_t>(3);
   const auto function_type = _.FindDef(function_type_id);
-  if (!function_type || SpvOpTypeFunction != function_type->opcode()) {
+  if (!function_type || spv::Op::OpTypeFunction != function_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpFunction Function Type <id> '" << _.getIdName(function_type_id)
-           << "' is not a function type.";
+           << "OpFunction Function Type <id> " << _.getIdName(function_type_id)
+           << " is not a function type.";
   }
 
   const auto return_id = function_type->GetOperandAs<uint32_t>(1);
   if (return_id != inst->type_id()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpFunction Result Type <id> '" << _.getIdName(inst->type_id())
-           << "' does not match the Function Type's return type <id> '"
-           << _.getIdName(return_id) << "'.";
+           << "OpFunction Result Type <id> " << _.getIdName(inst->type_id())
+           << " does not match the Function Type's return type <id> "
+           << _.getIdName(return_id) << ".";
   }
 
-  const std::vector<SpvOp> acceptable = {
-      SpvOpGroupDecorate,
-      SpvOpDecorate,
-      SpvOpEnqueueKernel,
-      SpvOpEntryPoint,
-      SpvOpExecutionMode,
-      SpvOpExecutionModeId,
-      SpvOpFunctionCall,
-      SpvOpGetKernelNDrangeSubGroupCount,
-      SpvOpGetKernelNDrangeMaxSubGroupSize,
-      SpvOpGetKernelWorkGroupSize,
-      SpvOpGetKernelPreferredWorkGroupSizeMultiple,
-      SpvOpGetKernelLocalSizeForSubgroupCount,
-      SpvOpGetKernelMaxNumSubgroups,
-      SpvOpName};
+  const std::vector<spv::Op> acceptable = {
+      spv::Op::OpGroupDecorate,
+      spv::Op::OpDecorate,
+      spv::Op::OpEnqueueKernel,
+      spv::Op::OpEntryPoint,
+      spv::Op::OpExecutionMode,
+      spv::Op::OpExecutionModeId,
+      spv::Op::OpFunctionCall,
+      spv::Op::OpGetKernelNDrangeSubGroupCount,
+      spv::Op::OpGetKernelNDrangeMaxSubGroupSize,
+      spv::Op::OpGetKernelWorkGroupSize,
+      spv::Op::OpGetKernelPreferredWorkGroupSizeMultiple,
+      spv::Op::OpGetKernelLocalSizeForSubgroupCount,
+      spv::Op::OpGetKernelMaxNumSubgroups,
+      spv::Op::OpName};
   for (auto& pair : inst->uses()) {
     const auto* use = pair.first;
     if (std::find(acceptable.begin(), acceptable.end(), use->opcode()) ==
@@ -112,14 +113,14 @@
   auto func_inst = &_.ordered_instructions()[inst_num];
   while (--inst_num) {
     func_inst = &_.ordered_instructions()[inst_num];
-    if (func_inst->opcode() == SpvOpFunction) {
+    if (func_inst->opcode() == spv::Op::OpFunction) {
       break;
-    } else if (func_inst->opcode() == SpvOpFunctionParameter) {
+    } else if (func_inst->opcode() == spv::Op::OpFunctionParameter) {
       ++param_index;
     }
   }
 
-  if (func_inst->opcode() != SpvOpFunction) {
+  if (func_inst->opcode() != spv::Op::OpFunction) {
     return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
            << "Function parameter must be preceded by a function.";
   }
@@ -141,34 +142,34 @@
       _.FindDef(function_type->GetOperandAs<uint32_t>(param_index + 2));
   if (!param_type || inst->type_id() != param_type->id()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpFunctionParameter Result Type <id> '"
+           << "OpFunctionParameter Result Type <id> "
            << _.getIdName(inst->type_id())
-           << "' does not match the OpTypeFunction parameter "
+           << " does not match the OpTypeFunction parameter "
               "type of the same index.";
   }
 
   // Validate that PhysicalStorageBuffer have one of Restrict, Aliased,
   // RestrictPointer, or AliasedPointer.
   auto param_nonarray_type_id = param_type->id();
-  while (_.GetIdOpcode(param_nonarray_type_id) == SpvOpTypeArray) {
+  while (_.GetIdOpcode(param_nonarray_type_id) == spv::Op::OpTypeArray) {
     param_nonarray_type_id =
         _.FindDef(param_nonarray_type_id)->GetOperandAs<uint32_t>(1u);
   }
-  if (_.GetIdOpcode(param_nonarray_type_id) == SpvOpTypePointer) {
+  if (_.GetIdOpcode(param_nonarray_type_id) == spv::Op::OpTypePointer) {
     auto param_nonarray_type = _.FindDef(param_nonarray_type_id);
-    if (param_nonarray_type->GetOperandAs<uint32_t>(1u) ==
-        SpvStorageClassPhysicalStorageBuffer) {
+    if (param_nonarray_type->GetOperandAs<spv::StorageClass>(1u) ==
+        spv::StorageClass::PhysicalStorageBuffer) {
       // check for Aliased or Restrict
       const auto& decorations = _.id_decorations(inst->id());
 
       bool foundAliased = std::any_of(
           decorations.begin(), decorations.end(), [](const Decoration& d) {
-            return SpvDecorationAliased == d.dec_type();
+            return spv::Decoration::Aliased == d.dec_type();
           });
 
       bool foundRestrict = std::any_of(
           decorations.begin(), decorations.end(), [](const Decoration& d) {
-            return SpvDecorationRestrict == d.dec_type();
+            return spv::Decoration::Restrict == d.dec_type();
           });
 
       if (!foundAliased && !foundRestrict) {
@@ -187,20 +188,20 @@
       const auto pointee_type_id =
           param_nonarray_type->GetOperandAs<uint32_t>(2);
       const auto pointee_type = _.FindDef(pointee_type_id);
-      if (SpvOpTypePointer == pointee_type->opcode() &&
-          pointee_type->GetOperandAs<uint32_t>(1u) ==
-              SpvStorageClassPhysicalStorageBuffer) {
+      if (spv::Op::OpTypePointer == pointee_type->opcode() &&
+          pointee_type->GetOperandAs<spv::StorageClass>(1u) ==
+              spv::StorageClass::PhysicalStorageBuffer) {
         // check for AliasedPointer/RestrictPointer
         const auto& decorations = _.id_decorations(inst->id());
 
         bool foundAliased = std::any_of(
             decorations.begin(), decorations.end(), [](const Decoration& d) {
-              return SpvDecorationAliasedPointer == d.dec_type();
+              return spv::Decoration::AliasedPointer == d.dec_type();
             });
 
         bool foundRestrict = std::any_of(
             decorations.begin(), decorations.end(), [](const Decoration& d) {
-              return SpvDecorationRestrictPointer == d.dec_type();
+              return spv::Decoration::RestrictPointer == d.dec_type();
             });
 
         if (!foundAliased && !foundRestrict) {
@@ -226,24 +227,23 @@
                                   const Instruction* inst) {
   const auto function_id = inst->GetOperandAs<uint32_t>(2);
   const auto function = _.FindDef(function_id);
-  if (!function || SpvOpFunction != function->opcode()) {
+  if (!function || spv::Op::OpFunction != function->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpFunctionCall Function <id> '" << _.getIdName(function_id)
-           << "' is not a function.";
+           << "OpFunctionCall Function <id> " << _.getIdName(function_id)
+           << " is not a function.";
   }
 
   auto return_type = _.FindDef(function->type_id());
   if (!return_type || return_type->id() != inst->type_id()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpFunctionCall Result Type <id> '"
-           << _.getIdName(inst->type_id())
-           << "'s type does not match Function <id> '"
-           << _.getIdName(return_type->id()) << "'s return type.";
+           << "OpFunctionCall Result Type <id> " << _.getIdName(inst->type_id())
+           << "s type does not match Function <id> "
+           << _.getIdName(return_type->id()) << "s return type.";
   }
 
   const auto function_type_id = function->GetOperandAs<uint32_t>(3);
   const auto function_type = _.FindDef(function_type_id);
-  if (!function_type || function_type->opcode() != SpvOpTypeFunction) {
+  if (!function_type || function_type->opcode() != spv::Op::OpTypeFunction) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Missing function type definition.";
   }
@@ -280,26 +280,27 @@
       if (!_.options()->before_hlsl_legalization ||
           !DoPointeesLogicallyMatch(argument_type, parameter_type, _)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << "OpFunctionCall Argument <id> '" << _.getIdName(argument_id)
-               << "'s type does not match Function <id> '"
-               << _.getIdName(parameter_type_id) << "'s parameter type.";
+               << "OpFunctionCall Argument <id> " << _.getIdName(argument_id)
+               << "s type does not match Function <id> "
+               << _.getIdName(parameter_type_id) << "s parameter type.";
       }
     }
 
-    if (_.addressing_model() == SpvAddressingModelLogical) {
-      if (parameter_type->opcode() == SpvOpTypePointer &&
+    if (_.addressing_model() == spv::AddressingModel::Logical) {
+      if (parameter_type->opcode() == spv::Op::OpTypePointer &&
           !_.options()->relax_logical_pointer) {
-        SpvStorageClass sc = parameter_type->GetOperandAs<SpvStorageClass>(1u);
+        spv::StorageClass sc =
+            parameter_type->GetOperandAs<spv::StorageClass>(1u);
         // Validate which storage classes can be pointer operands.
         switch (sc) {
-          case SpvStorageClassUniformConstant:
-          case SpvStorageClassFunction:
-          case SpvStorageClassPrivate:
-          case SpvStorageClassWorkgroup:
-          case SpvStorageClassAtomicCounter:
+          case spv::StorageClass::UniformConstant:
+          case spv::StorageClass::Function:
+          case spv::StorageClass::Private:
+          case spv::StorageClass::Workgroup:
+          case spv::StorageClass::AtomicCounter:
             // These are always allowed.
             break;
-          case SpvStorageClassStorageBuffer:
+          case spv::StorageClass::StorageBuffer:
             if (!_.features().variable_pointers) {
               return _.diag(SPV_ERROR_INVALID_ID, inst)
                      << "StorageBuffer pointer operand "
@@ -314,13 +315,14 @@
         }
 
         // Validate memory object declaration requirements.
-        if (argument->opcode() != SpvOpVariable &&
-            argument->opcode() != SpvOpFunctionParameter) {
+        if (argument->opcode() != spv::Op::OpVariable &&
+            argument->opcode() != spv::Op::OpFunctionParameter) {
           const bool ssbo_vptr = _.features().variable_pointers &&
-                                 sc == SpvStorageClassStorageBuffer;
-          const bool wg_vptr = _.HasCapability(SpvCapabilityVariablePointers) &&
-                               sc == SpvStorageClassWorkgroup;
-          const bool uc_ptr = sc == SpvStorageClassUniformConstant;
+                                 sc == spv::StorageClass::StorageBuffer;
+          const bool wg_vptr =
+              _.HasCapability(spv::Capability::VariablePointers) &&
+              sc == spv::StorageClass::Workgroup;
+          const bool uc_ptr = sc == spv::StorageClass::UniformConstant;
           if (!ssbo_vptr && !wg_vptr && !uc_ptr) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << "Pointer operand " << _.getIdName(argument_id)
@@ -337,13 +339,13 @@
 
 spv_result_t FunctionPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpFunction:
+    case spv::Op::OpFunction:
       if (auto error = ValidateFunction(_, inst)) return error;
       break;
-    case SpvOpFunctionParameter:
+    case spv::Op::OpFunctionParameter:
       if (auto error = ValidateFunctionParameter(_, inst)) return error;
       break;
-    case SpvOpFunctionCall:
+    case spv::Op::OpFunctionCall:
       if (auto error = ValidateFunctionCall(_, inst)) return error;
       break;
     default:
diff --git a/third_party/SPIRV-Tools/source/val/validate_id.cpp b/third_party/SPIRV-Tools/source/val/validate_id.cpp
index 2bab203..89a5ddd 100644
--- a/third_party/SPIRV-Tools/source/val/validate_id.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_id.cpp
@@ -71,7 +71,7 @@
           const Instruction* use = use_index_pair.first;
           if (const BasicBlock* use_block = use->block()) {
             if (use_block->reachable() == false) continue;
-            if (use->opcode() == SpvOpPhi) {
+            if (use->opcode() == spv::Op::OpPhi) {
               if (phi_ids.insert(use->id()).second) {
                 phi_instructions.push_back(use);
               }
@@ -131,7 +131,7 @@
 // instruction operand's ID can be forward referenced.
 spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
   auto can_have_forward_declared_ids =
-      inst->opcode() == SpvOpExtInst &&
+      inst->opcode() == spv::Op::OpExtInst &&
               spvExtInstIsDebugInfo(inst->ext_inst_type())
           ? spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
                 inst->ext_inst_type(), inst->word(4))
@@ -172,23 +172,27 @@
           if (spvOpcodeGeneratesType(def->opcode()) &&
               !spvOpcodeGeneratesType(opcode) && !spvOpcodeIsDebug(opcode) &&
               !inst->IsDebugInfo() && !inst->IsNonSemantic() &&
-              !spvOpcodeIsDecoration(opcode) && opcode != SpvOpFunction &&
-              opcode != SpvOpCooperativeMatrixLengthNV &&
-              !(opcode == SpvOpSpecConstantOp &&
-                inst->word(3) == SpvOpCooperativeMatrixLengthNV)) {
+              !spvOpcodeIsDecoration(opcode) && opcode != spv::Op::OpFunction &&
+              opcode != spv::Op::OpCooperativeMatrixLengthNV &&
+              !(opcode == spv::Op::OpSpecConstantOp &&
+                spv::Op(inst->word(3)) ==
+                    spv::Op::OpCooperativeMatrixLengthNV)) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << "Operand " << _.getIdName(operand_word)
                    << " cannot be a type";
           } else if (def->type_id() == 0 && !spvOpcodeGeneratesType(opcode) &&
                      !spvOpcodeIsDebug(opcode) && !inst->IsDebugInfo() &&
                      !inst->IsNonSemantic() && !spvOpcodeIsDecoration(opcode) &&
-                     !spvOpcodeIsBranch(opcode) && opcode != SpvOpPhi &&
-                     opcode != SpvOpExtInst && opcode != SpvOpExtInstImport &&
-                     opcode != SpvOpSelectionMerge &&
-                     opcode != SpvOpLoopMerge && opcode != SpvOpFunction &&
-                     opcode != SpvOpCooperativeMatrixLengthNV &&
-                     !(opcode == SpvOpSpecConstantOp &&
-                       inst->word(3) == SpvOpCooperativeMatrixLengthNV)) {
+                     !spvOpcodeIsBranch(opcode) && opcode != spv::Op::OpPhi &&
+                     opcode != spv::Op::OpExtInst &&
+                     opcode != spv::Op::OpExtInstImport &&
+                     opcode != spv::Op::OpSelectionMerge &&
+                     opcode != spv::Op::OpLoopMerge &&
+                     opcode != spv::Op::OpFunction &&
+                     opcode != spv::Op::OpCooperativeMatrixLengthNV &&
+                     !(opcode == spv::Op::OpSpecConstantOp &&
+                       spv::Op(inst->word(3)) ==
+                           spv::Op::OpCooperativeMatrixLengthNV)) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << "Operand " << _.getIdName(operand_word)
                    << " requires a type";
diff --git a/third_party/SPIRV-Tools/source/val/validate_image.cpp b/third_party/SPIRV-Tools/source/val/validate_image.cpp
index 2d5e2c7..8f0e6c4 100644
--- a/third_party/SPIRV-Tools/source/val/validate_image.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_image.cpp
@@ -32,47 +32,47 @@
 namespace val {
 namespace {
 
-// Performs compile time check that all SpvImageOperandsXXX cases are handled in
-// this module. If SpvImageOperandsXXX list changes, this function will fail the
-// build.
-// For all other purposes this is a placeholder function.
+// Performs compile time check that all spv::ImageOperandsMask::XXX cases are
+// handled in this module. If spv::ImageOperandsMask::XXX list changes, this
+// function will fail the build. For all other purposes this is a placeholder
+// function.
 bool CheckAllImageOperandsHandled() {
-  SpvImageOperandsMask enum_val = SpvImageOperandsBiasMask;
+  spv::ImageOperandsMask enum_val = spv::ImageOperandsMask::Bias;
 
   // Some improvised code to prevent the compiler from considering enum_val
   // constant and optimizing the switch away.
   uint32_t stack_var = 0;
   if (reinterpret_cast<uintptr_t>(&stack_var) % 256)
-    enum_val = SpvImageOperandsLodMask;
+    enum_val = spv::ImageOperandsMask::Lod;
 
   switch (enum_val) {
     // Please update the validation rules in this module if you are changing
     // the list of image operands, and add new enum values to this switch.
-    case SpvImageOperandsMaskNone:
+    case spv::ImageOperandsMask::MaskNone:
       return false;
-    case SpvImageOperandsBiasMask:
-    case SpvImageOperandsLodMask:
-    case SpvImageOperandsGradMask:
-    case SpvImageOperandsConstOffsetMask:
-    case SpvImageOperandsOffsetMask:
-    case SpvImageOperandsConstOffsetsMask:
-    case SpvImageOperandsSampleMask:
-    case SpvImageOperandsMinLodMask:
+    case spv::ImageOperandsMask::Bias:
+    case spv::ImageOperandsMask::Lod:
+    case spv::ImageOperandsMask::Grad:
+    case spv::ImageOperandsMask::ConstOffset:
+    case spv::ImageOperandsMask::Offset:
+    case spv::ImageOperandsMask::ConstOffsets:
+    case spv::ImageOperandsMask::Sample:
+    case spv::ImageOperandsMask::MinLod:
 
     // TODO(dneto): Support image operands related to the Vulkan memory model.
     // https://gitlab.khronos.org/spirv/spirv-tools/issues/32
-    case SpvImageOperandsMakeTexelAvailableKHRMask:
-    case SpvImageOperandsMakeTexelVisibleKHRMask:
-    case SpvImageOperandsNonPrivateTexelKHRMask:
-    case SpvImageOperandsVolatileTexelKHRMask:
-    case SpvImageOperandsSignExtendMask:
-    case SpvImageOperandsZeroExtendMask:
+    case spv::ImageOperandsMask::MakeTexelAvailableKHR:
+    case spv::ImageOperandsMask::MakeTexelVisibleKHR:
+    case spv::ImageOperandsMask::NonPrivateTexelKHR:
+    case spv::ImageOperandsMask::VolatileTexelKHR:
+    case spv::ImageOperandsMask::SignExtend:
+    case spv::ImageOperandsMask::ZeroExtend:
     // TODO(jaebaek): Move this line properly after handling image offsets
     //                operand. This line temporarily fixes CI failure that
     //                blocks other PRs.
     // https://github.com/KhronosGroup/SPIRV-Tools/issues/4565
-    case SpvImageOperandsOffsetsMask:
-    case SpvImageOperandsNontemporalMask:
+    case spv::ImageOperandsMask::Offsets:
+    case spv::ImageOperandsMask::Nontemporal:
       return true;
   }
   return false;
@@ -81,13 +81,13 @@
 // Used by GetImageTypeInfo. See OpTypeImage spec for more information.
 struct ImageTypeInfo {
   uint32_t sampled_type = 0;
-  SpvDim dim = SpvDimMax;
+  spv::Dim dim = spv::Dim::Max;
   uint32_t depth = 0;
   uint32_t arrayed = 0;
   uint32_t multisampled = 0;
   uint32_t sampled = 0;
-  SpvImageFormat format = SpvImageFormatMax;
-  SpvAccessQualifier access_qualifier = SpvAccessQualifierMax;
+  spv::ImageFormat format = spv::ImageFormat::Max;
+  spv::AccessQualifier access_qualifier = spv::AccessQualifier::Max;
 };
 
 // Provides information on image type. |id| should be object of either
@@ -100,39 +100,39 @@
   const Instruction* inst = _.FindDef(id);
   assert(inst);
 
-  if (inst->opcode() == SpvOpTypeSampledImage) {
+  if (inst->opcode() == spv::Op::OpTypeSampledImage) {
     inst = _.FindDef(inst->word(2));
     assert(inst);
   }
 
-  if (inst->opcode() != SpvOpTypeImage) return false;
+  if (inst->opcode() != spv::Op::OpTypeImage) return false;
 
   const size_t num_words = inst->words().size();
   if (num_words != 9 && num_words != 10) return false;
 
   info->sampled_type = inst->word(2);
-  info->dim = static_cast<SpvDim>(inst->word(3));
+  info->dim = static_cast<spv::Dim>(inst->word(3));
   info->depth = inst->word(4);
   info->arrayed = inst->word(5);
   info->multisampled = inst->word(6);
   info->sampled = inst->word(7);
-  info->format = static_cast<SpvImageFormat>(inst->word(8));
-  info->access_qualifier = num_words < 10
-                               ? SpvAccessQualifierMax
-                               : static_cast<SpvAccessQualifier>(inst->word(9));
+  info->format = static_cast<spv::ImageFormat>(inst->word(8));
+  info->access_qualifier =
+      num_words < 10 ? spv::AccessQualifier::Max
+                     : static_cast<spv::AccessQualifier>(inst->word(9));
   return true;
 }
 
-bool IsImplicitLod(SpvOp opcode) {
+bool IsImplicitLod(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
       return true;
     default:
       break;
@@ -140,16 +140,16 @@
   return false;
 }
 
-bool IsExplicitLod(SpvOp opcode) {
+bool IsExplicitLod(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
       return true;
     default:
       break;
@@ -157,22 +157,22 @@
   return false;
 }
 
-bool IsValidLodOperand(const ValidationState_t& _, SpvOp opcode) {
+bool IsValidLodOperand(const ValidationState_t& _, spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageRead:
-    case SpvOpImageWrite:
-    case SpvOpImageSparseRead:
-      return _.HasCapability(SpvCapabilityImageReadWriteLodAMD);
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageWrite:
+    case spv::Op::OpImageSparseRead:
+      return _.HasCapability(spv::Capability::ImageReadWriteLodAMD);
     default:
       return IsExplicitLod(opcode);
   }
 }
 
-bool IsValidGatherLodBiasAMD(const ValidationState_t& _, SpvOp opcode) {
+bool IsValidGatherLodBiasAMD(const ValidationState_t& _, spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageGather:
-    case SpvOpImageSparseGather:
-      return _.HasCapability(SpvCapabilityImageGatherBiasLodAMD);
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageSparseGather:
+      return _.HasCapability(spv::Capability::ImageGatherBiasLodAMD);
     default:
       break;
   }
@@ -181,16 +181,16 @@
 
 // Returns true if the opcode is a Image instruction which applies
 // homogenous projection to the coordinates.
-bool IsProj(SpvOp opcode) {
+bool IsProj(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
       return true;
     default:
       break;
@@ -204,21 +204,21 @@
   uint32_t plane_size = 0;
   // If this switch breaks your build, please add new values below.
   switch (info.dim) {
-    case SpvDim1D:
-    case SpvDimBuffer:
+    case spv::Dim::Dim1D:
+    case spv::Dim::Buffer:
       plane_size = 1;
       break;
-    case SpvDim2D:
-    case SpvDimRect:
-    case SpvDimSubpassData:
+    case spv::Dim::Dim2D:
+    case spv::Dim::Rect:
+    case spv::Dim::SubpassData:
       plane_size = 2;
       break;
-    case SpvDim3D:
-    case SpvDimCube:
+    case spv::Dim::Dim3D:
+    case spv::Dim::Cube:
       // For Cube direction vector is used instead of UV.
       plane_size = 3;
       break;
-    case SpvDimMax:
+    case spv::Dim::Max:
       assert(0);
       break;
   }
@@ -228,10 +228,10 @@
 
 // Returns minimal number of coordinates based on image dim, arrayed and whether
 // the instruction uses projection coordinates.
-uint32_t GetMinCoordSize(SpvOp opcode, const ImageTypeInfo& info) {
-  if (info.dim == SpvDimCube &&
-      (opcode == SpvOpImageRead || opcode == SpvOpImageWrite ||
-       opcode == SpvOpImageSparseRead)) {
+uint32_t GetMinCoordSize(spv::Op opcode, const ImageTypeInfo& info) {
+  if (info.dim == spv::Dim::Cube &&
+      (opcode == spv::Op::OpImageRead || opcode == spv::Op::OpImageWrite ||
+       opcode == spv::Op::OpImageSparseRead)) {
     // These opcodes use UV for Cube, not direction vector.
     return 3;
   }
@@ -248,7 +248,7 @@
   static const bool kAllImageOperandsHandled = CheckAllImageOperandsHandled();
   (void)kAllImageOperandsHandled;
 
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const size_t num_words = inst->words().size();
 
   const bool have_explicit_mask = (word_index - 1 < num_words);
@@ -257,14 +257,14 @@
   if (have_explicit_mask) {
     // NonPrivate, Volatile, SignExtend, ZeroExtend take no operand words.
     const uint32_t mask_bits_having_operands =
-        mask & ~uint32_t(SpvImageOperandsNonPrivateTexelKHRMask |
-                         SpvImageOperandsVolatileTexelKHRMask |
-                         SpvImageOperandsSignExtendMask |
-                         SpvImageOperandsZeroExtendMask |
-                         SpvImageOperandsNontemporalMask);
+        mask & ~uint32_t(spv::ImageOperandsMask::NonPrivateTexelKHR |
+                         spv::ImageOperandsMask::VolatileTexelKHR |
+                         spv::ImageOperandsMask::SignExtend |
+                         spv::ImageOperandsMask::ZeroExtend |
+                         spv::ImageOperandsMask::Nontemporal);
     size_t expected_num_image_operand_words =
         spvtools::utils::CountSetBits(mask_bits_having_operands);
-    if (mask & SpvImageOperandsGradMask) {
+    if (mask & uint32_t(spv::ImageOperandsMask::Grad)) {
       // Grad uses two words.
       ++expected_num_image_operand_words;
     }
@@ -279,7 +279,8 @@
            << "Number of image operand ids doesn't correspond to the bit mask";
   }
 
-  if (info.multisampled & (0 == (mask & SpvImageOperandsSampleMask))) {
+  if (info.multisampled &
+      (0 == (mask & uint32_t(spv::ImageOperandsMask::Sample)))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Image Operand Sample is required for operation on "
               "multi-sampled image";
@@ -289,10 +290,11 @@
   // the module to be invalid.
   if (mask == 0) return SPV_SUCCESS;
 
-  if (spvtools::utils::CountSetBits(mask & (SpvImageOperandsOffsetMask |
-                                            SpvImageOperandsConstOffsetMask |
-                                            SpvImageOperandsConstOffsetsMask |
-                                            SpvImageOperandsOffsetsMask)) > 1) {
+  if (spvtools::utils::CountSetBits(
+          mask & uint32_t(spv::ImageOperandsMask::Offset |
+                          spv::ImageOperandsMask::ConstOffset |
+                          spv::ImageOperandsMask::ConstOffsets |
+                          spv::ImageOperandsMask::Offsets)) > 1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << _.VkErrorID(4662)
            << "Image Operands Offset, ConstOffset, ConstOffsets, Offsets "
@@ -306,7 +308,7 @@
 
   // The checks should be done in the order of definition of OperandImage.
 
-  if (mask & SpvImageOperandsBiasMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Bias)) {
     if (!is_implicit_lod && !is_valid_gather_lod_bias_amd) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Bias can only be used with ImplicitLod opcodes";
@@ -318,8 +320,8 @@
              << "Expected Image Operand Bias to be float scalar";
     }
 
-    if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-        info.dim != SpvDimCube) {
+    if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+        info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Bias requires 'Dim' parameter to be 1D, 2D, 3D "
                 "or Cube";
@@ -328,15 +330,16 @@
     // Multisampled is already checked.
   }
 
-  if (mask & SpvImageOperandsLodMask) {
-    if (!is_valid_lod_operand && opcode != SpvOpImageFetch &&
-        opcode != SpvOpImageSparseFetch && !is_valid_gather_lod_bias_amd) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Lod)) {
+    if (!is_valid_lod_operand && opcode != spv::Op::OpImageFetch &&
+        opcode != spv::Op::OpImageSparseFetch &&
+        !is_valid_gather_lod_bias_amd) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Lod can only be used with ExplicitLod opcodes "
              << "and OpImageFetch";
     }
 
-    if (mask & SpvImageOperandsGradMask) {
+    if (mask & uint32_t(spv::ImageOperandsMask::Grad)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand bits Lod and Grad cannot be set at the same "
                 "time";
@@ -357,8 +360,8 @@
       }
     }
 
-    if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-        info.dim != SpvDimCube) {
+    if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+        info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Lod requires 'Dim' parameter to be 1D, 2D, 3D "
                 "or Cube";
@@ -367,7 +370,7 @@
     // Multisampled is already checked.
   }
 
-  if (mask & SpvImageOperandsGradMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Grad)) {
     if (!is_explicit_lod) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Grad can only be used with ExplicitLod opcodes";
@@ -400,8 +403,8 @@
     // Multisampled is already checked.
   }
 
-  if (mask & SpvImageOperandsConstOffsetMask) {
-    if (info.dim == SpvDimCube) {
+  if (mask & uint32_t(spv::ImageOperandsMask::ConstOffset)) {
+    if (info.dim == spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand ConstOffset cannot be used with Cube Image "
                 "'Dim'";
@@ -429,8 +432,8 @@
     }
   }
 
-  if (mask & SpvImageOperandsOffsetMask) {
-    if (info.dim == SpvDimCube) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Offset)) {
+    if (info.dim == spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Offset cannot be used with Cube Image 'Dim'";
     }
@@ -453,9 +456,10 @@
 
     if (!_.options()->before_hlsl_legalization &&
         spvIsVulkanEnv(_.context()->target_env)) {
-      if (opcode != SpvOpImageGather && opcode != SpvOpImageDrefGather &&
-          opcode != SpvOpImageSparseGather &&
-          opcode != SpvOpImageSparseDrefGather) {
+      if (opcode != spv::Op::OpImageGather &&
+          opcode != spv::Op::OpImageDrefGather &&
+          opcode != spv::Op::OpImageSparseGather &&
+          opcode != spv::Op::OpImageSparseDrefGather) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << _.VkErrorID(4663)
                << "Image Operand Offset can only be used with "
@@ -464,16 +468,17 @@
     }
   }
 
-  if (mask & SpvImageOperandsConstOffsetsMask) {
-    if (opcode != SpvOpImageGather && opcode != SpvOpImageDrefGather &&
-        opcode != SpvOpImageSparseGather &&
-        opcode != SpvOpImageSparseDrefGather) {
+  if (mask & uint32_t(spv::ImageOperandsMask::ConstOffsets)) {
+    if (opcode != spv::Op::OpImageGather &&
+        opcode != spv::Op::OpImageDrefGather &&
+        opcode != spv::Op::OpImageSparseGather &&
+        opcode != spv::Op::OpImageSparseDrefGather) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand ConstOffsets can only be used with "
                 "OpImageGather and OpImageDrefGather";
     }
 
-    if (info.dim == SpvDimCube) {
+    if (info.dim == spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand ConstOffsets cannot be used with Cube Image "
                 "'Dim'";
@@ -484,7 +489,7 @@
     const Instruction* type_inst = _.FindDef(type_id);
     assert(type_inst);
 
-    if (type_inst->opcode() != SpvOpTypeArray) {
+    if (type_inst->opcode() != spv::Op::OpTypeArray) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Expected Image Operand ConstOffsets to be an array of size 4";
     }
@@ -513,10 +518,11 @@
     }
   }
 
-  if (mask & SpvImageOperandsSampleMask) {
-    if (opcode != SpvOpImageFetch && opcode != SpvOpImageRead &&
-        opcode != SpvOpImageWrite && opcode != SpvOpImageSparseFetch &&
-        opcode != SpvOpImageSparseRead) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Sample)) {
+    if (opcode != spv::Op::OpImageFetch && opcode != spv::Op::OpImageRead &&
+        opcode != spv::Op::OpImageWrite &&
+        opcode != spv::Op::OpImageSparseFetch &&
+        opcode != spv::Op::OpImageSparseRead) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Sample can only be used with OpImageFetch, "
              << "OpImageRead, OpImageWrite, OpImageSparseFetch and "
@@ -535,8 +541,8 @@
     }
   }
 
-  if (mask & SpvImageOperandsMinLodMask) {
-    if (!is_implicit_lod && !(mask & SpvImageOperandsGradMask)) {
+  if (mask & uint32_t(spv::ImageOperandsMask::MinLod)) {
+    if (!is_implicit_lod && !(mask & uint32_t(spv::ImageOperandsMask::Grad))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MinLod can only be used with ImplicitLod "
              << "opcodes or together with Image Operand Grad";
@@ -548,8 +554,8 @@
              << "Expected Image Operand MinLod to be float scalar";
     }
 
-    if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-        info.dim != SpvDimCube) {
+    if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+        info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MinLod requires 'Dim' parameter to be 1D, 2D, "
                 "3D or Cube";
@@ -561,16 +567,16 @@
     }
   }
 
-  if (mask & SpvImageOperandsMakeTexelAvailableKHRMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::MakeTexelAvailableKHR)) {
     // Checked elsewhere: capability and memory model are correct.
-    if (opcode != SpvOpImageWrite) {
+    if (opcode != spv::Op::OpImageWrite) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MakeTexelAvailableKHR can only be used with Op"
-             << spvOpcodeString(SpvOpImageWrite) << ": Op"
+             << spvOpcodeString(spv::Op::OpImageWrite) << ": Op"
              << spvOpcodeString(opcode);
     }
 
-    if (!(mask & SpvImageOperandsNonPrivateTexelKHRMask)) {
+    if (!(mask & uint32_t(spv::ImageOperandsMask::NonPrivateTexelKHR))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MakeTexelAvailableKHR requires "
                 "NonPrivateTexelKHR is also specified: Op"
@@ -582,17 +588,18 @@
       return error;
   }
 
-  if (mask & SpvImageOperandsMakeTexelVisibleKHRMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::MakeTexelVisibleKHR)) {
     // Checked elsewhere: capability and memory model are correct.
-    if (opcode != SpvOpImageRead && opcode != SpvOpImageSparseRead) {
+    if (opcode != spv::Op::OpImageRead &&
+        opcode != spv::Op::OpImageSparseRead) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MakeTexelVisibleKHR can only be used with Op"
-             << spvOpcodeString(SpvOpImageRead) << " or Op"
-             << spvOpcodeString(SpvOpImageSparseRead) << ": Op"
+             << spvOpcodeString(spv::Op::OpImageRead) << " or Op"
+             << spvOpcodeString(spv::Op::OpImageSparseRead) << ": Op"
              << spvOpcodeString(opcode);
     }
 
-    if (!(mask & SpvImageOperandsNonPrivateTexelKHRMask)) {
+    if (!(mask & uint32_t(spv::ImageOperandsMask::NonPrivateTexelKHR))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MakeTexelVisibleKHR requires NonPrivateTexelKHR "
                 "is also specified: Op"
@@ -603,7 +610,7 @@
     if (auto error = ValidateMemoryScope(_, inst, visible_scope)) return error;
   }
 
-  if (mask & SpvImageOperandsSignExtendMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::SignExtend)) {
     // Checked elsewhere: SPIR-V 1.4 version or later.
 
     // "The texel value is converted to the target value via sign extension.
@@ -616,7 +623,7 @@
     // setup.
   }
 
-  if (mask & SpvImageOperandsZeroExtendMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::ZeroExtend)) {
     // Checked elsewhere: SPIR-V 1.4 version or later.
 
     // "The texel value is converted to the target value via zero extension.
@@ -629,11 +636,11 @@
     // setup.
   }
 
-  if (mask & SpvImageOperandsOffsetsMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Offsets)) {
     // TODO: add validation
   }
 
-  if (mask & SpvImageOperandsNontemporalMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Nontemporal)) {
     // Checked elsewhere: SPIR-V 1.6 version or later.
   }
 
@@ -643,8 +650,8 @@
 // Validate OpImage*Proj* instructions
 spv_result_t ValidateImageProj(ValidationState_t& _, const Instruction* inst,
                                const ImageTypeInfo& info) {
-  if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-      info.dim != SpvDimRect) {
+  if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+      info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Rect) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image 'Dim' parameter to be 1D, 2D, 3D or Rect";
   }
@@ -667,25 +674,27 @@
                                     const Instruction* inst,
                                     const ImageTypeInfo& info) {
   if (info.sampled == 2) {
-    if (info.dim == SpvDim1D && !_.HasCapability(SpvCapabilityImage1D)) {
+    if (info.dim == spv::Dim::Dim1D &&
+        !_.HasCapability(spv::Capability::Image1D)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability Image1D is required to access storage image";
-    } else if (info.dim == SpvDimRect &&
-               !_.HasCapability(SpvCapabilityImageRect)) {
+    } else if (info.dim == spv::Dim::Rect &&
+               !_.HasCapability(spv::Capability::ImageRect)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability ImageRect is required to access storage image";
-    } else if (info.dim == SpvDimBuffer &&
-               !_.HasCapability(SpvCapabilityImageBuffer)) {
+    } else if (info.dim == spv::Dim::Buffer &&
+               !_.HasCapability(spv::Capability::ImageBuffer)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability ImageBuffer is required to access storage image";
-    } else if (info.dim == SpvDimCube && info.arrayed == 1 &&
-               !_.HasCapability(SpvCapabilityImageCubeArray)) {
+    } else if (info.dim == spv::Dim::Cube && info.arrayed == 1 &&
+               !_.HasCapability(spv::Capability::ImageCubeArray)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability ImageCubeArray is required to access "
              << "storage image";
     }
 
-    if (info.multisampled == 1 && !_.HasCapability(SpvCapabilityImageMSArray)) {
+    if (info.multisampled == 1 &&
+        !_.HasCapability(spv::Capability::ImageMSArray)) {
 #if 0
       // TODO(atgoo@github.com) The description of this rule in the spec
       // is unclear and Glslang doesn't declare ImageMSArray. Need to clarify
@@ -704,21 +713,21 @@
 }
 
 // Returns true if opcode is *ImageSparse*, false otherwise.
-bool IsSparse(SpvOp opcode) {
+bool IsSparse(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseTexelsResident:
-    case SpvOpImageSparseRead: {
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseTexelsResident:
+    case spv::Op::OpImageSparseRead: {
       return true;
     }
 
@@ -733,13 +742,13 @@
 // Not valid for sparse image opcodes which do not return a struct.
 spv_result_t GetActualResultType(ValidationState_t& _, const Instruction* inst,
                                  uint32_t* actual_result_type) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   if (IsSparse(opcode)) {
     const Instruction* const type_inst = _.FindDef(inst->type_id());
     assert(type_inst);
 
-    if (!type_inst || type_inst->opcode() != SpvOpTypeStruct) {
+    if (!type_inst || type_inst->opcode() != spv::Op::OpTypeStruct) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Expected Result Type to be OpTypeStruct";
     }
@@ -761,7 +770,7 @@
 
 // Returns a string describing actual result type of an opcode.
 // Not valid for sparse image opcodes which do not return a struct.
-const char* GetActualResultTypeStr(SpvOp opcode) {
+const char* GetActualResultTypeStr(spv::Op opcode) {
   if (IsSparse(opcode)) return "Result Type's second member";
   return "Result Type";
 }
@@ -777,7 +786,7 @@
 
   if (_.IsIntScalarType(info.sampled_type) &&
       (64 == _.GetBitWidth(info.sampled_type)) &&
-      !_.HasCapability(SpvCapabilityInt64ImageEXT)) {
+      !_.HasCapability(spv::Capability::Int64ImageEXT)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Capability Int64ImageEXT is required when using Sampled Type of "
               "64-bit int";
@@ -802,10 +811,10 @@
              << "Sampled Type must be OpTypeVoid in the OpenCL environment.";
     }
   } else {
-    const SpvOp sampled_type_opcode = _.GetIdOpcode(info.sampled_type);
-    if (sampled_type_opcode != SpvOpTypeVoid &&
-        sampled_type_opcode != SpvOpTypeInt &&
-        sampled_type_opcode != SpvOpTypeFloat) {
+    const spv::Op sampled_type_opcode = _.GetIdOpcode(info.sampled_type);
+    if (sampled_type_opcode != spv::Op::OpTypeVoid &&
+        sampled_type_opcode != spv::Op::OpTypeInt &&
+        sampled_type_opcode != spv::Op::OpTypeFloat) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Expected Sampled Type to be either void or"
              << " numerical scalar type";
@@ -835,19 +844,19 @@
            << "Invalid Sampled " << info.sampled << " (must be 0, 1 or 2)";
   }
 
-  if (info.dim == SpvDimSubpassData) {
+  if (info.dim == spv::Dim::SubpassData) {
     if (info.sampled != 2) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(6214) << "Dim SubpassData requires Sampled to be 2";
     }
 
-    if (info.format != SpvImageFormatUnknown) {
+    if (info.format != spv::ImageFormat::Unknown) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Dim SubpassData requires format Unknown";
     }
   } else {
     if (info.multisampled && (info.sampled == 2) &&
-        !_.HasCapability(SpvCapabilityStorageImageMultisample)) {
+        !_.HasCapability(spv::Capability::StorageImageMultisample)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability StorageImageMultisample is required when using "
                 "multisampled storage image";
@@ -855,8 +864,8 @@
   }
 
   if (spvIsOpenCLEnv(target_env)) {
-    if ((info.arrayed == 1) && (info.dim != SpvDim1D) &&
-        (info.dim != SpvDim2D)) {
+    if ((info.arrayed == 1) && (info.dim != spv::Dim::Dim1D) &&
+        (info.dim != spv::Dim::Dim2D)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "In the OpenCL environment, Arrayed may only be set to 1 "
              << "when Dim is either 1D or 2D.";
@@ -872,7 +881,7 @@
              << "Sampled must be 0 in the OpenCL environment.";
     }
 
-    if (info.access_qualifier == SpvAccessQualifierMax) {
+    if (info.access_qualifier == spv::AccessQualifier::Max) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "In the OpenCL environment, the optional Access Qualifier"
              << " must be present.";
@@ -886,7 +895,7 @@
              << "Sampled must be 1 or 2 in the Vulkan environment.";
     }
 
-    if (info.dim == SpvDimSubpassData && info.arrayed != 0) {
+    if (info.dim == spv::Dim::SubpassData && info.arrayed != 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(6214) << "Dim SubpassData requires Arrayed to be 0";
     }
@@ -898,7 +907,7 @@
 spv_result_t ValidateTypeSampledImage(ValidationState_t& _,
                                       const Instruction* inst) {
   const uint32_t image_type = inst->word(2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -918,7 +927,8 @@
   }
 
   // This covers both OpTypeSampledImage and OpSampledImage.
-  if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 6) && info.dim == SpvDimBuffer) {
+  if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 6) &&
+      info.dim == spv::Dim::Buffer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "In SPIR-V 1.6 or later, sampled image dimension must not be "
               "Buffer";
@@ -927,31 +937,31 @@
   return SPV_SUCCESS;
 }
 
-bool IsAllowedSampledImageOperand(SpvOp opcode, ValidationState_t& _) {
+bool IsAllowedSampledImageOperand(spv::Op opcode, ValidationState_t& _) {
   switch (opcode) {
-    case SpvOpSampledImage:
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImage:
-    case SpvOpImageQueryLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpCopyObject:
+    case spv::Op::OpSampledImage:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImage:
+    case spv::Op::OpImageQueryLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpCopyObject:
       return true;
-    case SpvOpStore:
-      if (_.HasCapability(SpvCapabilityBindlessTextureNV)) return true;
+    case spv::Op::OpStore:
+      if (_.HasCapability(spv::Capability::BindlessTextureNV)) return true;
       return false;
     default:
       return false;
@@ -960,13 +970,13 @@
 
 spv_result_t ValidateSampledImage(ValidationState_t& _,
                                   const Instruction* inst) {
-  if (_.GetIdOpcode(inst->type_id()) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(inst->type_id()) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypeSampledImage.";
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage.";
   }
@@ -994,12 +1004,12 @@
     }
   }
 
-  if (info.dim == SpvDimSubpassData) {
+  if (info.dim == spv::Dim::SubpassData) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image 'Dim' parameter to be not SubpassData.";
   }
 
-  if (_.GetIdOpcode(_.GetOperandTypeId(inst, 3)) != SpvOpTypeSampler) {
+  if (_.GetIdOpcode(_.GetOperandTypeId(inst, 3)) != spv::Op::OpTypeSampler) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sampler to be of type OpTypeSampler";
   }
@@ -1020,34 +1030,35 @@
                << "All OpSampledImage instructions must be in the same block "
                   "in "
                   "which their Result <id> are consumed. OpSampledImage Result "
-                  "Type <id> '"
+                  "Type <id> "
                << _.getIdName(inst->id())
-               << "' has a consumer in a different basic "
-                  "block. The consumer instruction <id> is '"
-               << _.getIdName(consumer_instr->id()) << "'.";
+               << " has a consumer in a different basic "
+                  "block. The consumer instruction <id> is "
+               << _.getIdName(consumer_instr->id()) << ".";
       }
 
-      if (consumer_opcode == SpvOpPhi || consumer_opcode == SpvOpSelect) {
+      if (consumer_opcode == spv::Op::OpPhi ||
+          consumer_opcode == spv::Op::OpSelect) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Result <id> from OpSampledImage instruction must not appear "
                   "as "
                   "operands of Op"
-               << spvOpcodeString(static_cast<SpvOp>(consumer_opcode)) << "."
-               << " Found result <id> '" << _.getIdName(inst->id())
-               << "' as an operand of <id> '"
-               << _.getIdName(consumer_instr->id()) << "'.";
+               << spvOpcodeString(static_cast<spv::Op>(consumer_opcode)) << "."
+               << " Found result <id> " << _.getIdName(inst->id())
+               << " as an operand of <id> " << _.getIdName(consumer_instr->id())
+               << ".";
       }
 
       if (!IsAllowedSampledImageOperand(consumer_opcode, _)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Result <id> from OpSampledImage instruction must not appear "
                   "as operand for Op"
-               << spvOpcodeString(static_cast<SpvOp>(consumer_opcode))
+               << spvOpcodeString(static_cast<spv::Op>(consumer_opcode))
                << ", since it is not specified as taking an "
                << "OpTypeSampledImage."
-               << " Found result <id> '" << _.getIdName(inst->id())
-               << "' as an operand of <id> '"
-               << _.getIdName(consumer_instr->id()) << "'.";
+               << " Found result <id> " << _.getIdName(inst->id())
+               << " as an operand of <id> " << _.getIdName(consumer_instr->id())
+               << ".";
       }
     }
   }
@@ -1057,13 +1068,13 @@
 spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
                                        const Instruction* inst) {
   const auto result_type = _.FindDef(inst->type_id());
-  if (result_type->opcode() != SpvOpTypePointer) {
+  if (result_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypePointer";
   }
 
-  const auto storage_class = result_type->GetOperandAs<uint32_t>(1);
-  if (storage_class != SpvStorageClassImage) {
+  const auto storage_class = result_type->GetOperandAs<spv::StorageClass>(1);
+  if (storage_class != spv::StorageClass::Image) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypePointer whose Storage Class "
               "operand is Image";
@@ -1071,21 +1082,21 @@
 
   const auto ptr_type = result_type->GetOperandAs<uint32_t>(2);
   const auto ptr_opcode = _.GetIdOpcode(ptr_type);
-  if (ptr_opcode != SpvOpTypeInt && ptr_opcode != SpvOpTypeFloat &&
-      ptr_opcode != SpvOpTypeVoid) {
+  if (ptr_opcode != spv::Op::OpTypeInt && ptr_opcode != spv::Op::OpTypeFloat &&
+      ptr_opcode != spv::Op::OpTypeVoid) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypePointer whose Type operand "
               "must be a scalar numerical type or OpTypeVoid";
   }
 
   const auto image_ptr = _.FindDef(_.GetOperandTypeId(inst, 2));
-  if (!image_ptr || image_ptr->opcode() != SpvOpTypePointer) {
+  if (!image_ptr || image_ptr->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be OpTypePointer";
   }
 
   const auto image_type = image_ptr->GetOperandAs<uint32_t>(2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be OpTypePointer with Type OpTypeImage";
   }
@@ -1102,7 +1113,7 @@
               "pointed to by Result Type";
   }
 
-  if (info.dim == SpvDimSubpassData) {
+  if (info.dim == spv::Dim::SubpassData) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Image Dim SubpassData cannot be used with OpImageTexelPointer";
   }
@@ -1118,11 +1129,11 @@
     expected_coord_size = GetPlaneCoordSize(info);
   } else if (info.arrayed == 1) {
     switch (info.dim) {
-      case SpvDim1D:
+      case spv::Dim::Dim1D:
         expected_coord_size = 2;
         break;
-      case SpvDimCube:
-      case SpvDim2D:
+      case spv::Dim::Cube:
+      case spv::Dim::Dim2D:
         expected_coord_size = 3;
         break;
       default:
@@ -1157,11 +1168,11 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if ((info.format != SpvImageFormatR64i) &&
-        (info.format != SpvImageFormatR64ui) &&
-        (info.format != SpvImageFormatR32f) &&
-        (info.format != SpvImageFormatR32i) &&
-        (info.format != SpvImageFormatR32ui)) {
+    if ((info.format != spv::ImageFormat::R64i) &&
+        (info.format != spv::ImageFormat::R64ui) &&
+        (info.format != spv::ImageFormat::R32f) &&
+        (info.format != spv::ImageFormat::R32i) &&
+        (info.format != spv::ImageFormat::R32ui)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4658)
              << "Expected the Image Format in Image to be R64i, R64ui, R32f, "
@@ -1173,7 +1184,7 @@
 }
 
 spv_result_t ValidateImageLod(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   uint32_t actual_result_type = 0;
   if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
     return error;
@@ -1193,7 +1204,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sampled Image to be of type OpTypeSampledImage";
   }
@@ -1216,7 +1227,7 @@
            << "Sampling operation is invalid for multisample image";
   }
 
-  if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t texel_component_type =
         _.GetComponentType(actual_result_type);
     if (texel_component_type != info.sampled_type) {
@@ -1227,9 +1238,9 @@
   }
 
   const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
-  if ((opcode == SpvOpImageSampleExplicitLod ||
-       opcode == SpvOpImageSparseSampleExplicitLod) &&
-      _.HasCapability(SpvCapabilityKernel)) {
+  if ((opcode == spv::Op::OpImageSampleExplicitLod ||
+       opcode == spv::Op::OpImageSparseSampleExplicitLod) &&
+      _.HasCapability(spv::Capability::Kernel)) {
     if (!_.IsFloatScalarOrVectorType(coord_type) &&
         !_.IsIntScalarOrVectorType(coord_type)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1252,9 +1263,9 @@
 
   const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
 
-  if (mask & SpvImageOperandsConstOffsetMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::ConstOffset)) {
     if (spvIsOpenCLEnv(_.context()->target_env)) {
-      if (opcode == SpvOpImageSampleExplicitLod) {
+      if (opcode == spv::Op::OpImageSampleExplicitLod) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "ConstOffset image operand not allowed "
                << "in the OpenCL environment.";
@@ -1279,7 +1290,7 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (info.dim == SpvDim3D) {
+    if (info.dim == spv::Dim::Dim3D) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4777)
              << "In Vulkan, OpImage*Dref* instructions must not use images "
@@ -1292,7 +1303,7 @@
 
 spv_result_t ValidateImageDrefLod(ValidationState_t& _,
                                   const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   uint32_t actual_result_type = 0;
   if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
     return error;
@@ -1306,7 +1317,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sampled Image to be of type OpTypeSampledImage";
   }
@@ -1364,7 +1375,7 @@
     return error;
   }
 
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   if (!_.IsIntVectorType(actual_result_type) &&
       !_.IsFloatVectorType(actual_result_type)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1379,7 +1390,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1390,7 +1401,7 @@
            << "Corrupt image type definition";
   }
 
-  if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t result_component_type =
         _.GetComponentType(actual_result_type);
     if (result_component_type != info.sampled_type) {
@@ -1400,7 +1411,7 @@
     }
   }
 
-  if (info.dim == SpvDimCube) {
+  if (info.dim == spv::Dim::Cube) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'Dim' cannot be Cube";
   }
 
@@ -1436,7 +1447,7 @@
   if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type))
     return error;
 
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   if (!_.IsIntVectorType(actual_result_type) &&
       !_.IsFloatVectorType(actual_result_type)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1451,7 +1462,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sampled Image to be of type OpTypeSampledImage";
   }
@@ -1470,8 +1481,9 @@
            << "Gather operation is invalid for multisample image";
   }
 
-  if (opcode == SpvOpImageDrefGather || opcode == SpvOpImageSparseDrefGather ||
-      _.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (opcode == spv::Op::OpImageDrefGather ||
+      opcode == spv::Op::OpImageSparseDrefGather ||
+      _.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t result_component_type =
         _.GetComponentType(actual_result_type);
     if (result_component_type != info.sampled_type) {
@@ -1481,8 +1493,8 @@
     }
   }
 
-  if (info.dim != SpvDim2D && info.dim != SpvDimCube &&
-      info.dim != SpvDimRect) {
+  if (info.dim != spv::Dim::Dim2D && info.dim != spv::Dim::Cube &&
+      info.dim != spv::Dim::Rect) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << _.VkErrorID(4777)
            << "Expected Image 'Dim' to be 2D, Cube, or Rect";
@@ -1502,7 +1514,8 @@
            << " components, but given only " << actual_coord_size;
   }
 
-  if (opcode == SpvOpImageGather || opcode == SpvOpImageSparseGather) {
+  if (opcode == spv::Op::OpImageGather ||
+      opcode == spv::Op::OpImageSparseGather) {
     const uint32_t component = inst->GetOperandAs<uint32_t>(4);
     const uint32_t component_index_type = _.GetTypeId(component);
     if (!_.IsIntScalarType(component_index_type) ||
@@ -1519,8 +1532,8 @@
       }
     }
   } else {
-    assert(opcode == SpvOpImageDrefGather ||
-           opcode == SpvOpImageSparseDrefGather);
+    assert(opcode == spv::Op::OpImageDrefGather ||
+           opcode == spv::Op::OpImageSparseDrefGather);
     if (spv_result_t result = ValidateImageDref(_, inst, info)) return result;
   }
 
@@ -1532,7 +1545,7 @@
 }
 
 spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   uint32_t actual_result_type = 0;
   if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
     return error;
@@ -1557,7 +1570,7 @@
   }  // Check OpenCL below, after we get the image info.
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1591,27 +1604,27 @@
     }
 
     const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
-    if (mask & SpvImageOperandsConstOffsetMask) {
+    if (mask & uint32_t(spv::ImageOperandsMask::ConstOffset)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "ConstOffset image operand not allowed "
              << "in the OpenCL environment.";
     }
   }
 
-  if (info.dim == SpvDimSubpassData) {
-    if (opcode == SpvOpImageSparseRead) {
+  if (info.dim == spv::Dim::SubpassData) {
+    if (opcode == spv::Op::OpImageSparseRead) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Dim SubpassData cannot be used with ImageSparseRead";
     }
 
     _.function(inst->function()->id())
         ->RegisterExecutionModelLimitation(
-            SpvExecutionModelFragment,
+            spv::ExecutionModel::Fragment,
             std::string("Dim SubpassData requires Fragment execution model: ") +
                 spvOpcodeString(opcode));
   }
 
-  if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t result_component_type =
         _.GetComponentType(actual_result_type);
     if (result_component_type != info.sampled_type) {
@@ -1639,8 +1652,9 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (info.format == SpvImageFormatUnknown && info.dim != SpvDimSubpassData &&
-        !_.HasCapability(SpvCapabilityStorageImageReadWithoutFormat)) {
+    if (info.format == spv::ImageFormat::Unknown &&
+        info.dim != spv::Dim::SubpassData &&
+        !_.HasCapability(spv::Capability::StorageImageReadWithoutFormat)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability StorageImageReadWithoutFormat is required to "
              << "read storage image";
@@ -1656,7 +1670,7 @@
 
 spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) {
   const uint32_t image_type = _.GetOperandTypeId(inst, 0);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1667,7 +1681,7 @@
            << "Corrupt image type definition";
   }
 
-  if (info.dim == SpvDimSubpassData) {
+  if (info.dim == spv::Dim::SubpassData) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Image 'Dim' cannot be SubpassData";
   }
@@ -1689,8 +1703,7 @@
            << " components, but given only " << actual_coord_size;
   }
 
-  // TODO(atgoo@github.com) The spec doesn't explicitly say what the type
-  // of texel should be.
+  // because it needs to match with 'Sampled Type' the Texel can't be a boolean
   const uint32_t texel_type = _.GetOperandTypeId(inst, 2);
   if (!_.IsIntScalarOrVectorType(texel_type) &&
       !_.IsFloatScalarOrVectorType(texel_type)) {
@@ -1698,15 +1711,7 @@
            << "Expected Texel to be int or float vector or scalar";
   }
 
-#if 0
-  // TODO: See above.
-  if (_.GetDimension(texel_type) != 4) {
-    return _.diag(SPV_ERROR_INVALID_DATA, inst)
-        << "Expected Texel to have 4 components";
-  }
-#endif
-
-  if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t texel_component_type = _.GetComponentType(texel_type);
     if (texel_component_type != info.sampled_type) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1716,8 +1721,9 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (info.format == SpvImageFormatUnknown && info.dim != SpvDimSubpassData &&
-        !_.HasCapability(SpvCapabilityStorageImageWriteWithoutFormat)) {
+    if (info.format == spv::ImageFormat::Unknown &&
+        info.dim != spv::Dim::SubpassData &&
+        !_.HasCapability(spv::Capability::StorageImageWriteWithoutFormat)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability StorageImageWriteWithoutFormat is required to "
                 "write "
@@ -1742,7 +1748,7 @@
 
 spv_result_t ValidateImage(ValidationState_t& _, const Instruction* inst) {
   const uint32_t result_type = inst->type_id();
-  if (_.GetIdOpcode(result_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(result_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypeImage";
   }
@@ -1751,7 +1757,7 @@
   const Instruction* sampled_image_type_inst = _.FindDef(sampled_image_type);
   assert(sampled_image_type_inst);
 
-  if (sampled_image_type_inst->opcode() != SpvOpTypeSampledImage) {
+  if (sampled_image_type_inst->opcode() != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sample Image to be of type OpTypeSampleImage";
   }
@@ -1773,7 +1779,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1786,14 +1792,14 @@
 
   uint32_t expected_num_components = info.arrayed;
   switch (info.dim) {
-    case SpvDim1D:
+    case spv::Dim::Dim1D:
       expected_num_components += 1;
       break;
-    case SpvDim2D:
-    case SpvDimCube:
+    case spv::Dim::Dim2D:
+    case spv::Dim::Cube:
       expected_num_components += 2;
       break;
-    case SpvDim3D:
+    case spv::Dim::Dim3D:
       expected_num_components += 3;
       break;
     default:
@@ -1839,7 +1845,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1852,16 +1858,16 @@
 
   uint32_t expected_num_components = info.arrayed;
   switch (info.dim) {
-    case SpvDim1D:
-    case SpvDimBuffer:
+    case spv::Dim::Dim1D:
+    case spv::Dim::Buffer:
       expected_num_components += 1;
       break;
-    case SpvDim2D:
-    case SpvDimCube:
-    case SpvDimRect:
+    case spv::Dim::Dim2D:
+    case spv::Dim::Cube:
+    case spv::Dim::Rect:
       expected_num_components += 2;
       break;
-    case SpvDim3D:
+    case spv::Dim::Dim3D:
       expected_num_components += 3;
       break;
     default:
@@ -1869,8 +1875,8 @@
              << "Image 'Dim' must be 1D, Buffer, 2D, Cube, 3D or Rect";
   }
 
-  if (info.dim == SpvDim1D || info.dim == SpvDim2D || info.dim == SpvDim3D ||
-      info.dim == SpvDimCube) {
+  if (info.dim == spv::Dim::Dim1D || info.dim == spv::Dim::Dim2D ||
+      info.dim == spv::Dim::Dim3D || info.dim == spv::Dim::Cube) {
     if (info.multisampled != 1 && info.sampled != 0 && info.sampled != 2) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image must have either 'MS'=1 or 'Sampled'=0 or 'Sampled'=2";
@@ -1894,7 +1900,7 @@
            << "Expected Result Type to be int scalar type";
   }
 
-  if (_.GetIdOpcode(_.GetOperandTypeId(inst, 2)) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(_.GetOperandTypeId(inst, 2)) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected operand to be of type OpTypeImage";
   }
@@ -1905,9 +1911,9 @@
                                    const Instruction* inst) {
   _.function(inst->function()->id())
       ->RegisterExecutionModelLimitation(
-          [&](SpvExecutionModel model, std::string* message) {
-            if (model != SpvExecutionModelFragment &&
-                model != SpvExecutionModelGLCompute) {
+          [&](spv::ExecutionModel model, std::string* message) {
+            if (model != spv::ExecutionModel::Fragment &&
+                model != spv::ExecutionModel::GLCompute) {
               if (message) {
                 *message = std::string(
                     "OpImageQueryLod requires Fragment or GLCompute execution "
@@ -1923,10 +1929,10 @@
                               std::string* message) {
         const auto* models = state.GetExecutionModels(entry_point->id());
         const auto* modes = state.GetExecutionModes(entry_point->id());
-        if (models->find(SpvExecutionModelGLCompute) != models->end() &&
-            modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
+        if (models->find(spv::ExecutionModel::GLCompute) != models->end() &&
+            modes->find(spv::ExecutionMode::DerivativeGroupLinearNV) ==
                 modes->end() &&
-            modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
+            modes->find(spv::ExecutionMode::DerivativeGroupQuadsNV) ==
                 modes->end()) {
           if (message) {
             *message = std::string(
@@ -1951,7 +1957,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image operand to be of type OpTypeSampledImage";
   }
@@ -1962,14 +1968,14 @@
            << "Corrupt image type definition";
   }
 
-  if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-      info.dim != SpvDimCube) {
+  if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+      info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Image 'Dim' must be 1D, 2D, 3D or Cube";
   }
 
   const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
-  if (_.HasCapability(SpvCapabilityKernel)) {
+  if (_.HasCapability(spv::Capability::Kernel)) {
     if (!_.IsFloatScalarOrVectorType(coord_type) &&
         !_.IsIntScalarOrVectorType(coord_type)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2014,7 +2020,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -2025,10 +2031,10 @@
            << "Corrupt image type definition";
   }
 
-  const SpvOp opcode = inst->opcode();
-  if (opcode == SpvOpImageQueryLevels) {
-    if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-        info.dim != SpvDimCube) {
+  const spv::Op opcode = inst->opcode();
+  if (opcode == spv::Op::OpImageQueryLevels) {
+    if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+        info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image 'Dim' must be 1D, 2D, 3D or Cube";
     }
@@ -2042,8 +2048,8 @@
       }
     }
   } else {
-    assert(opcode == SpvOpImageQuerySamples);
-    if (info.dim != SpvDim2D) {
+    assert(opcode == spv::Op::OpImageQuerySamples);
+    if (info.dim != spv::Dim::Dim2D) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'Dim' must be 2D";
     }
 
@@ -2074,13 +2080,13 @@
 
 // Validates correctness of image instructions.
 spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   if (IsImplicitLod(opcode)) {
     _.function(inst->function()->id())
-        ->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
+        ->RegisterExecutionModelLimitation([opcode](spv::ExecutionModel model,
                                                     std::string* message) {
-          if (model != SpvExecutionModelFragment &&
-              model != SpvExecutionModelGLCompute) {
+          if (model != spv::ExecutionModel::Fragment &&
+              model != spv::ExecutionModel::GLCompute) {
             if (message) {
               *message =
                   std::string(
@@ -2099,11 +2105,11 @@
           const auto* models = state.GetExecutionModels(entry_point->id());
           const auto* modes = state.GetExecutionModes(entry_point->id());
           if (models &&
-              models->find(SpvExecutionModelGLCompute) != models->end() &&
+              models->find(spv::ExecutionModel::GLCompute) != models->end() &&
               (!modes ||
-               (modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
+               (modes->find(spv::ExecutionMode::DerivativeGroupLinearNV) ==
                     modes->end() &&
-                modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
+                modes->find(spv::ExecutionMode::DerivativeGroupQuadsNV) ==
                     modes->end()))) {
             if (message) {
               *message =
@@ -2120,73 +2126,73 @@
   }
 
   switch (opcode) {
-    case SpvOpTypeImage:
+    case spv::Op::OpTypeImage:
       return ValidateTypeImage(_, inst);
-    case SpvOpTypeSampledImage:
+    case spv::Op::OpTypeSampledImage:
       return ValidateTypeSampledImage(_, inst);
-    case SpvOpSampledImage:
+    case spv::Op::OpSampledImage:
       return ValidateSampledImage(_, inst);
-    case SpvOpImageTexelPointer:
+    case spv::Op::OpImageTexelPointer:
       return ValidateImageTexelPointer(_, inst);
 
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
       return ValidateImageLod(_, inst);
 
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
       return ValidateImageDrefLod(_, inst);
 
-    case SpvOpImageFetch:
-    case SpvOpImageSparseFetch:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageSparseFetch:
       return ValidateImageFetch(_, inst);
 
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
       return ValidateImageGather(_, inst);
 
-    case SpvOpImageRead:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseRead:
       return ValidateImageRead(_, inst);
 
-    case SpvOpImageWrite:
+    case spv::Op::OpImageWrite:
       return ValidateImageWrite(_, inst);
 
-    case SpvOpImage:
+    case spv::Op::OpImage:
       return ValidateImage(_, inst);
 
-    case SpvOpImageQueryFormat:
-    case SpvOpImageQueryOrder:
+    case spv::Op::OpImageQueryFormat:
+    case spv::Op::OpImageQueryOrder:
       return ValidateImageQueryFormatOrOrder(_, inst);
 
-    case SpvOpImageQuerySizeLod:
+    case spv::Op::OpImageQuerySizeLod:
       return ValidateImageQuerySizeLod(_, inst);
-    case SpvOpImageQuerySize:
+    case spv::Op::OpImageQuerySize:
       return ValidateImageQuerySize(_, inst);
-    case SpvOpImageQueryLod:
+    case spv::Op::OpImageQueryLod:
       return ValidateImageQueryLod(_, inst);
 
-    case SpvOpImageQueryLevels:
-    case SpvOpImageQuerySamples:
+    case spv::Op::OpImageQueryLevels:
+    case spv::Op::OpImageQuerySamples:
       return ValidateImageQueryLevelsOrSamples(_, inst);
 
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
       return ValidateImageSparseLod(_, inst);
 
-    case SpvOpImageSparseTexelsResident:
+    case spv::Op::OpImageSparseTexelsResident:
       return ValidateImageSparseTexelsResident(_, inst);
 
     default:
diff --git a/third_party/SPIRV-Tools/source/val/validate_instruction.cpp b/third_party/SPIRV-Tools/source/val/validate_instruction.cpp
index 767c0ce..1b7847c 100644
--- a/third_party/SPIRV-Tools/source/val/validate_instruction.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_instruction.cpp
@@ -44,13 +44,13 @@
 std::string ToString(const CapabilitySet& capabilities,
                      const AssemblyGrammar& grammar) {
   std::stringstream ss;
-  capabilities.ForEach([&grammar, &ss](SpvCapability cap) {
+  capabilities.ForEach([&grammar, &ss](spv::Capability cap) {
     spv_operand_desc desc;
-    if (SPV_SUCCESS ==
-        grammar.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc))
+    if (SPV_SUCCESS == grammar.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
+                                             uint32_t(cap), &desc))
       ss << desc->name << " ";
     else
-      ss << cap << " ";
+      ss << uint32_t(cap) << " ";
   });
   return ss.str();
 }
@@ -60,18 +60,18 @@
 // the opcode may only be used if at least one of the capabilities is specified
 // by the module.
 CapabilitySet EnablingCapabilitiesForOp(const ValidationState_t& state,
-                                        SpvOp opcode) {
+                                        spv::Op opcode) {
   // Exceptions for SPV_AMD_shader_ballot
   switch (opcode) {
     // Normally these would require Group capability
-    case SpvOpGroupIAddNonUniformAMD:
-    case SpvOpGroupFAddNonUniformAMD:
-    case SpvOpGroupFMinNonUniformAMD:
-    case SpvOpGroupUMinNonUniformAMD:
-    case SpvOpGroupSMinNonUniformAMD:
-    case SpvOpGroupFMaxNonUniformAMD:
-    case SpvOpGroupUMaxNonUniformAMD:
-    case SpvOpGroupSMaxNonUniformAMD:
+    case spv::Op::OpGroupIAddNonUniformAMD:
+    case spv::Op::OpGroupFAddNonUniformAMD:
+    case spv::Op::OpGroupFMinNonUniformAMD:
+    case spv::Op::OpGroupUMinNonUniformAMD:
+    case spv::Op::OpGroupSMinNonUniformAMD:
+    case spv::Op::OpGroupFMaxNonUniformAMD:
+    case spv::Op::OpGroupUMaxNonUniformAMD:
+    case spv::Op::OpGroupSMaxNonUniformAMD:
       if (state.HasExtension(kSPV_AMD_shader_ballot)) return CapabilitySet();
       break;
     default:
@@ -151,10 +151,10 @@
   // not implemented yet.  This rule is independent of target environment.
   // See https://github.com/KhronosGroup/SPIRV-Tools/issues/365
   if (operand.type == SPV_OPERAND_TYPE_BUILT_IN) {
-    switch (word) {
-      case SpvBuiltInPointSize:
-      case SpvBuiltInClipDistance:
-      case SpvBuiltInCullDistance:
+    switch (spv::BuiltIn(word)) {
+      case spv::BuiltIn::PointSize:
+      case spv::BuiltIn::ClipDistance:
+      case spv::BuiltIn::CullDistance:
         return SPV_SUCCESS;
       default:
         break;
@@ -166,7 +166,7 @@
     }
   } else if (operand.type == SPV_OPERAND_TYPE_GROUP_OPERATION &&
              state.features().group_ops_reduce_and_scans &&
-             (word <= uint32_t(SpvGroupOperationExclusiveScan))) {
+             (word <= uint32_t(spv::GroupOperation::ExclusiveScan))) {
     // Allow certain group operations if requested.
     return SPV_SUCCESS;
   }
@@ -178,15 +178,16 @@
   if (lookup_result == SPV_SUCCESS) {
     // Allow FPRoundingMode decoration if requested.
     if (operand.type == SPV_OPERAND_TYPE_DECORATION &&
-        operand_desc->value == SpvDecorationFPRoundingMode) {
+        spv::Decoration(operand_desc->value) ==
+            spv::Decoration::FPRoundingMode) {
       if (state.features().free_fp_rounding_mode) return SPV_SUCCESS;
 
       // Vulkan API requires more capabilities on rounding mode.
       if (spvIsVulkanEnv(state.context()->target_env)) {
-        enabling_capabilities.Add(SpvCapabilityStorageUniformBufferBlock16);
-        enabling_capabilities.Add(SpvCapabilityStorageUniform16);
-        enabling_capabilities.Add(SpvCapabilityStoragePushConstant16);
-        enabling_capabilities.Add(SpvCapabilityStorageInputOutput16);
+        enabling_capabilities.Add(spv::Capability::StorageUniformBufferBlock16);
+        enabling_capabilities.Add(spv::Capability::StorageUniform16);
+        enabling_capabilities.Add(spv::Capability::StoragePushConstant16);
+        enabling_capabilities.Add(spv::Capability::StorageInputOutput16);
       }
     } else {
       enabling_capabilities = state.grammar().filterCapsAgainstTargetEnv(
@@ -197,7 +198,7 @@
     // registers a capability with the module *before* checking capabilities.
     // So in the case of an OpCapability instruction, don't bother checking
     // enablement by another capability.
-    if (inst->opcode() != SpvOpCapability) {
+    if (inst->opcode() != spv::Op::OpCapability) {
       const bool enabled_by_cap =
           state.HasAnyOfCapabilities(enabling_capabilities);
       if (!enabling_capabilities.IsEmpty() && !enabled_by_cap) {
@@ -218,14 +219,14 @@
 // is explicitly reserved in the SPIR-V core spec.  Otherwise return
 // SPV_SUCCESS.
 spv_result_t ReservedCheck(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   switch (opcode) {
     // These instructions are enabled by a capability, but should never
     // be used anyway.
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod: {
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod: {
       spv_opcode_desc inst_desc;
       _.grammar().lookupOpcode(opcode, &inst_desc);
       return _.diag(SPV_ERROR_INVALID_BINARY, inst)
@@ -241,7 +242,7 @@
 // instruction is invalid because the required capability isn't declared
 // in the module.
 spv_result_t CapabilityCheck(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   CapabilitySet opcode_caps = EnablingCapabilitiesForOp(_, opcode);
   if (!_.HasAnyOfCapabilities(opcode_caps)) {
     return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst)
@@ -299,7 +300,7 @@
   // OpTerminateInvocation is special because it is enabled by Shader
   // capability, but also requires an extension and/or version check.
   const bool capability_check_is_sufficient =
-      inst->opcode() != SpvOpTerminateInvocation;
+      inst->opcode() != spv::Op::OpTerminateInvocation;
 
   if (capability_check_is_sufficient && (inst_desc->numCapabilities > 0u)) {
     // We already checked that the direct capability dependency has been
@@ -357,7 +358,7 @@
 
 // Checks that the number of OpTypeStruct members is within the limit.
 spv_result_t LimitCheckStruct(ValidationState_t& _, const Instruction* inst) {
-  if (SpvOpTypeStruct != inst->opcode()) {
+  if (spv::Op::OpTypeStruct != inst->opcode()) {
     return SPV_SUCCESS;
   }
 
@@ -382,7 +383,7 @@
   for (size_t word_i = 2; word_i < inst->words().size(); ++word_i) {
     auto member = inst->word(word_i);
     auto memberTypeInstr = _.FindDef(member);
-    if (memberTypeInstr && SpvOpTypeStruct == memberTypeInstr->opcode()) {
+    if (memberTypeInstr && spv::Op::OpTypeStruct == memberTypeInstr->opcode()) {
       max_member_depth = std::max(
           max_member_depth, _.struct_nesting_depth(memberTypeInstr->id()));
     }
@@ -402,7 +403,7 @@
 // Checks that the number of (literal, label) pairs in OpSwitch is within
 // the limit.
 spv_result_t LimitCheckSwitch(ValidationState_t& _, const Instruction* inst) {
-  if (SpvOpSwitch == inst->opcode()) {
+  if (spv::Op::OpSwitch == inst->opcode()) {
     // The instruction syntax is as follows:
     // OpSwitch <selector ID> <Default ID> literal label literal label ...
     // literal,label pairs come after the first 2 operands.
@@ -422,8 +423,8 @@
 // Ensure the number of variables of the given class does not exceed the
 // limit.
 spv_result_t LimitCheckNumVars(ValidationState_t& _, const uint32_t var_id,
-                               const SpvStorageClass storage_class) {
-  if (SpvStorageClassFunction == storage_class) {
+                               const spv::StorageClass storage_class) {
+  if (spv::StorageClass::Function == storage_class) {
     _.registerLocalVariable(var_id);
     const uint32_t num_local_vars_limit =
         _.options()->universal_limits_.max_local_variables;
@@ -462,29 +463,29 @@
 }  // namespace
 
 spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
-  if (opcode == SpvOpExtension) {
+  const spv::Op opcode = inst->opcode();
+  if (opcode == spv::Op::OpExtension) {
     CheckIfKnownExtension(_, inst);
-  } else if (opcode == SpvOpCapability) {
-    _.RegisterCapability(inst->GetOperandAs<SpvCapability>(0));
-  } else if (opcode == SpvOpMemoryModel) {
+  } else if (opcode == spv::Op::OpCapability) {
+    _.RegisterCapability(inst->GetOperandAs<spv::Capability>(0));
+  } else if (opcode == spv::Op::OpMemoryModel) {
     if (_.has_memory_model_specified()) {
       return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
              << "OpMemoryModel should only be provided once.";
     }
-    _.set_addressing_model(inst->GetOperandAs<SpvAddressingModel>(0));
-    _.set_memory_model(inst->GetOperandAs<SpvMemoryModel>(1));
-  } else if (opcode == SpvOpExecutionMode) {
+    _.set_addressing_model(inst->GetOperandAs<spv::AddressingModel>(0));
+    _.set_memory_model(inst->GetOperandAs<spv::MemoryModel>(1));
+  } else if (opcode == spv::Op::OpExecutionMode) {
     const uint32_t entry_point = inst->word(1);
     _.RegisterExecutionModeForEntryPoint(entry_point,
-                                         SpvExecutionMode(inst->word(2)));
-  } else if (opcode == SpvOpVariable) {
-    const auto storage_class = inst->GetOperandAs<SpvStorageClass>(2);
+                                         spv::ExecutionMode(inst->word(2)));
+  } else if (opcode == spv::Op::OpVariable) {
+    const auto storage_class = inst->GetOperandAs<spv::StorageClass>(2);
     if (auto error = LimitCheckNumVars(_, inst->id(), storage_class)) {
       return error;
     }
-  } else if (opcode == SpvOpSamplerImageAddressingModeNV) {
-    if (!_.HasCapability(SpvCapabilityBindlessTextureNV)) {
+  } else if (opcode == spv::Op::OpSamplerImageAddressingModeNV) {
+    if (!_.HasCapability(spv::Capability::BindlessTextureNV)) {
       return _.diag(SPV_ERROR_MISSING_EXTENSION, inst)
              << "OpSamplerImageAddressingModeNV supported only with extension "
                 "SPV_NV_bindless_texture";
diff --git a/third_party/SPIRV-Tools/source/val/validate_interfaces.cpp b/third_party/SPIRV-Tools/source/val/validate_interfaces.cpp
index 7f2d648..54152da 100644
--- a/third_party/SPIRV-Tools/source/val/validate_interfaces.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_interfaces.cpp
@@ -35,12 +35,15 @@
 bool is_interface_variable(const Instruction* inst, bool is_spv_1_4) {
   if (is_spv_1_4) {
     // Starting in SPIR-V 1.4, all global variables are interface variables.
-    return inst->opcode() == SpvOpVariable &&
-           inst->word(3u) != SpvStorageClassFunction;
+    return inst->opcode() == spv::Op::OpVariable &&
+           inst->GetOperandAs<spv::StorageClass>(2u) !=
+               spv::StorageClass::Function;
   } else {
-    return inst->opcode() == SpvOpVariable &&
-           (inst->word(3u) == SpvStorageClassInput ||
-            inst->word(3u) == SpvStorageClassOutput);
+    return inst->opcode() == spv::Op::OpVariable &&
+           (inst->GetOperandAs<spv::StorageClass>(2u) ==
+                spv::StorageClass::Input ||
+            inst->GetOperandAs<spv::StorageClass>(2u) ==
+                spv::StorageClass::Output);
   }
 }
 
@@ -114,29 +117,30 @@
                                   uint32_t* num_locations) {
   *num_locations = 0;
   switch (type->opcode()) {
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       // Scalars always consume a single location.
       *num_locations = 1;
       break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       // 3- and 4-component 64-bit vectors consume two locations.
-      if ((_.ContainsSizedIntOrFloatType(type->id(), SpvOpTypeInt, 64) ||
-           _.ContainsSizedIntOrFloatType(type->id(), SpvOpTypeFloat, 64)) &&
+      if ((_.ContainsSizedIntOrFloatType(type->id(), spv::Op::OpTypeInt, 64) ||
+           _.ContainsSizedIntOrFloatType(type->id(), spv::Op::OpTypeFloat,
+                                         64)) &&
           (type->GetOperandAs<uint32_t>(2) > 2)) {
         *num_locations = 2;
       } else {
         *num_locations = 1;
       }
       break;
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       // Matrices consume locations equal to the underlying vector type for
       // each column.
       NumConsumedLocations(_, _.FindDef(type->GetOperandAs<uint32_t>(1)),
                            num_locations);
       *num_locations *= type->GetOperandAs<uint32_t>(2);
       break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       // Arrays consume locations equal to the underlying type times the number
       // of elements in the vector.
       NumConsumedLocations(_, _.FindDef(type->GetOperandAs<uint32_t>(1)),
@@ -150,9 +154,9 @@
       if (is_int && is_const) *num_locations *= value;
       break;
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       // Members cannot have location decorations at this point.
-      if (_.HasDecoration(type->id(), SpvDecorationLocation)) {
+      if (_.HasDecoration(type->id(), spv::Decoration::Location)) {
         return _.diag(SPV_ERROR_INVALID_DATA, type)
                << _.VkErrorID(4918) << "Members cannot be assigned a location";
       }
@@ -182,8 +186,8 @@
 uint32_t NumConsumedComponents(ValidationState_t& _, const Instruction* type) {
   uint32_t num_components = 0;
   switch (type->opcode()) {
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       // 64-bit types consume two components.
       if (type->GetOperandAs<uint32_t>(1) == 64) {
         num_components = 2;
@@ -191,7 +195,7 @@
         num_components = 1;
       }
       break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       // Vectors consume components equal to the underlying type's consumption
       // times the number of elements in the vector. Note that 3- and 4-element
       // vectors cannot have a component decoration (i.e. assumed to be zero).
@@ -199,7 +203,7 @@
           NumConsumedComponents(_, _.FindDef(type->GetOperandAs<uint32_t>(1)));
       num_components *= type->GetOperandAs<uint32_t>(2);
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       // Skip the array.
       return NumConsumedComponents(_,
                                    _.FindDef(type->GetOperandAs<uint32_t>(1)));
@@ -218,10 +222,10 @@
     ValidationState_t& _, const Instruction* entry_point,
     const Instruction* variable, std::unordered_set<uint32_t>* locations,
     std::unordered_set<uint32_t>* output_index1_locations) {
-  const bool is_fragment = entry_point->GetOperandAs<SpvExecutionModel>(0) ==
-                           SpvExecutionModelFragment;
+  const bool is_fragment = entry_point->GetOperandAs<spv::ExecutionModel>(0) ==
+                           spv::ExecutionModel::Fragment;
   const bool is_output =
-      variable->GetOperandAs<SpvStorageClass>(2) == SpvStorageClassOutput;
+      variable->GetOperandAs<spv::StorageClass>(2) == spv::StorageClass::Output;
   auto ptr_type_id = variable->GetOperandAs<uint32_t>(0);
   auto ptr_type = _.FindDef(ptr_type_id);
   auto type_id = ptr_type->GetOperandAs<uint32_t>(2);
@@ -240,21 +244,21 @@
   bool has_per_task_nv = false;
   bool has_per_vertex_khr = false;
   for (auto& dec : _.id_decorations(variable->id())) {
-    if (dec.dec_type() == SpvDecorationLocation) {
+    if (dec.dec_type() == spv::Decoration::Location) {
       if (has_location && dec.params()[0] != location) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << "Variable has conflicting location decorations";
       }
       has_location = true;
       location = dec.params()[0];
-    } else if (dec.dec_type() == SpvDecorationComponent) {
+    } else if (dec.dec_type() == spv::Decoration::Component) {
       if (has_component && dec.params()[0] != component) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << "Variable has conflicting component decorations";
       }
       has_component = true;
       component = dec.params()[0];
-    } else if (dec.dec_type() == SpvDecorationIndex) {
+    } else if (dec.dec_type() == spv::Decoration::Index) {
       if (!is_output || !is_fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << "Index can only be applied to Fragment output variables";
@@ -265,22 +269,22 @@
       }
       has_index = true;
       index = dec.params()[0];
-    } else if (dec.dec_type() == SpvDecorationBuiltIn) {
+    } else if (dec.dec_type() == spv::Decoration::BuiltIn) {
       // Don't check built-ins.
       return SPV_SUCCESS;
-    } else if (dec.dec_type() == SpvDecorationPatch) {
+    } else if (dec.dec_type() == spv::Decoration::Patch) {
       has_patch = true;
-    } else if (dec.dec_type() == SpvDecorationPerTaskNV) {
+    } else if (dec.dec_type() == spv::Decoration::PerTaskNV) {
       has_per_task_nv = true;
-    } else if (dec.dec_type() == SpvDecorationPerVertexKHR) {
+    } else if (dec.dec_type() == spv::Decoration::PerVertexKHR) {
       if (!is_fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << _.VkErrorID(6777)
                << "PerVertexKHR can only be applied to Fragment Execution "
                   "Models";
       }
-      if (type->opcode() != SpvOpTypeArray &&
-          type->opcode() != SpvOpTypeRuntimeArray) {
+      if (type->opcode() != spv::Op::OpTypeArray &&
+          type->opcode() != spv::Op::OpTypeRuntimeArray) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << _.VkErrorID(6778)
                << "PerVertexKHR must be declared as arrays";
@@ -293,28 +297,28 @@
   // tessellation control, evaluation and geometry per-vertex inputs have a
   // layer of arraying that is not included in interface matching.
   bool is_arrayed = false;
-  switch (entry_point->GetOperandAs<SpvExecutionModel>(0)) {
-    case SpvExecutionModelTessellationControl:
+  switch (entry_point->GetOperandAs<spv::ExecutionModel>(0)) {
+    case spv::ExecutionModel::TessellationControl:
       if (!has_patch) {
         is_arrayed = true;
       }
       break;
-    case SpvExecutionModelTessellationEvaluation:
+    case spv::ExecutionModel::TessellationEvaluation:
       if (!is_output && !has_patch) {
         is_arrayed = true;
       }
       break;
-    case SpvExecutionModelGeometry:
+    case spv::ExecutionModel::Geometry:
       if (!is_output) {
         is_arrayed = true;
       }
       break;
-    case SpvExecutionModelFragment:
+    case spv::ExecutionModel::Fragment:
       if (!is_output && has_per_vertex_khr) {
         is_arrayed = true;
       }
       break;
-    case SpvExecutionModelMeshNV:
+    case spv::ExecutionModel::MeshNV:
       if (is_output && !has_per_task_nv) {
         is_arrayed = true;
       }
@@ -324,21 +328,21 @@
   }
 
   // Unpack arrayness.
-  if (is_arrayed && (type->opcode() == SpvOpTypeArray ||
-                     type->opcode() == SpvOpTypeRuntimeArray)) {
+  if (is_arrayed && (type->opcode() == spv::Op::OpTypeArray ||
+                     type->opcode() == spv::Op::OpTypeRuntimeArray)) {
     type_id = type->GetOperandAs<uint32_t>(1);
     type = _.FindDef(type_id);
   }
 
-  if (type->opcode() == SpvOpTypeStruct) {
+  if (type->opcode() == spv::Op::OpTypeStruct) {
     // Don't check built-ins.
-    if (_.HasDecoration(type_id, SpvDecorationBuiltIn)) return SPV_SUCCESS;
+    if (_.HasDecoration(type_id, spv::Decoration::BuiltIn)) return SPV_SUCCESS;
   }
 
   // Only block-decorated structs don't need a location on the variable.
-  const bool is_block = _.HasDecoration(type_id, SpvDecorationBlock);
+  const bool is_block = _.HasDecoration(type_id, spv::Decoration::Block);
   if (!has_location && !is_block) {
-    const auto vuid = (type->opcode() == SpvOpTypeStruct) ? 4917 : 4916;
+    const auto vuid = (type->opcode() == spv::Op::OpTypeStruct) ? 4917 : 4916;
     return _.diag(SPV_ERROR_INVALID_DATA, variable)
            << _.VkErrorID(vuid) << "Variable must be decorated with a location";
   }
@@ -351,7 +355,7 @@
     uint32_t array_size = 1;
     // If the variable is still arrayed, mark the locations/components per
     // index.
-    if (type->opcode() == SpvOpTypeArray) {
+    if (type->opcode() == spv::Op::OpTypeArray) {
       // Determine the array size if possible and get the element type.
       std::tie(is_int, is_const, array_size) =
           _.EvalInt32IfConst(type->GetOperandAs<uint32_t>(2));
@@ -399,7 +403,7 @@
     std::unordered_map<uint32_t, uint32_t> member_locations;
     std::unordered_map<uint32_t, uint32_t> member_components;
     for (auto& dec : _.id_decorations(type_id)) {
-      if (dec.dec_type() == SpvDecorationLocation) {
+      if (dec.dec_type() == spv::Decoration::Location) {
         auto where = member_locations.find(dec.struct_member_index());
         if (where == member_locations.end()) {
           member_locations[dec.struct_member_index()] = dec.params()[0];
@@ -408,7 +412,7 @@
                  << "Member index " << dec.struct_member_index()
                  << " has conflicting location assignments";
         }
-      } else if (dec.dec_type() == SpvDecorationComponent) {
+      } else if (dec.dec_type() == spv::Decoration::Component) {
         auto where = member_components.find(dec.struct_member_index());
         if (where == member_components.end()) {
           member_components[dec.struct_member_index()] = dec.params()[0];
@@ -447,7 +451,7 @@
         continue;
       }
 
-      if (member->opcode() == SpvOpTypeArray && num_components >= 1 &&
+      if (member->opcode() == spv::Op::OpTypeArray && num_components >= 1 &&
           num_components < 4) {
         // When an array has an element that takes less than a location in
         // size, calculate the used locations in a strided manner.
@@ -492,12 +496,12 @@
   // TODO(dneto): SPV_NV_ray_tracing also uses locations on interface variables,
   // in other shader stages. Similarly, the *provisional* version of
   // SPV_KHR_ray_tracing did as well, but not the final version.
-  switch (entry_point->GetOperandAs<SpvExecutionModel>(0)) {
-    case SpvExecutionModelVertex:
-    case SpvExecutionModelTessellationControl:
-    case SpvExecutionModelTessellationEvaluation:
-    case SpvExecutionModelGeometry:
-    case SpvExecutionModelFragment:
+  switch (entry_point->GetOperandAs<spv::ExecutionModel>(0)) {
+    case spv::ExecutionModel::Vertex:
+    case spv::ExecutionModel::TessellationControl:
+    case spv::ExecutionModel::TessellationEvaluation:
+    case spv::ExecutionModel::Geometry:
+    case spv::ExecutionModel::Fragment:
       break;
     default:
       return SPV_SUCCESS;
@@ -511,9 +515,9 @@
   for (uint32_t i = 3; i < entry_point->operands().size(); ++i) {
     auto interface_id = entry_point->GetOperandAs<uint32_t>(i);
     auto interface_var = _.FindDef(interface_id);
-    auto storage_class = interface_var->GetOperandAs<SpvStorageClass>(2);
-    if (storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    auto storage_class = interface_var->GetOperandAs<spv::StorageClass>(2);
+    if (storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       continue;
     }
     if (!seen.insert(interface_id).second) {
@@ -522,7 +526,7 @@
       continue;
     }
 
-    auto locations = (storage_class == SpvStorageClassInput)
+    auto locations = (storage_class == spv::StorageClass::Input)
                          ? &input_locations
                          : &output_locations_index0;
     if (auto error = GetLocationsForVariable(
@@ -533,6 +537,64 @@
   return SPV_SUCCESS;
 }
 
+spv_result_t ValidateStorageClass(ValidationState_t& _,
+                                  const Instruction* entry_point) {
+  bool has_push_constant = false;
+  bool has_ray_payload = false;
+  bool has_hit_attribute = false;
+  bool has_callable_data = false;
+  for (uint32_t i = 3; i < entry_point->operands().size(); ++i) {
+    auto interface_id = entry_point->GetOperandAs<uint32_t>(i);
+    auto interface_var = _.FindDef(interface_id);
+    auto storage_class = interface_var->GetOperandAs<spv::StorageClass>(2);
+    switch (storage_class) {
+      case spv::StorageClass::PushConstant: {
+        if (has_push_constant) {
+          return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
+                 << _.VkErrorID(6673)
+                 << "Entry-point has more than one variable with the "
+                    "PushConstant storage class in the interface";
+        }
+        has_push_constant = true;
+        break;
+      }
+      case spv::StorageClass::IncomingRayPayloadKHR: {
+        if (has_ray_payload) {
+          return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
+                 << _.VkErrorID(4700)
+                 << "Entry-point has more than one variable with the "
+                    "IncomingRayPayloadKHR storage class in the interface";
+        }
+        has_ray_payload = true;
+        break;
+      }
+      case spv::StorageClass::HitAttributeKHR: {
+        if (has_hit_attribute) {
+          return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
+                 << _.VkErrorID(4702)
+                 << "Entry-point has more than one variable with the "
+                    "HitAttributeKHR storage class in the interface";
+        }
+        has_hit_attribute = true;
+        break;
+      }
+      case spv::StorageClass::IncomingCallableDataKHR: {
+        if (has_callable_data) {
+          return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
+                 << _.VkErrorID(4706)
+                 << "Entry-point has more than one variable with the "
+                    "IncomingCallableDataKHR storage class in the interface";
+        }
+        has_callable_data = true;
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  return SPV_SUCCESS;
+}
+
 }  // namespace
 
 spv_result_t ValidateInterfaces(ValidationState_t& _) {
@@ -547,12 +609,15 @@
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
     for (auto& inst : _.ordered_instructions()) {
-      if (inst.opcode() == SpvOpEntryPoint) {
+      if (inst.opcode() == spv::Op::OpEntryPoint) {
         if (auto error = ValidateLocations(_, &inst)) {
           return error;
         }
+        if (auto error = ValidateStorageClass(_, &inst)) {
+          return error;
+        }
       }
-      if (inst.opcode() == SpvOpTypeVoid) break;
+      if (inst.opcode() == spv::Op::OpTypeVoid) break;
     }
   }
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_layout.cpp b/third_party/SPIRV-Tools/source/val/validate_layout.cpp
index 6f95135..238dd9b 100644
--- a/third_party/SPIRV-Tools/source/val/validate_layout.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_layout.cpp
@@ -35,9 +35,9 @@
 // is part of the current layout section. If it is not then the next sections is
 // checked.
 spv_result_t ModuleScopedInstructions(ValidationState_t& _,
-                                      const Instruction* inst, SpvOp opcode) {
+                                      const Instruction* inst, spv::Op opcode) {
   switch (opcode) {
-    case SpvOpExtInst:
+    case spv::Op::OpExtInst:
       if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
         const uint32_t ext_inst_index = inst->word(4);
         bool local_debug_info = false;
@@ -131,7 +131,7 @@
 
     switch (_.current_layout_section()) {
       case kLayoutMemoryModel:
-        if (opcode != SpvOpMemoryModel) {
+        if (opcode != spv::Op::OpMemoryModel) {
           return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
                  << spvOpcodeString(opcode)
                  << " cannot appear before the memory model instruction";
@@ -154,7 +154,8 @@
 // inside of another function. This stage ends when the first label is
 // encountered inside of a function.
 spv_result_t FunctionScopedInstructions(ValidationState_t& _,
-                                        const Instruction* inst, SpvOp opcode) {
+                                        const Instruction* inst,
+                                        spv::Op opcode) {
   // Make sure we advance into the function definitions when we hit
   // non-function declaration instructions.
   if (_.current_layout_section() == kLayoutFunctionDeclarations &&
@@ -171,12 +172,12 @@
 
   if (_.IsOpcodeInCurrentLayoutSection(opcode)) {
     switch (opcode) {
-      case SpvOpFunction: {
+      case spv::Op::OpFunction: {
         if (_.in_function_body()) {
           return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
                  << "Cannot declare a function in a function body";
         }
-        auto control_mask = inst->GetOperandAs<SpvFunctionControlMask>(2);
+        auto control_mask = inst->GetOperandAs<spv::FunctionControlMask>(2);
         if (auto error =
                 _.RegisterFunction(inst->id(), inst->type_id(), control_mask,
                                    inst->GetOperandAs<uint32_t>(3)))
@@ -188,7 +189,7 @@
         }
       } break;
 
-      case SpvOpFunctionParameter:
+      case spv::Op::OpFunctionParameter:
         if (_.in_function_body() == false) {
           return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
                  << "Function parameter instructions must be in a "
@@ -204,7 +205,7 @@
           return error;
         break;
 
-      case SpvOpFunctionEnd:
+      case spv::Op::OpFunctionEnd:
         if (_.in_function_body() == false) {
           return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
                  << "Function end instructions must be in a function body";
@@ -227,10 +228,10 @@
         if (auto error = _.RegisterFunctionEnd()) return error;
         break;
 
-      case SpvOpLine:
-      case SpvOpNoLine:
+      case spv::Op::OpLine:
+      case spv::Op::OpNoLine:
         break;
-      case SpvOpLabel:
+      case spv::Op::OpLabel:
         // If the label is encountered then the current function is a
         // definition so set the function to a declaration and update the
         // module section
@@ -244,7 +245,7 @@
         }
         break;
 
-      case SpvOpExtInst:
+      case spv::Op::OpExtInst:
         if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
           const uint32_t ext_inst_index = inst->word(4);
           bool local_debug_info = false;
@@ -356,7 +357,7 @@
 // NOTE: This function does not handle CFG related validation
 // Performs logical layout validation. See Section 2.4
 spv_result_t ModuleLayoutPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   switch (_.current_layout_section()) {
     case kLayoutCapabilities:
diff --git a/third_party/SPIRV-Tools/source/val/validate_logicals.cpp b/third_party/SPIRV-Tools/source/val/validate_logicals.cpp
index ec1e207..dd66ce9 100644
--- a/third_party/SPIRV-Tools/source/val/validate_logicals.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_logicals.cpp
@@ -26,12 +26,12 @@
 
 // Validates correctness of logical instructions.
 spv_result_t LogicalsPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpAny:
-    case SpvOpAll: {
+    case spv::Op::OpAny:
+    case spv::Op::OpAll: {
       if (!_.IsBoolScalarType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar type as Result Type: "
@@ -46,11 +46,11 @@
       break;
     }
 
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet: {
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
@@ -72,21 +72,21 @@
       break;
     }
 
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered: {
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
@@ -113,10 +113,10 @@
       break;
     }
 
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd: {
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
@@ -131,7 +131,7 @@
       break;
     }
 
-    case SpvOpLogicalNot: {
+    case spv::Op::OpLogicalNot: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
@@ -145,7 +145,7 @@
       break;
     }
 
-    case SpvOpSelect: {
+    case spv::Op::OpSelect: {
       uint32_t dimension = 1;
       {
         const Instruction* type_inst = _.FindDef(result_type);
@@ -159,10 +159,10 @@
                  << " type as Result Type: " << spvOpcodeString(opcode);
         };
 
-        const SpvOp type_opcode = type_inst->opcode();
+        const spv::Op type_opcode = type_inst->opcode();
         switch (type_opcode) {
-          case SpvOpTypePointer: {
-            if (_.addressing_model() == SpvAddressingModelLogical &&
+          case spv::Op::OpTypePointer: {
+            if (_.addressing_model() == spv::AddressingModel::Logical &&
                 !_.features().variable_pointers)
               return _.diag(SPV_ERROR_INVALID_DATA, inst)
                      << "Using pointers with OpSelect requires capability "
@@ -170,31 +170,31 @@
             break;
           }
 
-          case SpvOpTypeSampledImage:
-          case SpvOpTypeImage:
-          case SpvOpTypeSampler: {
-            if (!_.HasCapability(SpvCapabilityBindlessTextureNV))
+          case spv::Op::OpTypeSampledImage:
+          case spv::Op::OpTypeImage:
+          case spv::Op::OpTypeSampler: {
+            if (!_.HasCapability(spv::Capability::BindlessTextureNV))
               return _.diag(SPV_ERROR_INVALID_DATA, inst)
                      << "Using image/sampler with OpSelect requires capability "
                      << "BindlessTextureNV";
             break;
           }
 
-          case SpvOpTypeVector: {
+          case spv::Op::OpTypeVector: {
             dimension = type_inst->word(3);
             break;
           }
 
-          case SpvOpTypeBool:
-          case SpvOpTypeInt:
-          case SpvOpTypeFloat: {
+          case spv::Op::OpTypeBool:
+          case spv::Op::OpTypeInt:
+          case spv::Op::OpTypeFloat: {
             break;
           }
 
           // Not RuntimeArray because of other rules.
-          case SpvOpTypeArray:
-          case SpvOpTypeMatrix:
-          case SpvOpTypeStruct: {
+          case spv::Op::OpTypeArray:
+          case spv::Op::OpTypeMatrix:
+          case spv::Op::OpTypeStruct: {
             if (!composites) return fail();
             break;
           }
@@ -235,16 +235,16 @@
       }
     }
 
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSGreaterThan:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpSLessThan:
-    case SpvOpSLessThanEqual: {
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpSLessThanEqual: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
diff --git a/third_party/SPIRV-Tools/source/val/validate_memory.cpp b/third_party/SPIRV-Tools/source/val/validate_memory.cpp
index 425a8d3..80c9e87 100644
--- a/third_party/SPIRV-Tools/source/val/validate_memory.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_memory.cpp
@@ -39,13 +39,13 @@
                                  const std::set<Decoration>&);
 
 bool IsAllowedTypeOrArrayOfSame(ValidationState_t& _, const Instruction* type,
-                                std::initializer_list<uint32_t> allowed) {
+                                std::initializer_list<spv::Op> allowed) {
   if (std::find(allowed.begin(), allowed.end(), type->opcode()) !=
       allowed.end()) {
     return true;
   }
-  if (type->opcode() == SpvOpTypeArray ||
-      type->opcode() == SpvOpTypeRuntimeArray) {
+  if (type->opcode() == spv::Op::OpTypeArray ||
+      type->opcode() == spv::Op::OpTypeRuntimeArray) {
     auto elem_type = _.FindDef(type->word(2));
     return std::find(allowed.begin(), allowed.end(), elem_type->opcode()) !=
            allowed.end();
@@ -57,10 +57,10 @@
 // validator can tell, have the exact same data layout.
 bool AreLayoutCompatibleStructs(ValidationState_t& _, const Instruction* type1,
                                 const Instruction* type2) {
-  if (type1->opcode() != SpvOpTypeStruct) {
+  if (type1->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
-  if (type2->opcode() != SpvOpTypeStruct) {
+  if (type2->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
@@ -74,9 +74,9 @@
 // be OpTypeStruct instructions.
 bool HaveLayoutCompatibleMembers(ValidationState_t& _, const Instruction* type1,
                                  const Instruction* type2) {
-  assert(type1->opcode() == SpvOpTypeStruct &&
+  assert(type1->opcode() == spv::Op::OpTypeStruct &&
          "type1 must be an OpTypeStruct instruction.");
-  assert(type2->opcode() == SpvOpTypeStruct &&
+  assert(type2->opcode() == spv::Op::OpTypeStruct &&
          "type2 must be an OpTypeStruct instruction.");
   const auto& type1_operands = type1->operands();
   const auto& type2_operands = type2->operands();
@@ -101,9 +101,9 @@
 // OpTypeStruct instructions.
 bool HaveSameLayoutDecorations(ValidationState_t& _, const Instruction* type1,
                                const Instruction* type2) {
-  assert(type1->opcode() == SpvOpTypeStruct &&
+  assert(type1->opcode() == spv::Op::OpTypeStruct &&
          "type1 must be an OpTypeStruct instruction.");
-  assert(type2->opcode() == SpvOpTypeStruct &&
+  assert(type2->opcode() == spv::Op::OpTypeStruct &&
          "type2 must be an OpTypeStruct instruction.");
   const std::set<Decoration>& type1_decorations = _.id_decorations(type1->id());
   const std::set<Decoration>& type2_decorations = _.id_decorations(type2->id());
@@ -130,11 +130,11 @@
     // type1_decoration.  Therefore, it cannot lead to a conflict.
     for (const Decoration& decoration : type1_decorations) {
       switch (decoration.dec_type()) {
-        case SpvDecorationOffset: {
+        case spv::Decoration::Offset: {
           // Since these affect the layout of the struct, they must be present
           // in both structs.
           auto compare = [&decoration](const Decoration& rhs) {
-            if (rhs.dec_type() != SpvDecorationOffset) return false;
+            if (rhs.dec_type() != spv::Decoration::Offset) return false;
             return decoration.struct_member_index() ==
                    rhs.struct_member_index();
           };
@@ -163,7 +163,7 @@
                          bool skip_builtin) {
   if (skip_builtin) {
     for (const Decoration& decoration : _.id_decorations(storage->id())) {
-      if (decoration.dec_type() == SpvDecorationBuiltIn) return false;
+      if (decoration.dec_type() == spv::Decoration::BuiltIn) return false;
     }
   }
 
@@ -172,16 +172,16 @@
   Instruction* elem_type;
 
   switch (storage->opcode()) {
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       return true;
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       elem_type_id = storage->GetOperandAs<uint32_t>(elem_type_index);
       elem_type = _.FindDef(elem_type_id);
       return ContainsInvalidBool(_, elem_type, skip_builtin);
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       for (size_t member_type_index = 1;
            member_type_index < storage->operands().size();
            ++member_type_index) {
@@ -203,14 +203,14 @@
   Instruction* elem_type;
 
   switch (storage->opcode()) {
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       return true;
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       elem_type_id = storage->GetOperandAs<uint32_t>(elem_type_index);
       elem_type = _.FindDef(elem_type_id);
       return ContainsCooperativeMatrix(_, elem_type);
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       for (size_t member_type_index = 1;
            member_type_index < storage->operands().size();
            ++member_type_index) {
@@ -226,33 +226,33 @@
   return false;
 }
 
-std::pair<SpvStorageClass, SpvStorageClass> GetStorageClass(
+std::pair<spv::StorageClass, spv::StorageClass> GetStorageClass(
     ValidationState_t& _, const Instruction* inst) {
-  SpvStorageClass dst_sc = SpvStorageClassMax;
-  SpvStorageClass src_sc = SpvStorageClassMax;
+  spv::StorageClass dst_sc = spv::StorageClass::Max;
+  spv::StorageClass src_sc = spv::StorageClass::Max;
   switch (inst->opcode()) {
-    case SpvOpCooperativeMatrixLoadNV:
-    case SpvOpLoad: {
+    case spv::Op::OpCooperativeMatrixLoadNV:
+    case spv::Op::OpLoad: {
       auto load_pointer = _.FindDef(inst->GetOperandAs<uint32_t>(2));
       auto load_pointer_type = _.FindDef(load_pointer->type_id());
-      dst_sc = load_pointer_type->GetOperandAs<SpvStorageClass>(1);
+      dst_sc = load_pointer_type->GetOperandAs<spv::StorageClass>(1);
       break;
     }
-    case SpvOpCooperativeMatrixStoreNV:
-    case SpvOpStore: {
+    case spv::Op::OpCooperativeMatrixStoreNV:
+    case spv::Op::OpStore: {
       auto store_pointer = _.FindDef(inst->GetOperandAs<uint32_t>(0));
       auto store_pointer_type = _.FindDef(store_pointer->type_id());
-      dst_sc = store_pointer_type->GetOperandAs<SpvStorageClass>(1);
+      dst_sc = store_pointer_type->GetOperandAs<spv::StorageClass>(1);
       break;
     }
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized: {
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized: {
       auto dst = _.FindDef(inst->GetOperandAs<uint32_t>(0));
       auto dst_type = _.FindDef(dst->type_id());
-      dst_sc = dst_type->GetOperandAs<SpvStorageClass>(1);
+      dst_sc = dst_type->GetOperandAs<spv::StorageClass>(1);
       auto src = _.FindDef(inst->GetOperandAs<uint32_t>(1));
       auto src_type = _.FindDef(src->type_id());
-      src_sc = src_type->GetOperandAs<SpvStorageClass>(1);
+      src_sc = src_type->GetOperandAs<spv::StorageClass>(1);
       break;
     }
     default:
@@ -266,9 +266,9 @@
 // argument and its implied operands.
 int MemoryAccessNumWords(uint32_t mask) {
   int result = 1;  // Count the mask
-  if (mask & SpvMemoryAccessAlignedMask) ++result;
-  if (mask & SpvMemoryAccessMakePointerAvailableKHRMask) ++result;
-  if (mask & SpvMemoryAccessMakePointerVisibleKHRMask) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::Aligned)) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR)) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR)) ++result;
   return result;
 }
 
@@ -279,8 +279,8 @@
 // OpCooperativeMatrixStoreNV.
 uint32_t GetMakeAvailableScope(const Instruction* inst, uint32_t mask,
                                uint32_t mask_index) {
-  assert(mask & SpvMemoryAccessMakePointerAvailableKHRMask);
-  uint32_t this_bit = uint32_t(SpvMemoryAccessMakePointerAvailableKHRMask);
+  assert(mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR));
+  uint32_t this_bit = uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR);
   uint32_t index =
       mask_index - 1 + MemoryAccessNumWords(mask & (this_bit | (this_bit - 1)));
   return inst->GetOperandAs<uint32_t>(index);
@@ -291,8 +291,8 @@
 // OpCooperativeMatrixStoreNV.
 uint32_t GetMakeVisibleScope(const Instruction* inst, uint32_t mask,
                              uint32_t mask_index) {
-  assert(mask & SpvMemoryAccessMakePointerVisibleKHRMask);
-  uint32_t this_bit = uint32_t(SpvMemoryAccessMakePointerVisibleKHRMask);
+  assert(mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR));
+  uint32_t this_bit = uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR);
   uint32_t index =
       mask_index - 1 + MemoryAccessNumWords(mask & (this_bit | (this_bit - 1)));
   return inst->GetOperandAs<uint32_t>(index);
@@ -303,19 +303,19 @@
        ++member_index) {
     const auto member_id = inst->GetOperandAs<uint32_t>(member_index);
     const auto member_type = _.FindDef(member_id);
-    if (member_type->opcode() == SpvOpTypeRuntimeArray) return true;
+    if (member_type->opcode() == spv::Op::OpTypeRuntimeArray) return true;
   }
   return false;
 }
 
 spv_result_t CheckMemoryAccess(ValidationState_t& _, const Instruction* inst,
                                uint32_t index) {
-  SpvStorageClass dst_sc, src_sc;
+  spv::StorageClass dst_sc, src_sc;
   std::tie(dst_sc, src_sc) = GetStorageClass(_, inst);
   if (inst->operands().size() <= index) {
     // Cases where lack of some operand is invalid
-    if (src_sc == SpvStorageClassPhysicalStorageBuffer ||
-        dst_sc == SpvStorageClassPhysicalStorageBuffer) {
+    if (src_sc == spv::StorageClass::PhysicalStorageBuffer ||
+        dst_sc == spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << _.VkErrorID(4708)
              << "Memory accesses with PhysicalStorageBuffer must use Aligned.";
@@ -324,14 +324,14 @@
   }
 
   const uint32_t mask = inst->GetOperandAs<uint32_t>(index);
-  if (mask & SpvMemoryAccessMakePointerAvailableKHRMask) {
-    if (inst->opcode() == SpvOpLoad ||
-        inst->opcode() == SpvOpCooperativeMatrixLoadNV) {
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR)) {
+    if (inst->opcode() == spv::Op::OpLoad ||
+        inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "MakePointerAvailableKHR cannot be used with OpLoad.";
     }
 
-    if (!(mask & SpvMemoryAccessNonPrivatePointerKHRMask)) {
+    if (!(mask & uint32_t(spv::MemoryAccessMask::NonPrivatePointerKHR))) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "NonPrivatePointerKHR must be specified if "
                 "MakePointerAvailableKHR is specified.";
@@ -343,14 +343,14 @@
       return error;
   }
 
-  if (mask & SpvMemoryAccessMakePointerVisibleKHRMask) {
-    if (inst->opcode() == SpvOpStore ||
-        inst->opcode() == SpvOpCooperativeMatrixStoreNV) {
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR)) {
+    if (inst->opcode() == spv::Op::OpStore ||
+        inst->opcode() == spv::Op::OpCooperativeMatrixStoreNV) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "MakePointerVisibleKHR cannot be used with OpStore.";
     }
 
-    if (!(mask & SpvMemoryAccessNonPrivatePointerKHRMask)) {
+    if (!(mask & uint32_t(spv::MemoryAccessMask::NonPrivatePointerKHR))) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "NonPrivatePointerKHR must be specified if "
              << "MakePointerVisibleKHR is specified.";
@@ -361,24 +361,27 @@
     if (auto error = ValidateMemoryScope(_, inst, visible_scope)) return error;
   }
 
-  if (mask & SpvMemoryAccessNonPrivatePointerKHRMask) {
-    if (dst_sc != SpvStorageClassUniform &&
-        dst_sc != SpvStorageClassWorkgroup &&
-        dst_sc != SpvStorageClassCrossWorkgroup &&
-        dst_sc != SpvStorageClassGeneric && dst_sc != SpvStorageClassImage &&
-        dst_sc != SpvStorageClassStorageBuffer &&
-        dst_sc != SpvStorageClassPhysicalStorageBuffer) {
+  if (mask & uint32_t(spv::MemoryAccessMask::NonPrivatePointerKHR)) {
+    if (dst_sc != spv::StorageClass::Uniform &&
+        dst_sc != spv::StorageClass::Workgroup &&
+        dst_sc != spv::StorageClass::CrossWorkgroup &&
+        dst_sc != spv::StorageClass::Generic &&
+        dst_sc != spv::StorageClass::Image &&
+        dst_sc != spv::StorageClass::StorageBuffer &&
+        dst_sc != spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "NonPrivatePointerKHR requires a pointer in Uniform, "
              << "Workgroup, CrossWorkgroup, Generic, Image or StorageBuffer "
              << "storage classes.";
     }
-    if (src_sc != SpvStorageClassMax && src_sc != SpvStorageClassUniform &&
-        src_sc != SpvStorageClassWorkgroup &&
-        src_sc != SpvStorageClassCrossWorkgroup &&
-        src_sc != SpvStorageClassGeneric && src_sc != SpvStorageClassImage &&
-        src_sc != SpvStorageClassStorageBuffer &&
-        src_sc != SpvStorageClassPhysicalStorageBuffer) {
+    if (src_sc != spv::StorageClass::Max &&
+        src_sc != spv::StorageClass::Uniform &&
+        src_sc != spv::StorageClass::Workgroup &&
+        src_sc != spv::StorageClass::CrossWorkgroup &&
+        src_sc != spv::StorageClass::Generic &&
+        src_sc != spv::StorageClass::Image &&
+        src_sc != spv::StorageClass::StorageBuffer &&
+        src_sc != spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "NonPrivatePointerKHR requires a pointer in Uniform, "
              << "Workgroup, CrossWorkgroup, Generic, Image or StorageBuffer "
@@ -386,9 +389,9 @@
     }
   }
 
-  if (!(mask & SpvMemoryAccessAlignedMask)) {
-    if (src_sc == SpvStorageClassPhysicalStorageBuffer ||
-        dst_sc == SpvStorageClassPhysicalStorageBuffer) {
+  if (!(mask & uint32_t(spv::MemoryAccessMask::Aligned))) {
+    if (src_sc == spv::StorageClass::PhysicalStorageBuffer ||
+        dst_sc == spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << _.VkErrorID(4708)
              << "Memory accesses with PhysicalStorageBuffer must use Aligned.";
@@ -400,10 +403,10 @@
 
 spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
   auto result_type = _.FindDef(inst->type_id());
-  if (!result_type || result_type->opcode() != SpvOpTypePointer) {
+  if (!result_type || result_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpVariable Result Type <id> '" << _.getIdName(inst->type_id())
-           << "' is not a pointer type.";
+           << "OpVariable Result Type <id> " << _.getIdName(inst->type_id())
+           << " is not a pointer type.";
   }
 
   const auto type_index = 2;
@@ -416,15 +419,15 @@
     const auto initializer_id = inst->GetOperandAs<uint32_t>(initializer_index);
     const auto initializer = _.FindDef(initializer_id);
     const auto is_module_scope_var =
-        initializer && (initializer->opcode() == SpvOpVariable) &&
-        (initializer->GetOperandAs<SpvStorageClass>(storage_class_index) !=
-         SpvStorageClassFunction);
+        initializer && (initializer->opcode() == spv::Op::OpVariable) &&
+        (initializer->GetOperandAs<spv::StorageClass>(storage_class_index) !=
+         spv::StorageClass::Function);
     const auto is_constant =
         initializer && spvOpcodeIsConstant(initializer->opcode());
     if (!initializer || !(is_constant || is_module_scope_var)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpVariable Initializer <id> '" << _.getIdName(initializer_id)
-             << "' is not a constant or module-scope variable.";
+             << "OpVariable Initializer <id> " << _.getIdName(initializer_id)
+             << " is not a constant or module-scope variable.";
     }
     if (initializer->type_id() != value_id) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
@@ -433,33 +436,47 @@
     }
   }
 
-  auto storage_class = inst->GetOperandAs<SpvStorageClass>(storage_class_index);
-  if (storage_class != SpvStorageClassWorkgroup &&
-      storage_class != SpvStorageClassCrossWorkgroup &&
-      storage_class != SpvStorageClassPrivate &&
-      storage_class != SpvStorageClassFunction &&
-      storage_class != SpvStorageClassRayPayloadNV &&
-      storage_class != SpvStorageClassIncomingRayPayloadNV &&
-      storage_class != SpvStorageClassHitAttributeNV &&
-      storage_class != SpvStorageClassCallableDataNV &&
-      storage_class != SpvStorageClassIncomingCallableDataNV) {
-    bool storage_input_or_output = storage_class == SpvStorageClassInput ||
-                                   storage_class == SpvStorageClassOutput;
+  auto storage_class =
+      inst->GetOperandAs<spv::StorageClass>(storage_class_index);
+  if (storage_class != spv::StorageClass::Workgroup &&
+      storage_class != spv::StorageClass::CrossWorkgroup &&
+      storage_class != spv::StorageClass::Private &&
+      storage_class != spv::StorageClass::Function &&
+      storage_class != spv::StorageClass::RayPayloadKHR &&
+      storage_class != spv::StorageClass::IncomingRayPayloadKHR &&
+      storage_class != spv::StorageClass::HitAttributeKHR &&
+      storage_class != spv::StorageClass::CallableDataKHR &&
+      storage_class != spv::StorageClass::IncomingCallableDataKHR &&
+      storage_class != spv::StorageClass::TaskPayloadWorkgroupEXT) {
+    bool storage_input_or_output = storage_class == spv::StorageClass::Input ||
+                                   storage_class == spv::StorageClass::Output;
     bool builtin = false;
     if (storage_input_or_output) {
       for (const Decoration& decoration : _.id_decorations(inst->id())) {
-        if (decoration.dec_type() == SpvDecorationBuiltIn) {
+        if (decoration.dec_type() == spv::Decoration::BuiltIn) {
           builtin = true;
           break;
         }
       }
     }
-    if (!(storage_input_or_output && builtin) &&
+    if (!builtin &&
         ContainsInvalidBool(_, value_type, storage_input_or_output)) {
-      return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "If OpTypeBool is stored in conjunction with OpVariable, it "
-             << "can only be used with non-externally visible shader Storage "
-             << "Classes: Workgroup, CrossWorkgroup, Private, and Function";
+      if (storage_input_or_output) {
+        return _.diag(SPV_ERROR_INVALID_ID, inst)
+               << _.VkErrorID(7290)
+               << "If OpTypeBool is stored in conjunction with OpVariable "
+                  "using Input or Output Storage Classes it requires a BuiltIn "
+                  "decoration";
+
+      } else {
+        return _.diag(SPV_ERROR_INVALID_ID, inst)
+               << "If OpTypeBool is stored in conjunction with OpVariable, it "
+                  "can only be used with non-externally visible shader Storage "
+                  "Classes: Workgroup, CrossWorkgroup, Private, Function, "
+                  "Input, Output, RayPayloadKHR, IncomingRayPayloadKHR, "
+                  "HitAttributeKHR, CallableDataKHR, or "
+                  "IncomingCallableDataKHR";
+      }
     }
   }
 
@@ -469,18 +486,18 @@
            << "Invalid storage class for target environment";
   }
 
-  if (storage_class == SpvStorageClassGeneric) {
+  if (storage_class == spv::StorageClass::Generic) {
     return _.diag(SPV_ERROR_INVALID_BINARY, inst)
            << "OpVariable storage class cannot be Generic";
   }
 
-  if (inst->function() && storage_class != SpvStorageClassFunction) {
+  if (inst->function() && storage_class != spv::StorageClass::Function) {
     return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
            << "Variables must have a function[7] storage class inside"
               " of a function";
   }
 
-  if (!inst->function() && storage_class == SpvStorageClassFunction) {
+  if (!inst->function() && storage_class == spv::StorageClass::Function) {
     return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
            << "Variables can not have a function[7] storage class "
               "outside of a function";
@@ -490,7 +507,7 @@
   // storage class.
   const auto result_storage_class_index = 1;
   const auto result_storage_class =
-      result_type->GetOperandAs<uint32_t>(result_storage_class_index);
+      result_type->GetOperandAs<spv::StorageClass>(result_storage_class_index);
   if (storage_class != result_storage_class) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "From SPIR-V spec, section 3.32.8 on OpVariable:\n"
@@ -500,16 +517,16 @@
 
   // Variable pointer related restrictions.
   const auto pointee = _.FindDef(result_type->word(3));
-  if (_.addressing_model() == SpvAddressingModelLogical &&
+  if (_.addressing_model() == spv::AddressingModel::Logical &&
       !_.options()->relax_logical_pointer) {
     // VariablePointersStorageBuffer is implied by VariablePointers.
-    if (pointee->opcode() == SpvOpTypePointer) {
-      if (!_.HasCapability(SpvCapabilityVariablePointersStorageBuffer)) {
+    if (pointee->opcode() == spv::Op::OpTypePointer) {
+      if (!_.HasCapability(spv::Capability::VariablePointersStorageBuffer)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "In Logical addressing, variables may not allocate a pointer "
                << "type";
-      } else if (storage_class != SpvStorageClassFunction &&
-                 storage_class != SpvStorageClassPrivate) {
+      } else if (storage_class != spv::StorageClass::Function &&
+                 storage_class != spv::StorageClass::Private) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "In Logical addressing with variable pointers, variables "
                << "that allocate pointers must be in Function or Private "
@@ -521,11 +538,11 @@
   if (spvIsVulkanEnv(_.context()->target_env)) {
     // Vulkan Push Constant Interface section: Check type of PushConstant
     // variables.
-    if (storage_class == SpvStorageClassPushConstant) {
-      if (pointee->opcode() != SpvOpTypeStruct) {
+    if (storage_class == spv::StorageClass::PushConstant) {
+      if (pointee->opcode() != spv::Op::OpTypeStruct) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << _.VkErrorID(6808) << "PushConstant OpVariable <id> '"
-               << _.getIdName(inst->id()) << "' has illegal type.\n"
+               << _.VkErrorID(6808) << "PushConstant OpVariable <id> "
+               << _.getIdName(inst->id()) << " has illegal type.\n"
                << "From Vulkan spec, Push Constant Interface section:\n"
                << "Such variables must be typed as OpTypeStruct";
       }
@@ -533,14 +550,15 @@
 
     // Vulkan Descriptor Set Interface: Check type of UniformConstant and
     // Uniform variables.
-    if (storage_class == SpvStorageClassUniformConstant) {
+    if (storage_class == spv::StorageClass::UniformConstant) {
       if (!IsAllowedTypeOrArrayOfSame(
               _, pointee,
-              {SpvOpTypeImage, SpvOpTypeSampler, SpvOpTypeSampledImage,
-               SpvOpTypeAccelerationStructureKHR})) {
+              {spv::Op::OpTypeImage, spv::Op::OpTypeSampler,
+               spv::Op::OpTypeSampledImage,
+               spv::Op::OpTypeAccelerationStructureKHR})) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << _.VkErrorID(4655) << "UniformConstant OpVariable <id> '"
-               << _.getIdName(inst->id()) << "' has illegal type.\n"
+               << _.VkErrorID(4655) << "UniformConstant OpVariable <id> "
+               << _.getIdName(inst->id()) << " has illegal type.\n"
                << "Variables identified with the UniformConstant storage class "
                << "are used only as handles to refer to opaque resources. Such "
                << "variables must be typed as OpTypeImage, OpTypeSampler, "
@@ -549,11 +567,11 @@
       }
     }
 
-    if (storage_class == SpvStorageClassUniform) {
-      if (!IsAllowedTypeOrArrayOfSame(_, pointee, {SpvOpTypeStruct})) {
+    if (storage_class == spv::StorageClass::Uniform) {
+      if (!IsAllowedTypeOrArrayOfSame(_, pointee, {spv::Op::OpTypeStruct})) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << _.VkErrorID(6807) << "Uniform OpVariable <id> '"
-               << _.getIdName(inst->id()) << "' has illegal type.\n"
+               << _.VkErrorID(6807) << "Uniform OpVariable <id> "
+               << _.getIdName(inst->id()) << " has illegal type.\n"
                << "From Vulkan spec:\n"
                << "Variables identified with the Uniform storage class are "
                << "used to access transparent buffer backed resources. Such "
@@ -562,11 +580,11 @@
       }
     }
 
-    if (storage_class == SpvStorageClassStorageBuffer) {
-      if (!IsAllowedTypeOrArrayOfSame(_, pointee, {SpvOpTypeStruct})) {
+    if (storage_class == spv::StorageClass::StorageBuffer) {
+      if (!IsAllowedTypeOrArrayOfSame(_, pointee, {spv::Op::OpTypeStruct})) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << _.VkErrorID(6807) << "StorageBuffer OpVariable <id> '"
-               << _.getIdName(inst->id()) << "' has illegal type.\n"
+               << _.VkErrorID(6807) << "StorageBuffer OpVariable <id> "
+               << _.getIdName(inst->id()) << " has illegal type.\n"
                << "From Vulkan spec:\n"
                << "Variables identified with the StorageBuffer storage class "
                   "are used to access transparent buffer backed resources. "
@@ -576,9 +594,9 @@
     }
 
     // Check for invalid use of Invariant
-    if (storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
-      if (_.HasDecoration(inst->id(), SpvDecorationInvariant)) {
+    if (storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
+      if (_.HasDecoration(inst->id(), spv::Decoration::Invariant)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << _.VkErrorID(4677)
                << "Variable decorated with Invariant must only be identified "
@@ -586,8 +604,8 @@
                   "environment.";
       }
       // Need to check if only the members in a struct are decorated
-      if (value_type && value_type->opcode() == SpvOpTypeStruct) {
-        if (_.HasDecoration(value_id, SpvDecorationInvariant)) {
+      if (value_type && value_type->opcode() == spv::Op::OpTypeStruct) {
+        if (_.HasDecoration(value_id, spv::Decoration::Invariant)) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << _.VkErrorID(4677)
                  << "Variable struct member decorated with Invariant must only "
@@ -599,24 +617,24 @@
 
     // Initializers in Vulkan are only allowed in some storage clases
     if (inst->operands().size() > 3) {
-      if (storage_class == SpvStorageClassWorkgroup) {
+      if (storage_class == spv::StorageClass::Workgroup) {
         auto init_id = inst->GetOperandAs<uint32_t>(3);
         auto init = _.FindDef(init_id);
-        if (init->opcode() != SpvOpConstantNull) {
+        if (init->opcode() != spv::Op::OpConstantNull) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << _.VkErrorID(4734) << "OpVariable, <id> '"
+                 << _.VkErrorID(4734) << "OpVariable, <id> "
                  << _.getIdName(inst->id())
-                 << "', initializers are limited to OpConstantNull in "
+                 << ", initializers are limited to OpConstantNull in "
                     "Workgroup "
                     "storage class";
         }
-      } else if (storage_class != SpvStorageClassOutput &&
-                 storage_class != SpvStorageClassPrivate &&
-                 storage_class != SpvStorageClassFunction) {
+      } else if (storage_class != spv::StorageClass::Output &&
+                 storage_class != spv::StorageClass::Private &&
+                 storage_class != spv::StorageClass::Function) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << _.VkErrorID(4651) << "OpVariable, <id> '"
+               << _.VkErrorID(4651) << "OpVariable, <id> "
                << _.getIdName(inst->id())
-               << "', has a disallowed initializer & storage class "
+               << ", has a disallowed initializer & storage class "
                << "combination.\n"
                << "From " << spvLogStringForEnv(_.context()->target_env)
                << " spec:\n"
@@ -627,23 +645,36 @@
     }
   }
 
-  if (storage_class == SpvStorageClassPhysicalStorageBuffer) {
+  if (inst->operands().size() > 3) {
+    if (storage_class == spv::StorageClass::TaskPayloadWorkgroupEXT) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "OpVariable, <id> " << _.getIdName(inst->id())
+             << ", initializer are not allowed for TaskPayloadWorkgroupEXT";
+    }
+    if (storage_class == spv::StorageClass::Input) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "OpVariable, <id> " << _.getIdName(inst->id())
+             << ", initializer are not allowed for Input";
+    }
+  }
+
+  if (storage_class == spv::StorageClass::PhysicalStorageBuffer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "PhysicalStorageBuffer must not be used with OpVariable.";
   }
 
   auto pointee_base = pointee;
-  while (pointee_base->opcode() == SpvOpTypeArray) {
+  while (pointee_base->opcode() == spv::Op::OpTypeArray) {
     pointee_base = _.FindDef(pointee_base->GetOperandAs<uint32_t>(1u));
   }
-  if (pointee_base->opcode() == SpvOpTypePointer) {
-    if (pointee_base->GetOperandAs<uint32_t>(1u) ==
-        SpvStorageClassPhysicalStorageBuffer) {
+  if (pointee_base->opcode() == spv::Op::OpTypePointer) {
+    if (pointee_base->GetOperandAs<spv::StorageClass>(1u) ==
+        spv::StorageClass::PhysicalStorageBuffer) {
       // check for AliasedPointer/RestrictPointer
       bool foundAliased =
-          _.HasDecoration(inst->id(), SpvDecorationAliasedPointer);
+          _.HasDecoration(inst->id(), spv::Decoration::AliasedPointer);
       bool foundRestrict =
-          _.HasDecoration(inst->id(), SpvDecorationRestrictPointer);
+          _.HasDecoration(inst->id(), spv::Decoration::RestrictPointer);
       if (!foundAliased && !foundRestrict) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "OpVariable " << inst->id()
@@ -664,21 +695,21 @@
     // OpTypeRuntimeArray should only ever be in a container like OpTypeStruct,
     // so should never appear as a bare variable.
     // Unless the module has the RuntimeDescriptorArrayEXT capability.
-    if (value_type && value_type->opcode() == SpvOpTypeRuntimeArray) {
-      if (!_.HasCapability(SpvCapabilityRuntimeDescriptorArrayEXT)) {
+    if (value_type && value_type->opcode() == spv::Op::OpTypeRuntimeArray) {
+      if (!_.HasCapability(spv::Capability::RuntimeDescriptorArrayEXT)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << _.VkErrorID(4680) << "OpVariable, <id> '"
+               << _.VkErrorID(4680) << "OpVariable, <id> "
                << _.getIdName(inst->id())
-               << "', is attempting to create memory for an illegal type, "
+               << ", is attempting to create memory for an illegal type, "
                << "OpTypeRuntimeArray.\nFor Vulkan OpTypeRuntimeArray can only "
                << "appear as the final member of an OpTypeStruct, thus cannot "
                << "be instantiated via OpVariable";
       } else {
         // A bare variable OpTypeRuntimeArray is allowed in this context, but
         // still need to check the storage class.
-        if (storage_class != SpvStorageClassStorageBuffer &&
-            storage_class != SpvStorageClassUniform &&
-            storage_class != SpvStorageClassUniformConstant) {
+        if (storage_class != spv::StorageClass::StorageBuffer &&
+            storage_class != spv::StorageClass::Uniform &&
+            storage_class != spv::StorageClass::UniformConstant) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << _.VkErrorID(4680)
                  << "For Vulkan with RuntimeDescriptorArrayEXT, a variable "
@@ -692,11 +723,11 @@
     // must either have the storage class StorageBuffer and be decorated
     // with Block, or it must be in the Uniform storage class and be decorated
     // as BufferBlock.
-    if (value_type && value_type->opcode() == SpvOpTypeStruct) {
+    if (value_type && value_type->opcode() == spv::Op::OpTypeStruct) {
       if (DoesStructContainRTA(_, value_type)) {
-        if (storage_class == SpvStorageClassStorageBuffer ||
-            storage_class == SpvStorageClassPhysicalStorageBuffer) {
-          if (!_.HasDecoration(value_id, SpvDecorationBlock)) {
+        if (storage_class == spv::StorageClass::StorageBuffer ||
+            storage_class == spv::StorageClass::PhysicalStorageBuffer) {
+          if (!_.HasDecoration(value_id, spv::Decoration::Block)) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << _.VkErrorID(4680)
                    << "For Vulkan, an OpTypeStruct variable containing an "
@@ -704,8 +735,8 @@
                    << "has storage class StorageBuffer or "
                       "PhysicalStorageBuffer.";
           }
-        } else if (storage_class == SpvStorageClassUniform) {
-          if (!_.HasDecoration(value_id, SpvDecorationBufferBlock)) {
+        } else if (storage_class == spv::StorageClass::Uniform) {
+          if (!_.HasDecoration(value_id, spv::Decoration::BufferBlock)) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << _.VkErrorID(4680)
                    << "For Vulkan, an OpTypeStruct variable containing an "
@@ -724,8 +755,8 @@
   }
 
   // Cooperative matrix types can only be allocated in Function or Private
-  if ((storage_class != SpvStorageClassFunction &&
-       storage_class != SpvStorageClassPrivate) &&
+  if ((storage_class != spv::StorageClass::Function &&
+       storage_class != spv::StorageClass::Private) &&
       ContainsCooperativeMatrix(_, pointee)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Cooperative matrix types (or types containing them) can only be "
@@ -734,57 +765,59 @@
               "parameters";
   }
 
-  if (_.HasCapability(SpvCapabilityShader)) {
+  if (_.HasCapability(spv::Capability::Shader)) {
     // Don't allow variables containing 16-bit elements without the appropriate
     // capabilities.
-    if ((!_.HasCapability(SpvCapabilityInt16) &&
-         _.ContainsSizedIntOrFloatType(value_id, SpvOpTypeInt, 16)) ||
-        (!_.HasCapability(SpvCapabilityFloat16) &&
-         _.ContainsSizedIntOrFloatType(value_id, SpvOpTypeFloat, 16))) {
+    if ((!_.HasCapability(spv::Capability::Int16) &&
+         _.ContainsSizedIntOrFloatType(value_id, spv::Op::OpTypeInt, 16)) ||
+        (!_.HasCapability(spv::Capability::Float16) &&
+         _.ContainsSizedIntOrFloatType(value_id, spv::Op::OpTypeFloat, 16))) {
       auto underlying_type = value_type;
-      while (underlying_type->opcode() == SpvOpTypePointer) {
-        storage_class = underlying_type->GetOperandAs<SpvStorageClass>(1u);
+      while (underlying_type->opcode() == spv::Op::OpTypePointer) {
+        storage_class = underlying_type->GetOperandAs<spv::StorageClass>(1u);
         underlying_type =
             _.FindDef(underlying_type->GetOperandAs<uint32_t>(2u));
       }
       bool storage_class_ok = true;
       std::string sc_name = _.grammar().lookupOperandName(
-          SPV_OPERAND_TYPE_STORAGE_CLASS, storage_class);
+          SPV_OPERAND_TYPE_STORAGE_CLASS, uint32_t(storage_class));
       switch (storage_class) {
-        case SpvStorageClassStorageBuffer:
-        case SpvStorageClassPhysicalStorageBuffer:
-          if (!_.HasCapability(SpvCapabilityStorageBuffer16BitAccess)) {
+        case spv::StorageClass::StorageBuffer:
+        case spv::StorageClass::PhysicalStorageBuffer:
+          if (!_.HasCapability(spv::Capability::StorageBuffer16BitAccess)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassUniform:
+        case spv::StorageClass::Uniform:
           if (!_.HasCapability(
-                  SpvCapabilityUniformAndStorageBuffer16BitAccess)) {
-            if (underlying_type->opcode() == SpvOpTypeArray ||
-                underlying_type->opcode() == SpvOpTypeRuntimeArray) {
+                  spv::Capability::UniformAndStorageBuffer16BitAccess)) {
+            if (underlying_type->opcode() == spv::Op::OpTypeArray ||
+                underlying_type->opcode() == spv::Op::OpTypeRuntimeArray) {
               underlying_type =
                   _.FindDef(underlying_type->GetOperandAs<uint32_t>(1u));
             }
-            if (!_.HasCapability(SpvCapabilityStorageBuffer16BitAccess) ||
+            if (!_.HasCapability(spv::Capability::StorageBuffer16BitAccess) ||
                 !_.HasDecoration(underlying_type->id(),
-                                 SpvDecorationBufferBlock)) {
+                                 spv::Decoration::BufferBlock)) {
               storage_class_ok = false;
             }
           }
           break;
-        case SpvStorageClassPushConstant:
-          if (!_.HasCapability(SpvCapabilityStoragePushConstant16)) {
+        case spv::StorageClass::PushConstant:
+          if (!_.HasCapability(spv::Capability::StoragePushConstant16)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassInput:
-        case SpvStorageClassOutput:
-          if (!_.HasCapability(SpvCapabilityStorageInputOutput16)) {
+        case spv::StorageClass::Input:
+        case spv::StorageClass::Output:
+          if (!_.HasCapability(spv::Capability::StorageInputOutput16)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassWorkgroup:
-          if (!_.HasCapability(SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR)) {
+        case spv::StorageClass::Workgroup:
+          if (!_.HasCapability(
+                  spv::Capability::
+                      WorkgroupMemoryExplicitLayout16BitAccessKHR)) {
             storage_class_ok = false;
           }
           break;
@@ -801,46 +834,48 @@
     }
     // Don't allow variables containing 8-bit elements without the appropriate
     // capabilities.
-    if (!_.HasCapability(SpvCapabilityInt8) &&
-        _.ContainsSizedIntOrFloatType(value_id, SpvOpTypeInt, 8)) {
+    if (!_.HasCapability(spv::Capability::Int8) &&
+        _.ContainsSizedIntOrFloatType(value_id, spv::Op::OpTypeInt, 8)) {
       auto underlying_type = value_type;
-      while (underlying_type->opcode() == SpvOpTypePointer) {
-        storage_class = underlying_type->GetOperandAs<SpvStorageClass>(1u);
+      while (underlying_type->opcode() == spv::Op::OpTypePointer) {
+        storage_class = underlying_type->GetOperandAs<spv::StorageClass>(1u);
         underlying_type =
             _.FindDef(underlying_type->GetOperandAs<uint32_t>(2u));
       }
       bool storage_class_ok = true;
       std::string sc_name = _.grammar().lookupOperandName(
-          SPV_OPERAND_TYPE_STORAGE_CLASS, storage_class);
+          SPV_OPERAND_TYPE_STORAGE_CLASS, uint32_t(storage_class));
       switch (storage_class) {
-        case SpvStorageClassStorageBuffer:
-        case SpvStorageClassPhysicalStorageBuffer:
-          if (!_.HasCapability(SpvCapabilityStorageBuffer8BitAccess)) {
+        case spv::StorageClass::StorageBuffer:
+        case spv::StorageClass::PhysicalStorageBuffer:
+          if (!_.HasCapability(spv::Capability::StorageBuffer8BitAccess)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassUniform:
+        case spv::StorageClass::Uniform:
           if (!_.HasCapability(
-                  SpvCapabilityUniformAndStorageBuffer8BitAccess)) {
-            if (underlying_type->opcode() == SpvOpTypeArray ||
-                underlying_type->opcode() == SpvOpTypeRuntimeArray) {
+                  spv::Capability::UniformAndStorageBuffer8BitAccess)) {
+            if (underlying_type->opcode() == spv::Op::OpTypeArray ||
+                underlying_type->opcode() == spv::Op::OpTypeRuntimeArray) {
               underlying_type =
                   _.FindDef(underlying_type->GetOperandAs<uint32_t>(1u));
             }
-            if (!_.HasCapability(SpvCapabilityStorageBuffer8BitAccess) ||
+            if (!_.HasCapability(spv::Capability::StorageBuffer8BitAccess) ||
                 !_.HasDecoration(underlying_type->id(),
-                                 SpvDecorationBufferBlock)) {
+                                 spv::Decoration::BufferBlock)) {
               storage_class_ok = false;
             }
           }
           break;
-        case SpvStorageClassPushConstant:
-          if (!_.HasCapability(SpvCapabilityStoragePushConstant8)) {
+        case spv::StorageClass::PushConstant:
+          if (!_.HasCapability(spv::Capability::StoragePushConstant8)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassWorkgroup:
-          if (!_.HasCapability(SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR)) {
+        case spv::StorageClass::Workgroup:
+          if (!_.HasCapability(
+                  spv::Capability::
+                      WorkgroupMemoryExplicitLayout8BitAccessKHR)) {
             storage_class_ok = false;
           }
           break;
@@ -864,37 +899,40 @@
   const auto result_type = _.FindDef(inst->type_id());
   if (!result_type) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpLoad Result Type <id> '" << _.getIdName(inst->type_id())
-           << "' is not defined.";
+           << "OpLoad Result Type <id> " << _.getIdName(inst->type_id())
+           << " is not defined.";
   }
 
   const auto pointer_index = 2;
   const auto pointer_id = inst->GetOperandAs<uint32_t>(pointer_index);
   const auto pointer = _.FindDef(pointer_id);
   if (!pointer ||
-      ((_.addressing_model() == SpvAddressingModelLogical) &&
+      ((_.addressing_model() == spv::AddressingModel::Logical) &&
        ((!_.features().variable_pointers &&
          !spvOpcodeReturnsLogicalPointer(pointer->opcode())) ||
         (_.features().variable_pointers &&
          !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpLoad Pointer <id> '" << _.getIdName(pointer_id)
-           << "' is not a logical pointer.";
+           << "OpLoad Pointer <id> " << _.getIdName(pointer_id)
+           << " is not a logical pointer.";
   }
 
   const auto pointer_type = _.FindDef(pointer->type_id());
-  if (!pointer_type || pointer_type->opcode() != SpvOpTypePointer) {
+  if (!pointer_type || pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpLoad type for pointer <id> '" << _.getIdName(pointer_id)
-           << "' is not a pointer type.";
+           << "OpLoad type for pointer <id> " << _.getIdName(pointer_id)
+           << " is not a pointer type.";
   }
 
-  const auto pointee_type = _.FindDef(pointer_type->GetOperandAs<uint32_t>(2));
-  if (!pointee_type || result_type->id() != pointee_type->id()) {
+  uint32_t pointee_data_type;
+  spv::StorageClass storage_class;
+  if (!_.GetPointerTypeInfo(pointer_type->id(), &pointee_data_type,
+                            &storage_class) ||
+      result_type->id() != pointee_data_type) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpLoad Result Type <id> '" << _.getIdName(inst->type_id())
-           << "' does not match Pointer <id> '" << _.getIdName(pointer->id())
-           << "'s type.";
+           << "OpLoad Result Type <id> " << _.getIdName(inst->type_id())
+           << " does not match Pointer <id> " << _.getIdName(pointer->id())
+           << "s type.";
   }
 
   if (!_.options()->before_hlsl_legalization &&
@@ -905,13 +943,13 @@
 
   if (auto error = CheckMemoryAccess(_, inst, 3)) return error;
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id()) &&
-      result_type->opcode() != SpvOpTypePointer) {
-    if (result_type->opcode() != SpvOpTypeInt &&
-        result_type->opcode() != SpvOpTypeFloat &&
-        result_type->opcode() != SpvOpTypeVector &&
-        result_type->opcode() != SpvOpTypeMatrix) {
+      result_type->opcode() != spv::Op::OpTypePointer) {
+    if (result_type->opcode() != spv::Op::OpTypeInt &&
+        result_type->opcode() != spv::Op::OpTypeFloat &&
+        result_type->opcode() != spv::Op::OpTypeVector &&
+        result_type->opcode() != spv::Op::OpTypeMatrix) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "8- or 16-bit loads must be a scalar, vector or matrix type";
     }
@@ -925,60 +963,80 @@
   const auto pointer_id = inst->GetOperandAs<uint32_t>(pointer_index);
   const auto pointer = _.FindDef(pointer_id);
   if (!pointer ||
-      (_.addressing_model() == SpvAddressingModelLogical &&
+      (_.addressing_model() == spv::AddressingModel::Logical &&
        ((!_.features().variable_pointers &&
          !spvOpcodeReturnsLogicalPointer(pointer->opcode())) ||
         (_.features().variable_pointers &&
          !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpStore Pointer <id> '" << _.getIdName(pointer_id)
-           << "' is not a logical pointer.";
+           << "OpStore Pointer <id> " << _.getIdName(pointer_id)
+           << " is not a logical pointer.";
   }
   const auto pointer_type = _.FindDef(pointer->type_id());
-  if (!pointer_type || pointer_type->opcode() != SpvOpTypePointer) {
+  if (!pointer_type || pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpStore type for pointer <id> '" << _.getIdName(pointer_id)
-           << "' is not a pointer type.";
+           << "OpStore type for pointer <id> " << _.getIdName(pointer_id)
+           << " is not a pointer type.";
   }
   const auto type_id = pointer_type->GetOperandAs<uint32_t>(2);
   const auto type = _.FindDef(type_id);
-  if (!type || SpvOpTypeVoid == type->opcode()) {
+  if (!type || spv::Op::OpTypeVoid == type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpStore Pointer <id> '" << _.getIdName(pointer_id)
-           << "'s type is void.";
+           << "OpStore Pointer <id> " << _.getIdName(pointer_id)
+           << "s type is void.";
   }
 
   // validate storage class
   {
     uint32_t data_type;
-    uint32_t storage_class;
+    spv::StorageClass storage_class;
     if (!_.GetPointerTypeInfo(pointer_type->id(), &data_type, &storage_class)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpStore Pointer <id> '" << _.getIdName(pointer_id)
-             << "' is not pointer type";
+             << "OpStore Pointer <id> " << _.getIdName(pointer_id)
+             << " is not pointer type";
     }
 
-    if (storage_class == SpvStorageClassUniformConstant ||
-        storage_class == SpvStorageClassInput ||
-        storage_class == SpvStorageClassPushConstant) {
+    if (storage_class == spv::StorageClass::UniformConstant ||
+        storage_class == spv::StorageClass::Input ||
+        storage_class == spv::StorageClass::PushConstant) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpStore Pointer <id> '" << _.getIdName(pointer_id)
-             << "' storage class is read-only";
+             << "OpStore Pointer <id> " << _.getIdName(pointer_id)
+             << " storage class is read-only";
+    } else if (storage_class == spv::StorageClass::ShaderRecordBufferKHR) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "ShaderRecordBufferKHR Storage Class variables are read only";
+    } else if (storage_class == spv::StorageClass::HitAttributeKHR) {
+      std::string errorVUID = _.VkErrorID(4703);
+      _.function(inst->function()->id())
+          ->RegisterExecutionModelLimitation(
+              [errorVUID](spv::ExecutionModel model, std::string* message) {
+                if (model == spv::ExecutionModel::AnyHitKHR ||
+                    model == spv::ExecutionModel::ClosestHitKHR) {
+                  if (message) {
+                    *message =
+                        errorVUID +
+                        "HitAttributeKHR Storage Class variables are read only "
+                        "with AnyHitKHR and ClosestHitKHR";
+                  }
+                  return false;
+                }
+                return true;
+              });
     }
 
     if (spvIsVulkanEnv(_.context()->target_env) &&
-        storage_class == SpvStorageClassUniform) {
+        storage_class == spv::StorageClass::Uniform) {
       auto base_ptr = _.TracePointer(pointer);
-      if (base_ptr->opcode() == SpvOpVariable) {
+      if (base_ptr->opcode() == spv::Op::OpVariable) {
         // If it's not a variable a different check should catch the problem.
         auto base_type = _.FindDef(base_ptr->GetOperandAs<uint32_t>(0));
         // Get the pointed-to type.
         base_type = _.FindDef(base_type->GetOperandAs<uint32_t>(2u));
-        if (base_type->opcode() == SpvOpTypeArray ||
-            base_type->opcode() == SpvOpTypeRuntimeArray) {
+        if (base_type->opcode() == spv::Op::OpTypeArray ||
+            base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
           base_type = _.FindDef(base_type->GetOperandAs<uint32_t>(1u));
         }
-        if (_.HasDecoration(base_type->id(), SpvDecorationBlock)) {
+        if (_.HasDecoration(base_type->id(), spv::Decoration::Block)) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << _.VkErrorID(6925)
                  << "In the Vulkan environment, cannot store to Uniform Blocks";
@@ -992,43 +1050,44 @@
   const auto object = _.FindDef(object_id);
   if (!object || !object->type_id()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpStore Object <id> '" << _.getIdName(object_id)
-           << "' is not an object.";
+           << "OpStore Object <id> " << _.getIdName(object_id)
+           << " is not an object.";
   }
   const auto object_type = _.FindDef(object->type_id());
-  if (!object_type || SpvOpTypeVoid == object_type->opcode()) {
+  if (!object_type || spv::Op::OpTypeVoid == object_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpStore Object <id> '" << _.getIdName(object_id)
-           << "'s type is void.";
+           << "OpStore Object <id> " << _.getIdName(object_id)
+           << "s type is void.";
   }
 
   if (type->id() != object_type->id()) {
-    if (!_.options()->relax_struct_store || type->opcode() != SpvOpTypeStruct ||
-        object_type->opcode() != SpvOpTypeStruct) {
+    if (!_.options()->relax_struct_store ||
+        type->opcode() != spv::Op::OpTypeStruct ||
+        object_type->opcode() != spv::Op::OpTypeStruct) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpStore Pointer <id> '" << _.getIdName(pointer_id)
-             << "'s type does not match Object <id> '"
-             << _.getIdName(object->id()) << "'s type.";
+             << "OpStore Pointer <id> " << _.getIdName(pointer_id)
+             << "s type does not match Object <id> "
+             << _.getIdName(object->id()) << "s type.";
     }
 
     // TODO: Check for layout compatible matricies and arrays as well.
     if (!AreLayoutCompatibleStructs(_, type, object_type)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpStore Pointer <id> '" << _.getIdName(pointer_id)
-             << "'s layout does not match Object <id> '"
-             << _.getIdName(object->id()) << "'s layout.";
+             << "OpStore Pointer <id> " << _.getIdName(pointer_id)
+             << "s layout does not match Object <id> "
+             << _.getIdName(object->id()) << "s layout.";
     }
   }
 
   if (auto error = CheckMemoryAccess(_, inst, 2)) return error;
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id()) &&
-      object_type->opcode() != SpvOpTypePointer) {
-    if (object_type->opcode() != SpvOpTypeInt &&
-        object_type->opcode() != SpvOpTypeFloat &&
-        object_type->opcode() != SpvOpTypeVector &&
-        object_type->opcode() != SpvOpTypeMatrix) {
+      object_type->opcode() != spv::Op::OpTypePointer) {
+    if (object_type->opcode() != spv::Op::OpTypeInt &&
+        object_type->opcode() != spv::Op::OpTypeFloat &&
+        object_type->opcode() != spv::Op::OpTypeVector &&
+        object_type->opcode() != spv::Op::OpTypeMatrix) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "8- or 16-bit stores must be a scalar, vector or matrix type";
     }
@@ -1039,9 +1098,10 @@
 
 spv_result_t ValidateCopyMemoryMemoryAccess(ValidationState_t& _,
                                             const Instruction* inst) {
-  assert(inst->opcode() == SpvOpCopyMemory ||
-         inst->opcode() == SpvOpCopyMemorySized);
-  const uint32_t first_access_index = inst->opcode() == SpvOpCopyMemory ? 2 : 3;
+  assert(inst->opcode() == spv::Op::OpCopyMemory ||
+         inst->opcode() == spv::Op::OpCopyMemorySized);
+  const uint32_t first_access_index =
+      inst->opcode() == spv::Op::OpCopyMemory ? 2 : 3;
   if (inst->operands().size() > first_access_index) {
     if (auto error = CheckMemoryAccess(_, inst, first_access_index))
       return error;
@@ -1059,21 +1119,23 @@
         //  make-visible.
         //  - the second is the source (read) access and it can't have
         //  make-available.
-        if (first_access & SpvMemoryAccessMakePointerVisibleKHRMask) {
+        if (first_access &
+            uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Target memory access must not include "
                     "MakePointerVisibleKHR";
         }
         const auto second_access =
             inst->GetOperandAs<uint32_t>(second_access_index);
-        if (second_access & SpvMemoryAccessMakePointerAvailableKHRMask) {
+        if (second_access &
+            uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Source memory access must not include "
                     "MakePointerAvailableKHR";
         }
       } else {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
-               << spvOpcodeString(static_cast<SpvOp>(inst->opcode()))
+               << spvOpcodeString(static_cast<spv::Op>(inst->opcode()))
                << " with two memory access operands requires SPIR-V 1.4 or "
                   "later";
       }
@@ -1088,8 +1150,8 @@
   const auto target = _.FindDef(target_id);
   if (!target) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Target operand <id> '" << _.getIdName(target_id)
-           << "' is not defined.";
+           << "Target operand <id> " << _.getIdName(target_id)
+           << " is not defined.";
   }
 
   const auto source_index = 1;
@@ -1097,85 +1159,85 @@
   const auto source = _.FindDef(source_id);
   if (!source) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Source operand <id> '" << _.getIdName(source_id)
-           << "' is not defined.";
+           << "Source operand <id> " << _.getIdName(source_id)
+           << " is not defined.";
   }
 
   const auto target_pointer_type = _.FindDef(target->type_id());
   if (!target_pointer_type ||
-      target_pointer_type->opcode() != SpvOpTypePointer) {
+      target_pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Target operand <id> '" << _.getIdName(target_id)
-           << "' is not a pointer.";
+           << "Target operand <id> " << _.getIdName(target_id)
+           << " is not a pointer.";
   }
 
   const auto source_pointer_type = _.FindDef(source->type_id());
   if (!source_pointer_type ||
-      source_pointer_type->opcode() != SpvOpTypePointer) {
+      source_pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Source operand <id> '" << _.getIdName(source_id)
-           << "' is not a pointer.";
+           << "Source operand <id> " << _.getIdName(source_id)
+           << " is not a pointer.";
   }
 
-  if (inst->opcode() == SpvOpCopyMemory) {
+  if (inst->opcode() == spv::Op::OpCopyMemory) {
     const auto target_type =
         _.FindDef(target_pointer_type->GetOperandAs<uint32_t>(2));
-    if (!target_type || target_type->opcode() == SpvOpTypeVoid) {
+    if (!target_type || target_type->opcode() == spv::Op::OpTypeVoid) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "Target operand <id> '" << _.getIdName(target_id)
-             << "' cannot be a void pointer.";
+             << "Target operand <id> " << _.getIdName(target_id)
+             << " cannot be a void pointer.";
     }
 
     const auto source_type =
         _.FindDef(source_pointer_type->GetOperandAs<uint32_t>(2));
-    if (!source_type || source_type->opcode() == SpvOpTypeVoid) {
+    if (!source_type || source_type->opcode() == spv::Op::OpTypeVoid) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "Source operand <id> '" << _.getIdName(source_id)
-             << "' cannot be a void pointer.";
+             << "Source operand <id> " << _.getIdName(source_id)
+             << " cannot be a void pointer.";
     }
 
     if (target_type->id() != source_type->id()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "Target <id> '" << _.getIdName(source_id)
-             << "'s type does not match Source <id> '"
-             << _.getIdName(source_type->id()) << "'s type.";
+             << "Target <id> " << _.getIdName(source_id)
+             << "s type does not match Source <id> "
+             << _.getIdName(source_type->id()) << "s type.";
     }
   } else {
     const auto size_id = inst->GetOperandAs<uint32_t>(2);
     const auto size = _.FindDef(size_id);
     if (!size) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "Size operand <id> '" << _.getIdName(size_id)
-             << "' is not defined.";
+             << "Size operand <id> " << _.getIdName(size_id)
+             << " is not defined.";
     }
 
     const auto size_type = _.FindDef(size->type_id());
     if (!_.IsIntScalarType(size_type->id())) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "Size operand <id> '" << _.getIdName(size_id)
-             << "' must be a scalar integer type.";
+             << "Size operand <id> " << _.getIdName(size_id)
+             << " must be a scalar integer type.";
     }
 
     bool is_zero = true;
     switch (size->opcode()) {
-      case SpvOpConstantNull:
+      case spv::Op::OpConstantNull:
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << "Size operand <id> '" << _.getIdName(size_id)
-               << "' cannot be a constant zero.";
-      case SpvOpConstant:
+               << "Size operand <id> " << _.getIdName(size_id)
+               << " cannot be a constant zero.";
+      case spv::Op::OpConstant:
         if (size_type->word(3) == 1 &&
             size->word(size->words().size() - 1) & 0x80000000) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << "Size operand <id> '" << _.getIdName(size_id)
-                 << "' cannot have the sign bit set to 1.";
+                 << "Size operand <id> " << _.getIdName(size_id)
+                 << " cannot have the sign bit set to 1.";
         }
         for (size_t i = 3; is_zero && i < size->words().size(); ++i) {
           is_zero &= (size->word(i) == 0);
         }
         if (is_zero) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
-                 << "Size operand <id> '" << _.getIdName(size_id)
-                 << "' cannot be a constant zero.";
+                 << "Size operand <id> " << _.getIdName(size_id)
+                 << " cannot be a constant zero.";
         }
         break;
       default:
@@ -1187,10 +1249,10 @@
 
   // Get past the pointers to avoid checking a pointer copy.
   auto sub_type = _.FindDef(target_pointer_type->GetOperandAs<uint32_t>(2));
-  while (sub_type->opcode() == SpvOpTypePointer) {
+  while (sub_type->opcode() == spv::Op::OpTypePointer) {
     sub_type = _.FindDef(sub_type->GetOperandAs<uint32_t>(2));
   }
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(sub_type->id())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Cannot copy memory of objects containing 8- or 16-bit types";
@@ -1202,15 +1264,16 @@
 spv_result_t ValidateAccessChain(ValidationState_t& _,
                                  const Instruction* inst) {
   std::string instr_name =
-      "Op" + std::string(spvOpcodeString(static_cast<SpvOp>(inst->opcode())));
+      "Op" + std::string(spvOpcodeString(static_cast<spv::Op>(inst->opcode())));
 
   // The result type must be OpTypePointer.
   auto result_type = _.FindDef(inst->type_id());
-  if (SpvOpTypePointer != result_type->opcode()) {
+  if (spv::Op::OpTypePointer != result_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "The Result Type of " << instr_name << " <id> '"
-           << _.getIdName(inst->id()) << "' must be OpTypePointer. Found Op"
-           << spvOpcodeString(static_cast<SpvOp>(result_type->opcode())) << ".";
+           << "The Result Type of " << instr_name << " <id> "
+           << _.getIdName(inst->id()) << " must be OpTypePointer. Found Op"
+           << spvOpcodeString(static_cast<spv::Op>(result_type->opcode()))
+           << ".";
   }
 
   // Result type is a pointer. Find out what it's pointing to.
@@ -1223,9 +1286,9 @@
   const auto base_id = inst->GetOperandAs<uint32_t>(base_index);
   const auto base = _.FindDef(base_id);
   const auto base_type = _.FindDef(base->type_id());
-  if (!base_type || SpvOpTypePointer != base_type->opcode()) {
+  if (!base_type || spv::Op::OpTypePointer != base_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "The Base <id> '" << _.getIdName(base_id) << "' in " << instr_name
+           << "The Base <id> " << _.getIdName(base_id) << " in " << instr_name
            << " instruction must be a pointer.";
   }
 
@@ -1247,8 +1310,8 @@
   // The number of indexes passed to OpAccessChain may not exceed 255
   // The instruction includes 4 words + N words (for N indexes)
   size_t num_indexes = inst->words().size() - 4;
-  if (inst->opcode() == SpvOpPtrAccessChain ||
-      inst->opcode() == SpvOpInBoundsPtrAccessChain) {
+  if (inst->opcode() == spv::Op::OpPtrAccessChain ||
+      inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) {
     // In pointer access chains, the element operand is required, but not
     // counted as an index.
     --num_indexes;
@@ -1268,8 +1331,8 @@
   // on. Once any non-composite type is reached, there must be no remaining
   // (unused) indexes.
   auto starting_index = 4;
-  if (inst->opcode() == SpvOpPtrAccessChain ||
-      inst->opcode() == SpvOpInBoundsPtrAccessChain) {
+  if (inst->opcode() == spv::Op::OpPtrAccessChain ||
+      inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) {
     ++starting_index;
   }
   for (size_t i = starting_index; i < inst->words().size(); ++i) {
@@ -1278,26 +1341,26 @@
     auto cur_word_instr = _.FindDef(cur_word);
     // The index must be a scalar integer type (See OpAccessChain in the Spec.)
     auto index_type = _.FindDef(cur_word_instr->type_id());
-    if (!index_type || SpvOpTypeInt != index_type->opcode()) {
+    if (!index_type || spv::Op::OpTypeInt != index_type->opcode()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Indexes passed to " << instr_name
              << " must be of type integer.";
     }
     switch (type_pointee->opcode()) {
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
-      case SpvOpTypeCooperativeMatrixNV:
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray: {
-        // In OpTypeMatrix, OpTypeVector, SpvOpTypeCooperativeMatrixNV,
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeCooperativeMatrixNV:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray: {
+        // In OpTypeMatrix, OpTypeVector, spv::Op::OpTypeCooperativeMatrixNV,
         // OpTypeArray, and OpTypeRuntimeArray, word 2 is the Element Type.
         type_pointee = _.FindDef(type_pointee->word(2));
         break;
       }
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // In case of structures, there is an additional constraint on the
         // index: the index must be an OpConstant.
-        if (SpvOpConstant != cur_word_instr->opcode()) {
+        if (spv::Op::OpConstant != cur_word_instr->opcode()) {
           return _.diag(SPV_ERROR_INVALID_ID, cur_word_instr)
                  << "The <id> passed to " << instr_name
                  << " to index into a "
@@ -1317,8 +1380,8 @@
           return _.diag(SPV_ERROR_INVALID_ID, cur_word_instr)
                  << "Index is out of bounds: " << instr_name
                  << " can not find index " << cur_index
-                 << " into the structure <id> '"
-                 << _.getIdName(type_pointee->id()) << "'. This structure has "
+                 << " into the structure <id> "
+                 << _.getIdName(type_pointee->id()) << ". This structure has "
                  << num_struct_members << " members. Largest valid index is "
                  << num_struct_members - 1 << ".";
         }
@@ -1341,11 +1404,12 @@
   if (type_pointee->id() != result_type_pointee->id()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << instr_name << " result type (Op"
-           << spvOpcodeString(static_cast<SpvOp>(result_type_pointee->opcode()))
+           << spvOpcodeString(
+                  static_cast<spv::Op>(result_type_pointee->opcode()))
            << ") does not match the type that results from indexing into the "
               "base "
               "<id> (Op"
-           << spvOpcodeString(static_cast<SpvOp>(type_pointee->opcode()))
+           << spvOpcodeString(static_cast<spv::Op>(type_pointee->opcode()))
            << ").";
   }
 
@@ -1354,67 +1418,115 @@
 
 spv_result_t ValidatePtrAccessChain(ValidationState_t& _,
                                     const Instruction* inst) {
-  if (_.addressing_model() == SpvAddressingModelLogical) {
+  if (_.addressing_model() == spv::AddressingModel::Logical) {
     if (!_.features().variable_pointers) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Generating variable pointers requires capability "
              << "VariablePointers or VariablePointersStorageBuffer";
     }
   }
-  return ValidateAccessChain(_, inst);
+
+  // Need to call first, will make sure Base is a valid ID
+  if (auto error = ValidateAccessChain(_, inst)) return error;
+
+  const auto base_id = inst->GetOperandAs<uint32_t>(2);
+  const auto base = _.FindDef(base_id);
+  const auto base_type = _.FindDef(base->type_id());
+  const auto base_type_storage_class =
+      base_type->GetOperandAs<spv::StorageClass>(1);
+
+  if (_.HasCapability(spv::Capability::Shader) &&
+      (base_type_storage_class == spv::StorageClass::Uniform ||
+       base_type_storage_class == spv::StorageClass::StorageBuffer ||
+       base_type_storage_class == spv::StorageClass::PhysicalStorageBuffer ||
+       base_type_storage_class == spv::StorageClass::PushConstant ||
+       (_.HasCapability(spv::Capability::WorkgroupMemoryExplicitLayoutKHR) &&
+        base_type_storage_class == spv::StorageClass::Workgroup)) &&
+      !_.HasDecoration(base_type->id(), spv::Decoration::ArrayStride)) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "OpPtrAccessChain must have a Base whose type is decorated "
+              "with ArrayStride";
+  }
+
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if (base_type_storage_class == spv::StorageClass::Workgroup) {
+      if (!_.HasCapability(spv::Capability::VariablePointers)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << _.VkErrorID(7651)
+               << "OpPtrAccessChain Base operand pointing to Workgroup "
+                  "storage class must use VariablePointers capability";
+      }
+    } else if (base_type_storage_class == spv::StorageClass::StorageBuffer) {
+      if (!_.features().variable_pointers) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << _.VkErrorID(7652)
+               << "OpPtrAccessChain Base operand pointing to StorageBuffer "
+                  "storage class must use VariablePointers or "
+                  "VariablePointersStorageBuffer capability";
+      }
+    } else if (base_type_storage_class !=
+               spv::StorageClass::PhysicalStorageBuffer) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(7650)
+             << "OpPtrAccessChain Base operand must point to Workgroup, "
+                "StorageBuffer, or PhysicalStorageBuffer storage class";
+    }
+  }
+
+  return SPV_SUCCESS;
 }
 
 spv_result_t ValidateArrayLength(ValidationState_t& state,
                                  const Instruction* inst) {
   std::string instr_name =
-      "Op" + std::string(spvOpcodeString(static_cast<SpvOp>(inst->opcode())));
+      "Op" + std::string(spvOpcodeString(static_cast<spv::Op>(inst->opcode())));
 
   // Result type must be a 32-bit unsigned int.
   auto result_type = state.FindDef(inst->type_id());
-  if (result_type->opcode() != SpvOpTypeInt ||
+  if (result_type->opcode() != spv::Op::OpTypeInt ||
       result_type->GetOperandAs<uint32_t>(1) != 32 ||
       result_type->GetOperandAs<uint32_t>(2) != 0) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
-           << "The Result Type of " << instr_name << " <id> '"
+           << "The Result Type of " << instr_name << " <id> "
            << state.getIdName(inst->id())
-           << "' must be OpTypeInt with width 32 and signedness 0.";
+           << " must be OpTypeInt with width 32 and signedness 0.";
   }
 
   // The structure that is passed in must be an pointer to a structure, whose
   // last element is a runtime array.
   auto pointer = state.FindDef(inst->GetOperandAs<uint32_t>(2));
   auto pointer_type = state.FindDef(pointer->type_id());
-  if (pointer_type->opcode() != SpvOpTypePointer) {
+  if (pointer_type->opcode() != spv::Op::OpTypePointer) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
-           << "The Struture's type in " << instr_name << " <id> '"
+           << "The Structure's type in " << instr_name << " <id> "
            << state.getIdName(inst->id())
-           << "' must be a pointer to an OpTypeStruct.";
+           << " must be a pointer to an OpTypeStruct.";
   }
 
   auto structure_type = state.FindDef(pointer_type->GetOperandAs<uint32_t>(2));
-  if (structure_type->opcode() != SpvOpTypeStruct) {
+  if (structure_type->opcode() != spv::Op::OpTypeStruct) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
-           << "The Struture's type in " << instr_name << " <id> '"
+           << "The Structure's type in " << instr_name << " <id> "
            << state.getIdName(inst->id())
-           << "' must be a pointer to an OpTypeStruct.";
+           << " must be a pointer to an OpTypeStruct.";
   }
 
   auto num_of_members = structure_type->operands().size() - 1;
   auto last_member =
       state.FindDef(structure_type->GetOperandAs<uint32_t>(num_of_members));
-  if (last_member->opcode() != SpvOpTypeRuntimeArray) {
+  if (last_member->opcode() != spv::Op::OpTypeRuntimeArray) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
-           << "The Struture's last member in " << instr_name << " <id> '"
-           << state.getIdName(inst->id()) << "' must be an OpTypeRuntimeArray.";
+           << "The Structure's last member in " << instr_name << " <id> "
+           << state.getIdName(inst->id()) << " must be an OpTypeRuntimeArray.";
   }
 
   // The array member must the index of the last element (the run time
   // array).
   if (inst->GetOperandAs<uint32_t>(3) != num_of_members - 1) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
-           << "The array member in " << instr_name << " <id> '"
+           << "The array member in " << instr_name << " <id> "
            << state.getIdName(inst->id())
-           << "' must be an the last member of the struct.";
+           << " must be an the last member of the struct.";
   }
   return SPV_SUCCESS;
 }
@@ -1422,26 +1534,25 @@
 spv_result_t ValidateCooperativeMatrixLengthNV(ValidationState_t& state,
                                                const Instruction* inst) {
   std::string instr_name =
-      "Op" + std::string(spvOpcodeString(static_cast<SpvOp>(inst->opcode())));
+      "Op" + std::string(spvOpcodeString(static_cast<spv::Op>(inst->opcode())));
 
   // Result type must be a 32-bit unsigned int.
   auto result_type = state.FindDef(inst->type_id());
-  if (result_type->opcode() != SpvOpTypeInt ||
+  if (result_type->opcode() != spv::Op::OpTypeInt ||
       result_type->GetOperandAs<uint32_t>(1) != 32 ||
       result_type->GetOperandAs<uint32_t>(2) != 0) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
-           << "The Result Type of " << instr_name << " <id> '"
+           << "The Result Type of " << instr_name << " <id> "
            << state.getIdName(inst->id())
-           << "' must be OpTypeInt with width 32 and signedness 0.";
+           << " must be OpTypeInt with width 32 and signedness 0.";
   }
 
   auto type_id = inst->GetOperandAs<uint32_t>(2);
   auto type = state.FindDef(type_id);
-  if (type->opcode() != SpvOpTypeCooperativeMatrixNV) {
+  if (type->opcode() != spv::Op::OpTypeCooperativeMatrixNV) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
-           << "The type in " << instr_name << " <id> '"
-           << state.getIdName(type_id)
-           << "' must be OpTypeCooperativeMatrixNV.";
+           << "The type in " << instr_name << " <id> "
+           << state.getIdName(type_id) << " must be OpTypeCooperativeMatrixNV.";
   }
   return SPV_SUCCESS;
 }
@@ -1450,63 +1561,63 @@
                                                   const Instruction* inst) {
   uint32_t type_id;
   const char* opname;
-  if (inst->opcode() == SpvOpCooperativeMatrixLoadNV) {
+  if (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) {
     type_id = inst->type_id();
-    opname = "SpvOpCooperativeMatrixLoadNV";
+    opname = "spv::Op::OpCooperativeMatrixLoadNV";
   } else {
     // get Object operand's type
     type_id = _.FindDef(inst->GetOperandAs<uint32_t>(1))->type_id();
-    opname = "SpvOpCooperativeMatrixStoreNV";
+    opname = "spv::Op::OpCooperativeMatrixStoreNV";
   }
 
   auto matrix_type = _.FindDef(type_id);
 
-  if (matrix_type->opcode() != SpvOpTypeCooperativeMatrixNV) {
-    if (inst->opcode() == SpvOpCooperativeMatrixLoadNV) {
+  if (matrix_type->opcode() != spv::Op::OpTypeCooperativeMatrixNV) {
+    if (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "SpvOpCooperativeMatrixLoadNV Result Type <id> '"
-             << _.getIdName(type_id) << "' is not a cooperative matrix type.";
+             << "spv::Op::OpCooperativeMatrixLoadNV Result Type <id> "
+             << _.getIdName(type_id) << " is not a cooperative matrix type.";
     } else {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "SpvOpCooperativeMatrixStoreNV Object type <id> '"
-             << _.getIdName(type_id) << "' is not a cooperative matrix type.";
+             << "spv::Op::OpCooperativeMatrixStoreNV Object type <id> "
+             << _.getIdName(type_id) << " is not a cooperative matrix type.";
     }
   }
 
   const auto pointer_index =
-      (inst->opcode() == SpvOpCooperativeMatrixLoadNV) ? 2u : 0u;
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) ? 2u : 0u;
   const auto pointer_id = inst->GetOperandAs<uint32_t>(pointer_index);
   const auto pointer = _.FindDef(pointer_id);
   if (!pointer ||
-      ((_.addressing_model() == SpvAddressingModelLogical) &&
+      ((_.addressing_model() == spv::AddressingModel::Logical) &&
        ((!_.features().variable_pointers &&
          !spvOpcodeReturnsLogicalPointer(pointer->opcode())) ||
         (_.features().variable_pointers &&
          !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << opname << " Pointer <id> '" << _.getIdName(pointer_id)
-           << "' is not a logical pointer.";
+           << opname << " Pointer <id> " << _.getIdName(pointer_id)
+           << " is not a logical pointer.";
   }
 
   const auto pointer_type_id = pointer->type_id();
   const auto pointer_type = _.FindDef(pointer_type_id);
-  if (!pointer_type || pointer_type->opcode() != SpvOpTypePointer) {
+  if (!pointer_type || pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << opname << " type for pointer <id> '" << _.getIdName(pointer_id)
-           << "' is not a pointer type.";
+           << opname << " type for pointer <id> " << _.getIdName(pointer_id)
+           << " is not a pointer type.";
   }
 
   const auto storage_class_index = 1u;
   const auto storage_class =
-      pointer_type->GetOperandAs<uint32_t>(storage_class_index);
+      pointer_type->GetOperandAs<spv::StorageClass>(storage_class_index);
 
-  if (storage_class != SpvStorageClassWorkgroup &&
-      storage_class != SpvStorageClassStorageBuffer &&
-      storage_class != SpvStorageClassPhysicalStorageBuffer) {
+  if (storage_class != spv::StorageClass::Workgroup &&
+      storage_class != spv::StorageClass::StorageBuffer &&
+      storage_class != spv::StorageClass::PhysicalStorageBuffer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << opname << " storage class for pointer type <id> '"
+           << opname << " storage class for pointer type <id> "
            << _.getIdName(pointer_type_id)
-           << "' is not Workgroup or StorageBuffer.";
+           << " is not Workgroup or StorageBuffer.";
   }
 
   const auto pointee_id = pointer_type->GetOperandAs<uint32_t>(2);
@@ -1514,34 +1625,34 @@
   if (!pointee_type || !(_.IsIntScalarOrVectorType(pointee_id) ||
                          _.IsFloatScalarOrVectorType(pointee_id))) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << opname << " Pointer <id> '" << _.getIdName(pointer->id())
-           << "'s Type must be a scalar or vector type.";
+           << opname << " Pointer <id> " << _.getIdName(pointer->id())
+           << "s Type must be a scalar or vector type.";
   }
 
   const auto stride_index =
-      (inst->opcode() == SpvOpCooperativeMatrixLoadNV) ? 3u : 2u;
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) ? 3u : 2u;
   const auto stride_id = inst->GetOperandAs<uint32_t>(stride_index);
   const auto stride = _.FindDef(stride_id);
   if (!stride || !_.IsIntScalarType(stride->type_id())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Stride operand <id> '" << _.getIdName(stride_id)
-           << "' must be a scalar integer type.";
+           << "Stride operand <id> " << _.getIdName(stride_id)
+           << " must be a scalar integer type.";
   }
 
   const auto colmajor_index =
-      (inst->opcode() == SpvOpCooperativeMatrixLoadNV) ? 4u : 3u;
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) ? 4u : 3u;
   const auto colmajor_id = inst->GetOperandAs<uint32_t>(colmajor_index);
   const auto colmajor = _.FindDef(colmajor_id);
   if (!colmajor || !_.IsBoolScalarType(colmajor->type_id()) ||
       !(spvOpcodeIsConstant(colmajor->opcode()) ||
         spvOpcodeIsSpecConstant(colmajor->opcode()))) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Column Major operand <id> '" << _.getIdName(colmajor_id)
-           << "' must be a boolean constant instruction.";
+           << "Column Major operand <id> " << _.getIdName(colmajor_id)
+           << " must be a boolean constant instruction.";
   }
 
   const auto memory_access_index =
-      (inst->opcode() == SpvOpCooperativeMatrixLoadNV) ? 5u : 4u;
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) ? 5u : 4u;
   if (inst->operands().size() > memory_access_index) {
     if (auto error = CheckMemoryAccess(_, inst, memory_access_index))
       return error;
@@ -1552,7 +1663,7 @@
 
 spv_result_t ValidatePtrComparison(ValidationState_t& _,
                                    const Instruction* inst) {
-  if (_.addressing_model() == SpvAddressingModelLogical &&
+  if (_.addressing_model() == spv::AddressingModel::Logical &&
       !_.features().variable_pointers) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Instruction cannot for logical addressing model be used without "
@@ -1560,13 +1671,13 @@
   }
 
   const auto result_type = _.FindDef(inst->type_id());
-  if (inst->opcode() == SpvOpPtrDiff) {
-    if (!result_type || result_type->opcode() != SpvOpTypeInt) {
+  if (inst->opcode() == spv::Op::OpPtrDiff) {
+    if (!result_type || result_type->opcode() != spv::Op::OpTypeInt) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Result Type must be an integer scalar";
     }
   } else {
-    if (!result_type || result_type->opcode() != SpvOpTypeBool) {
+    if (!result_type || result_type->opcode() != spv::Op::OpTypeBool) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Result Type must be OpTypeBool";
     }
@@ -1579,25 +1690,26 @@
            << "The types of Operand 1 and Operand 2 must match";
   }
   const auto op1_type = _.FindDef(op1->type_id());
-  if (!op1_type || op1_type->opcode() != SpvOpTypePointer) {
+  if (!op1_type || op1_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Operand type must be a pointer";
   }
 
-  SpvStorageClass sc = op1_type->GetOperandAs<SpvStorageClass>(1u);
-  if (_.addressing_model() == SpvAddressingModelLogical) {
-    if (sc != SpvStorageClassWorkgroup && sc != SpvStorageClassStorageBuffer) {
+  spv::StorageClass sc = op1_type->GetOperandAs<spv::StorageClass>(1u);
+  if (_.addressing_model() == spv::AddressingModel::Logical) {
+    if (sc != spv::StorageClass::Workgroup &&
+        sc != spv::StorageClass::StorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Invalid pointer storage class";
     }
 
-    if (sc == SpvStorageClassWorkgroup &&
-        !_.HasCapability(SpvCapabilityVariablePointers)) {
+    if (sc == spv::StorageClass::Workgroup &&
+        !_.HasCapability(spv::Capability::VariablePointers)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Workgroup storage class pointer requires VariablePointers "
                 "capability to be specified";
     }
-  } else if (sc == SpvStorageClassPhysicalStorageBuffer) {
+  } else if (sc == spv::StorageClass::PhysicalStorageBuffer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Cannot use a pointer in the PhysicalStorageBuffer storage class";
   }
@@ -1609,45 +1721,45 @@
 
 spv_result_t MemoryPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpVariable:
+    case spv::Op::OpVariable:
       if (auto error = ValidateVariable(_, inst)) return error;
       break;
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       if (auto error = ValidateLoad(_, inst)) return error;
       break;
-    case SpvOpStore:
+    case spv::Op::OpStore:
       if (auto error = ValidateStore(_, inst)) return error;
       break;
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       if (auto error = ValidateCopyMemory(_, inst)) return error;
       break;
-    case SpvOpPtrAccessChain:
+    case spv::Op::OpPtrAccessChain:
       if (auto error = ValidatePtrAccessChain(_, inst)) return error;
       break;
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       if (auto error = ValidateAccessChain(_, inst)) return error;
       break;
-    case SpvOpArrayLength:
+    case spv::Op::OpArrayLength:
       if (auto error = ValidateArrayLength(_, inst)) return error;
       break;
-    case SpvOpCooperativeMatrixLoadNV:
-    case SpvOpCooperativeMatrixStoreNV:
+    case spv::Op::OpCooperativeMatrixLoadNV:
+    case spv::Op::OpCooperativeMatrixStoreNV:
       if (auto error = ValidateCooperativeMatrixLoadStoreNV(_, inst))
         return error;
       break;
-    case SpvOpCooperativeMatrixLengthNV:
+    case spv::Op::OpCooperativeMatrixLengthNV:
       if (auto error = ValidateCooperativeMatrixLengthNV(_, inst)) return error;
       break;
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
-    case SpvOpPtrDiff:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
+    case spv::Op::OpPtrDiff:
       if (auto error = ValidatePtrComparison(_, inst)) return error;
       break;
-    case SpvOpImageTexelPointer:
-    case SpvOpGenericPtrMemSemantics:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpGenericPtrMemSemantics:
     default:
       break;
   }
diff --git a/third_party/SPIRV-Tools/source/val/validate_memory_semantics.cpp b/third_party/SPIRV-Tools/source/val/validate_memory_semantics.cpp
index d918931..748b238 100644
--- a/third_party/SPIRV-Tools/source/val/validate_memory_semantics.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_memory_semantics.cpp
@@ -27,7 +27,7 @@
                                      const Instruction* inst,
                                      uint32_t operand_index,
                                      uint32_t memory_scope) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const auto id = inst->GetOperandAs<const uint32_t>(operand_index);
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
@@ -40,15 +40,15 @@
   }
 
   if (!is_const_int32) {
-    if (_.HasCapability(SpvCapabilityShader) &&
-        !_.HasCapability(SpvCapabilityCooperativeMatrixNV)) {
+    if (_.HasCapability(spv::Capability::Shader) &&
+        !_.HasCapability(spv::Capability::CooperativeMatrixNV)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Memory Semantics ids must be OpConstant when Shader "
                 "capability is present";
     }
 
-    if (_.HasCapability(SpvCapabilityShader) &&
-        _.HasCapability(SpvCapabilityCooperativeMatrixNV) &&
+    if (_.HasCapability(spv::Capability::Shader) &&
+        _.HasCapability(spv::Capability::CooperativeMatrixNV) &&
         !spvOpcodeIsConstant(_.GetIdOpcode(id))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Memory Semantics must be a constant instruction when "
@@ -58,9 +58,10 @@
   }
 
   const size_t num_memory_order_set_bits = spvtools::utils::CountSetBits(
-      value & (SpvMemorySemanticsAcquireMask | SpvMemorySemanticsReleaseMask |
-               SpvMemorySemanticsAcquireReleaseMask |
-               SpvMemorySemanticsSequentiallyConsistentMask));
+      value & uint32_t(spv::MemorySemanticsMask::Acquire |
+                       spv::MemorySemanticsMask::Release |
+                       spv::MemorySemanticsMask::AcquireRelease |
+                       spv::MemorySemanticsMask::SequentiallyConsistent));
 
   if (num_memory_order_set_bits > 1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -71,40 +72,40 @@
               "SequentiallyConsistent";
   }
 
-  if (_.memory_model() == SpvMemoryModelVulkanKHR &&
-      value & SpvMemorySemanticsSequentiallyConsistentMask) {
+  if (_.memory_model() == spv::MemoryModel::VulkanKHR &&
+      value & uint32_t(spv::MemorySemanticsMask::SequentiallyConsistent)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "SequentiallyConsistent memory "
               "semantics cannot be used with "
               "the VulkanKHR memory model.";
   }
 
-  if (value & SpvMemorySemanticsMakeAvailableKHRMask &&
-      !_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeAvailableKHR) &&
+      !_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics MakeAvailableKHR requires capability "
            << "VulkanMemoryModelKHR";
   }
 
-  if (value & SpvMemorySemanticsMakeVisibleKHRMask &&
-      !_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeVisibleKHR) &&
+      !_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics MakeVisibleKHR requires capability "
            << "VulkanMemoryModelKHR";
   }
 
-  if (value & SpvMemorySemanticsOutputMemoryKHRMask &&
-      !_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::OutputMemoryKHR) &&
+      !_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics OutputMemoryKHR requires capability "
            << "VulkanMemoryModelKHR";
   }
 
-  if (value & SpvMemorySemanticsVolatileMask) {
-    if (!_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::Volatile)) {
+    if (!_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << spvOpcodeString(opcode)
              << ": Memory Semantics Volatile requires capability "
@@ -118,26 +119,27 @@
     }
   }
 
-  if (value & SpvMemorySemanticsUniformMemoryMask &&
-      !_.HasCapability(SpvCapabilityShader)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::UniformMemory) &&
+      !_.HasCapability(spv::Capability::Shader)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics UniformMemory requires capability Shader";
   }
 
-  // Checking for SpvCapabilityAtomicStorage is intentionally not done here. See
-  // https://github.com/KhronosGroup/glslang/issues/1618 for the reasoning why.
+  // Checking for spv::Capability::AtomicStorage is intentionally not done here.
+  // See https://github.com/KhronosGroup/glslang/issues/1618 for the reasoning
+  // why.
 
-  if (value & (SpvMemorySemanticsMakeAvailableKHRMask |
-               SpvMemorySemanticsMakeVisibleKHRMask)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeAvailableKHR |
+                       spv::MemorySemanticsMask::MakeVisibleKHR)) {
     const bool includes_storage_class =
-        value & (SpvMemorySemanticsUniformMemoryMask |
-                 SpvMemorySemanticsSubgroupMemoryMask |
-                 SpvMemorySemanticsWorkgroupMemoryMask |
-                 SpvMemorySemanticsCrossWorkgroupMemoryMask |
-                 SpvMemorySemanticsAtomicCounterMemoryMask |
-                 SpvMemorySemanticsImageMemoryMask |
-                 SpvMemorySemanticsOutputMemoryKHRMask);
+        value & uint32_t(spv::MemorySemanticsMask::UniformMemory |
+                         spv::MemorySemanticsMask::SubgroupMemory |
+                         spv::MemorySemanticsMask::WorkgroupMemory |
+                         spv::MemorySemanticsMask::CrossWorkgroupMemory |
+                         spv::MemorySemanticsMask::AtomicCounterMemory |
+                         spv::MemorySemanticsMask::ImageMemory |
+                         spv::MemorySemanticsMask::OutputMemoryKHR);
 
     if (!includes_storage_class) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -146,18 +148,18 @@
     }
   }
 
-  if (value & SpvMemorySemanticsMakeVisibleKHRMask &&
-      !(value & (SpvMemorySemanticsAcquireMask |
-                 SpvMemorySemanticsAcquireReleaseMask))) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeVisibleKHR) &&
+      !(value & uint32_t(spv::MemorySemanticsMask::Acquire |
+                         spv::MemorySemanticsMask::AcquireRelease))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": MakeVisibleKHR Memory Semantics also requires either Acquire "
               "or AcquireRelease Memory Semantics";
   }
 
-  if (value & SpvMemorySemanticsMakeAvailableKHRMask &&
-      !(value & (SpvMemorySemanticsReleaseMask |
-                 SpvMemorySemanticsAcquireReleaseMask))) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeAvailableKHR) &&
+      !(value & uint32_t(spv::MemorySemanticsMask::Release |
+                         spv::MemorySemanticsMask::AcquireRelease))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": MakeAvailableKHR Memory Semantics also requires either "
@@ -166,12 +168,12 @@
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
     const bool includes_storage_class =
-        value & (SpvMemorySemanticsUniformMemoryMask |
-                 SpvMemorySemanticsWorkgroupMemoryMask |
-                 SpvMemorySemanticsImageMemoryMask |
-                 SpvMemorySemanticsOutputMemoryKHRMask);
+        value & uint32_t(spv::MemorySemanticsMask::UniformMemory |
+                         spv::MemorySemanticsMask::WorkgroupMemory |
+                         spv::MemorySemanticsMask::ImageMemory |
+                         spv::MemorySemanticsMask::OutputMemoryKHR);
 
-    if (opcode == SpvOpMemoryBarrier && !num_memory_order_set_bits) {
+    if (opcode == spv::Op::OpMemoryBarrier && !num_memory_order_set_bits) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4732) << spvOpcodeString(opcode)
              << ": Vulkan specification requires Memory Semantics to have "
@@ -179,13 +181,15 @@
                 "of the following bits set: Acquire, Release, "
                 "AcquireRelease "
                 "or SequentiallyConsistent";
-    } else if (opcode != SpvOpMemoryBarrier && num_memory_order_set_bits) {
+    } else if (opcode != spv::Op::OpMemoryBarrier &&
+               num_memory_order_set_bits) {
       // should leave only atomics and control barriers for Vulkan env
       bool memory_is_int32 = false, memory_is_const_int32 = false;
       uint32_t memory_value = 0;
       std::tie(memory_is_int32, memory_is_const_int32, memory_value) =
           _.EvalInt32IfConst(memory_scope);
-      if (memory_is_int32 && memory_value == SpvScopeInvocation) {
+      if (memory_is_int32 &&
+          spv::Scope(memory_value) == spv::Scope::Invocation) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << _.VkErrorID(4641) << spvOpcodeString(opcode)
                << ": Vulkan specification requires Memory Semantics to be None "
@@ -193,7 +197,7 @@
       }
     }
 
-    if (opcode == SpvOpMemoryBarrier && !includes_storage_class) {
+    if (opcode == spv::Op::OpMemoryBarrier && !includes_storage_class) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4733) << spvOpcodeString(opcode)
              << ": expected Memory Semantics to include a Vulkan-supported "
@@ -202,7 +206,7 @@
 
 #if 0
     // TODO(atgoo@github.com): this check fails Vulkan CTS, reenable once fixed.
-    if (opcode == SpvOpControlBarrier && value && !includes_storage_class) {
+    if (opcode == spv::Op::OpControlBarrier && value && !includes_storage_class) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << spvOpcodeString(opcode)
              << ": expected Memory Semantics to include a Vulkan-supported "
@@ -211,18 +215,18 @@
 #endif
   }
 
-  if (opcode == SpvOpAtomicFlagClear &&
-      (value & SpvMemorySemanticsAcquireMask ||
-       value & SpvMemorySemanticsAcquireReleaseMask)) {
+  if (opcode == spv::Op::OpAtomicFlagClear &&
+      (value & uint32_t(spv::MemorySemanticsMask::Acquire) ||
+       value & uint32_t(spv::MemorySemanticsMask::AcquireRelease))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Memory Semantics Acquire and AcquireRelease cannot be used "
               "with "
            << spvOpcodeString(opcode);
   }
 
-  if (opcode == SpvOpAtomicCompareExchange && operand_index == 5 &&
-      (value & SpvMemorySemanticsReleaseMask ||
-       value & SpvMemorySemanticsAcquireReleaseMask)) {
+  if (opcode == spv::Op::OpAtomicCompareExchange && operand_index == 5 &&
+      (value & uint32_t(spv::MemorySemanticsMask::Release) ||
+       value & uint32_t(spv::MemorySemanticsMask::AcquireRelease))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics Release and AcquireRelease cannot be "
@@ -231,20 +235,20 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (opcode == SpvOpAtomicLoad &&
-        (value & SpvMemorySemanticsReleaseMask ||
-         value & SpvMemorySemanticsAcquireReleaseMask ||
-         value & SpvMemorySemanticsSequentiallyConsistentMask)) {
+    if (opcode == spv::Op::OpAtomicLoad &&
+        (value & uint32_t(spv::MemorySemanticsMask::Release) ||
+         value & uint32_t(spv::MemorySemanticsMask::AcquireRelease) ||
+         value & uint32_t(spv::MemorySemanticsMask::SequentiallyConsistent))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4731)
              << "Vulkan spec disallows OpAtomicLoad with Memory Semantics "
                 "Release, AcquireRelease and SequentiallyConsistent";
     }
 
-    if (opcode == SpvOpAtomicStore &&
-        (value & SpvMemorySemanticsAcquireMask ||
-         value & SpvMemorySemanticsAcquireReleaseMask ||
-         value & SpvMemorySemanticsSequentiallyConsistentMask)) {
+    if (opcode == spv::Op::OpAtomicStore &&
+        (value & uint32_t(spv::MemorySemanticsMask::Acquire) ||
+         value & uint32_t(spv::MemorySemanticsMask::AcquireRelease) ||
+         value & uint32_t(spv::MemorySemanticsMask::SequentiallyConsistent))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4730)
              << "Vulkan spec disallows OpAtomicStore with Memory Semantics "
diff --git a/third_party/SPIRV-Tools/source/val/validate_mesh_shading.cpp b/third_party/SPIRV-Tools/source/val/validate_mesh_shading.cpp
new file mode 100644
index 0000000..e569e25
--- /dev/null
+++ b/third_party/SPIRV-Tools/source/val/validate_mesh_shading.cpp
@@ -0,0 +1,123 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Validates ray query instructions from SPV_KHR_ray_query
+
+#include "source/opcode.h"
+#include "source/val/instruction.h"
+#include "source/val/validate.h"
+#include "source/val/validation_state.h"
+
+namespace spvtools {
+namespace val {
+
+spv_result_t MeshShadingPass(ValidationState_t& _, const Instruction* inst) {
+  const spv::Op opcode = inst->opcode();
+  switch (opcode) {
+    case spv::Op::OpEmitMeshTasksEXT: {
+      _.function(inst->function()->id())
+          ->RegisterExecutionModelLimitation(
+              [](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::TaskEXT) {
+                  if (message) {
+                    *message =
+                        "OpEmitMeshTasksEXT requires TaskEXT execution model";
+                  }
+                  return false;
+                }
+                return true;
+              });
+
+      const uint32_t group_count_x = _.GetOperandTypeId(inst, 0);
+      if (!_.IsUnsignedIntScalarType(group_count_x) ||
+          _.GetBitWidth(group_count_x) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Group Count X must be a 32-bit unsigned int scalar";
+      }
+
+      const uint32_t group_count_y = _.GetOperandTypeId(inst, 1);
+      if (!_.IsUnsignedIntScalarType(group_count_y) ||
+          _.GetBitWidth(group_count_y) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Group Count Y must be a 32-bit unsigned int scalar";
+      }
+
+      const uint32_t group_count_z = _.GetOperandTypeId(inst, 2);
+      if (!_.IsUnsignedIntScalarType(group_count_z) ||
+          _.GetBitWidth(group_count_z) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Group Count Z must be a 32-bit unsigned int scalar";
+      }
+
+      if (inst->operands().size() == 4) {
+        const auto payload = _.FindDef(inst->GetOperandAs<uint32_t>(3));
+        if (payload->opcode() != spv::Op::OpVariable) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "Payload must be the result of a OpVariable";
+        }
+        if (payload->GetOperandAs<spv::StorageClass>(2) !=
+            spv::StorageClass::TaskPayloadWorkgroupEXT) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "Payload OpVariable must have a storage class of "
+                    "TaskPayloadWorkgroupEXT";
+        }
+      }
+      break;
+    }
+
+    case spv::Op::OpSetMeshOutputsEXT: {
+      _.function(inst->function()->id())
+          ->RegisterExecutionModelLimitation(
+              [](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::MeshEXT) {
+                  if (message) {
+                    *message =
+                        "OpSetMeshOutputsEXT requires MeshEXT execution model";
+                  }
+                  return false;
+                }
+                return true;
+              });
+
+      const uint32_t vertex_count = _.GetOperandTypeId(inst, 0);
+      if (!_.IsUnsignedIntScalarType(vertex_count) ||
+          _.GetBitWidth(vertex_count) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Vertex Count must be a 32-bit unsigned int scalar";
+      }
+
+      const uint32_t primitive_count = _.GetOperandTypeId(inst, 1);
+      if (!_.IsUnsignedIntScalarType(primitive_count) ||
+          _.GetBitWidth(primitive_count) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Primitive Count must be a 32-bit unsigned int scalar";
+      }
+
+      break;
+    }
+
+    case spv::Op::OpWritePackedPrimitiveIndices4x8NV: {
+      // No validation rules (for the moment).
+      break;
+    }
+
+    default:
+      break;
+  }
+
+  return SPV_SUCCESS;
+}
+
+}  // namespace val
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/val/validate_misc.cpp b/third_party/SPIRV-Tools/source/val/validate_misc.cpp
index 5acc21e..d71fd2d 100644
--- a/third_party/SPIRV-Tools/source/val/validate_misc.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_misc.cpp
@@ -30,7 +30,7 @@
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Cannot create undefined values with void type";
   }
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id()) &&
       !_.IsPointerType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
@@ -50,7 +50,8 @@
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
-  if (is_const_int32 && value != SpvScopeSubgroup && value != SpvScopeDevice) {
+  if (is_const_int32 && spv::Scope(value) != spv::Scope::Subgroup &&
+      spv::Scope(value) != spv::Scope::Device) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << _.VkErrorID(4652) << "Scope must be Subgroup or Device";
   }
@@ -104,18 +105,18 @@
 
 spv_result_t MiscPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpUndef:
+    case spv::Op::OpUndef:
       if (auto error = ValidateUndef(_, inst)) return error;
       break;
     default:
       break;
   }
   switch (inst->opcode()) {
-    case SpvOpBeginInvocationInterlockEXT:
-    case SpvOpEndInvocationInterlockEXT:
+    case spv::Op::OpBeginInvocationInterlockEXT:
+    case spv::Op::OpEndInvocationInterlockEXT:
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              SpvExecutionModelFragment,
+              spv::ExecutionModel::Fragment,
               "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT "
               "require Fragment execution model");
 
@@ -126,14 +127,14 @@
             const auto* execution_modes =
                 state.GetExecutionModes(entry_point->id());
 
-            auto find_interlock = [](const SpvExecutionMode& mode) {
+            auto find_interlock = [](const spv::ExecutionMode& mode) {
               switch (mode) {
-                case SpvExecutionModePixelInterlockOrderedEXT:
-                case SpvExecutionModePixelInterlockUnorderedEXT:
-                case SpvExecutionModeSampleInterlockOrderedEXT:
-                case SpvExecutionModeSampleInterlockUnorderedEXT:
-                case SpvExecutionModeShadingRateInterlockOrderedEXT:
-                case SpvExecutionModeShadingRateInterlockUnorderedEXT:
+                case spv::ExecutionMode::PixelInterlockOrderedEXT:
+                case spv::ExecutionMode::PixelInterlockUnorderedEXT:
+                case spv::ExecutionMode::SampleInterlockOrderedEXT:
+                case spv::ExecutionMode::SampleInterlockUnorderedEXT:
+                case spv::ExecutionMode::ShadingRateInterlockOrderedEXT:
+                case spv::ExecutionMode::ShadingRateInterlockUnorderedEXT:
                   return true;
                 default:
                   return false;
@@ -156,18 +157,18 @@
             return true;
           });
       break;
-    case SpvOpDemoteToHelperInvocationEXT:
+    case spv::Op::OpDemoteToHelperInvocationEXT:
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              SpvExecutionModelFragment,
+              spv::ExecutionModel::Fragment,
               "OpDemoteToHelperInvocationEXT requires Fragment execution "
               "model");
       break;
-    case SpvOpIsHelperInvocationEXT: {
+    case spv::Op::OpIsHelperInvocationEXT: {
       const uint32_t result_type = inst->type_id();
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              SpvExecutionModelFragment,
+              spv::ExecutionModel::Fragment,
               "OpIsHelperInvocationEXT requires Fragment execution model");
       if (!_.IsBoolScalarType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -175,17 +176,17 @@
                << spvOpcodeString(inst->opcode());
       break;
     }
-    case SpvOpReadClockKHR:
+    case spv::Op::OpReadClockKHR:
       if (auto error = ValidateShaderClock(_, inst)) {
         return error;
       }
       break;
-    case SpvOpAssumeTrueKHR:
+    case spv::Op::OpAssumeTrueKHR:
       if (auto error = ValidateAssumeTrue(_, inst)) {
         return error;
       }
       break;
-    case SpvOpExpectKHR:
+    case spv::Op::OpExpectKHR:
       if (auto error = ValidateExpect(_, inst)) {
         return error;
       }
diff --git a/third_party/SPIRV-Tools/source/val/validate_mode_setting.cpp b/third_party/SPIRV-Tools/source/val/validate_mode_setting.cpp
index 67b10c5..dfa4646 100644
--- a/third_party/SPIRV-Tools/source/val/validate_mode_setting.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_mode_setting.cpp
@@ -12,13 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-#include "source/val/validate.h"
-
 #include <algorithm>
 
 #include "source/opcode.h"
 #include "source/spirv_target_env.h"
 #include "source/val/instruction.h"
+#include "source/val/validate.h"
 #include "source/val/validation_state.h"
 
 namespace spvtools {
@@ -28,60 +27,60 @@
 spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) {
   const auto entry_point_id = inst->GetOperandAs<uint32_t>(1);
   auto entry_point = _.FindDef(entry_point_id);
-  if (!entry_point || SpvOpFunction != entry_point->opcode()) {
+  if (!entry_point || spv::Op::OpFunction != entry_point->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpEntryPoint Entry Point <id> '" << _.getIdName(entry_point_id)
-           << "' is not a function.";
+           << "OpEntryPoint Entry Point <id> " << _.getIdName(entry_point_id)
+           << " is not a function.";
   }
 
   // Only check the shader execution models
-  const SpvExecutionModel execution_model =
-      inst->GetOperandAs<SpvExecutionModel>(0);
-  if (execution_model != SpvExecutionModelKernel) {
+  const spv::ExecutionModel execution_model =
+      inst->GetOperandAs<spv::ExecutionModel>(0);
+  if (execution_model != spv::ExecutionModel::Kernel) {
     const auto entry_point_type_id = entry_point->GetOperandAs<uint32_t>(3);
     const auto entry_point_type = _.FindDef(entry_point_type_id);
     if (!entry_point_type || 3 != entry_point_type->words().size()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << _.VkErrorID(4633) << "OpEntryPoint Entry Point <id> '"
+             << _.VkErrorID(4633) << "OpEntryPoint Entry Point <id> "
              << _.getIdName(entry_point_id)
-             << "'s function parameter count is not zero.";
+             << "s function parameter count is not zero.";
     }
   }
 
   auto return_type = _.FindDef(entry_point->type_id());
-  if (!return_type || SpvOpTypeVoid != return_type->opcode()) {
+  if (!return_type || spv::Op::OpTypeVoid != return_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << _.VkErrorID(4633) << "OpEntryPoint Entry Point <id> '"
+           << _.VkErrorID(4633) << "OpEntryPoint Entry Point <id> "
            << _.getIdName(entry_point_id)
-           << "'s function return type is not void.";
+           << "s function return type is not void.";
   }
 
   const auto* execution_modes = _.GetExecutionModes(entry_point_id);
-  if (_.HasCapability(SpvCapabilityShader)) {
+  if (_.HasCapability(spv::Capability::Shader)) {
     switch (execution_model) {
-      case SpvExecutionModelFragment:
+      case spv::ExecutionModel::Fragment:
         if (execution_modes &&
-            execution_modes->count(SpvExecutionModeOriginUpperLeft) &&
-            execution_modes->count(SpvExecutionModeOriginLowerLeft)) {
+            execution_modes->count(spv::ExecutionMode::OriginUpperLeft) &&
+            execution_modes->count(spv::ExecutionMode::OriginLowerLeft)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Fragment execution model entry points can only specify "
                     "one of OriginUpperLeft or OriginLowerLeft execution "
                     "modes.";
         }
         if (!execution_modes ||
-            (!execution_modes->count(SpvExecutionModeOriginUpperLeft) &&
-             !execution_modes->count(SpvExecutionModeOriginLowerLeft))) {
+            (!execution_modes->count(spv::ExecutionMode::OriginUpperLeft) &&
+             !execution_modes->count(spv::ExecutionMode::OriginLowerLeft))) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Fragment execution model entry points require either an "
                     "OriginUpperLeft or OriginLowerLeft execution mode.";
         }
         if (execution_modes &&
             1 < std::count_if(execution_modes->begin(), execution_modes->end(),
-                              [](const SpvExecutionMode& mode) {
+                              [](const spv::ExecutionMode& mode) {
                                 switch (mode) {
-                                  case SpvExecutionModeDepthGreater:
-                                  case SpvExecutionModeDepthLess:
-                                  case SpvExecutionModeDepthUnchanged:
+                                  case spv::ExecutionMode::DepthGreater:
+                                  case spv::ExecutionMode::DepthLess:
+                                  case spv::ExecutionMode::DepthUnchanged:
                                     return true;
                                   default:
                                     return false;
@@ -95,14 +94,15 @@
         if (execution_modes &&
             1 < std::count_if(
                     execution_modes->begin(), execution_modes->end(),
-                    [](const SpvExecutionMode& mode) {
+                    [](const spv::ExecutionMode& mode) {
                       switch (mode) {
-                        case SpvExecutionModePixelInterlockOrderedEXT:
-                        case SpvExecutionModePixelInterlockUnorderedEXT:
-                        case SpvExecutionModeSampleInterlockOrderedEXT:
-                        case SpvExecutionModeSampleInterlockUnorderedEXT:
-                        case SpvExecutionModeShadingRateInterlockOrderedEXT:
-                        case SpvExecutionModeShadingRateInterlockUnorderedEXT:
+                        case spv::ExecutionMode::PixelInterlockOrderedEXT:
+                        case spv::ExecutionMode::PixelInterlockUnorderedEXT:
+                        case spv::ExecutionMode::SampleInterlockOrderedEXT:
+                        case spv::ExecutionMode::SampleInterlockUnorderedEXT:
+                        case spv::ExecutionMode::ShadingRateInterlockOrderedEXT:
+                        case spv::ExecutionMode::
+                            ShadingRateInterlockUnorderedEXT:
                           return true;
                         default:
                           return false;
@@ -115,11 +115,11 @@
         if (execution_modes &&
             1 < std::count_if(
                     execution_modes->begin(), execution_modes->end(),
-                    [](const SpvExecutionMode& mode) {
+                    [](const spv::ExecutionMode& mode) {
                       switch (mode) {
-                        case SpvExecutionModeStencilRefUnchangedFrontAMD:
-                        case SpvExecutionModeStencilRefLessFrontAMD:
-                        case SpvExecutionModeStencilRefGreaterFrontAMD:
+                        case spv::ExecutionMode::StencilRefUnchangedFrontAMD:
+                        case spv::ExecutionMode::StencilRefLessFrontAMD:
+                        case spv::ExecutionMode::StencilRefGreaterFrontAMD:
                           return true;
                         default:
                           return false;
@@ -134,11 +134,11 @@
         if (execution_modes &&
             1 < std::count_if(
                     execution_modes->begin(), execution_modes->end(),
-                    [](const SpvExecutionMode& mode) {
+                    [](const spv::ExecutionMode& mode) {
                       switch (mode) {
-                        case SpvExecutionModeStencilRefUnchangedBackAMD:
-                        case SpvExecutionModeStencilRefLessBackAMD:
-                        case SpvExecutionModeStencilRefGreaterBackAMD:
+                        case spv::ExecutionMode::StencilRefUnchangedBackAMD:
+                        case spv::ExecutionMode::StencilRefLessBackAMD:
+                        case spv::ExecutionMode::StencilRefGreaterBackAMD:
                           return true;
                         default:
                           return false;
@@ -151,20 +151,21 @@
                     "execution modes.";
         }
         break;
-      case SpvExecutionModelTessellationControl:
-      case SpvExecutionModelTessellationEvaluation:
+      case spv::ExecutionModel::TessellationControl:
+      case spv::ExecutionModel::TessellationEvaluation:
         if (execution_modes &&
-            1 < std::count_if(execution_modes->begin(), execution_modes->end(),
-                              [](const SpvExecutionMode& mode) {
-                                switch (mode) {
-                                  case SpvExecutionModeSpacingEqual:
-                                  case SpvExecutionModeSpacingFractionalEven:
-                                  case SpvExecutionModeSpacingFractionalOdd:
-                                    return true;
-                                  default:
-                                    return false;
-                                }
-                              })) {
+            1 < std::count_if(
+                    execution_modes->begin(), execution_modes->end(),
+                    [](const spv::ExecutionMode& mode) {
+                      switch (mode) {
+                        case spv::ExecutionMode::SpacingEqual:
+                        case spv::ExecutionMode::SpacingFractionalEven:
+                        case spv::ExecutionMode::SpacingFractionalOdd:
+                          return true;
+                        default:
+                          return false;
+                      }
+                    })) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Tessellation execution model entry points can specify at "
                     "most one of SpacingEqual, SpacingFractionalOdd or "
@@ -172,11 +173,11 @@
         }
         if (execution_modes &&
             1 < std::count_if(execution_modes->begin(), execution_modes->end(),
-                              [](const SpvExecutionMode& mode) {
+                              [](const spv::ExecutionMode& mode) {
                                 switch (mode) {
-                                  case SpvExecutionModeTriangles:
-                                  case SpvExecutionModeQuads:
-                                  case SpvExecutionModeIsolines:
+                                  case spv::ExecutionMode::Triangles:
+                                  case spv::ExecutionMode::Quads:
+                                  case spv::ExecutionMode::Isolines:
                                     return true;
                                   default:
                                     return false;
@@ -188,10 +189,10 @@
         }
         if (execution_modes &&
             1 < std::count_if(execution_modes->begin(), execution_modes->end(),
-                              [](const SpvExecutionMode& mode) {
+                              [](const spv::ExecutionMode& mode) {
                                 switch (mode) {
-                                  case SpvExecutionModeVertexOrderCw:
-                                  case SpvExecutionModeVertexOrderCcw:
+                                  case spv::ExecutionMode::VertexOrderCw:
+                                  case spv::ExecutionMode::VertexOrderCcw:
                                     return true;
                                   default:
                                     return false;
@@ -203,21 +204,22 @@
                     "modes.";
         }
         break;
-      case SpvExecutionModelGeometry:
+      case spv::ExecutionModel::Geometry:
         if (!execution_modes ||
-            1 != std::count_if(execution_modes->begin(), execution_modes->end(),
-                               [](const SpvExecutionMode& mode) {
-                                 switch (mode) {
-                                   case SpvExecutionModeInputPoints:
-                                   case SpvExecutionModeInputLines:
-                                   case SpvExecutionModeInputLinesAdjacency:
-                                   case SpvExecutionModeTriangles:
-                                   case SpvExecutionModeInputTrianglesAdjacency:
-                                     return true;
-                                   default:
-                                     return false;
-                                 }
-                               })) {
+            1 != std::count_if(
+                     execution_modes->begin(), execution_modes->end(),
+                     [](const spv::ExecutionMode& mode) {
+                       switch (mode) {
+                         case spv::ExecutionMode::InputPoints:
+                         case spv::ExecutionMode::InputLines:
+                         case spv::ExecutionMode::InputLinesAdjacency:
+                         case spv::ExecutionMode::Triangles:
+                         case spv::ExecutionMode::InputTrianglesAdjacency:
+                           return true;
+                         default:
+                           return false;
+                       }
+                     })) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Geometry execution model entry points must specify "
                     "exactly one of InputPoints, InputLines, "
@@ -226,11 +228,11 @@
         }
         if (!execution_modes ||
             1 != std::count_if(execution_modes->begin(), execution_modes->end(),
-                               [](const SpvExecutionMode& mode) {
+                               [](const spv::ExecutionMode& mode) {
                                  switch (mode) {
-                                   case SpvExecutionModeOutputPoints:
-                                   case SpvExecutionModeOutputLineStrip:
-                                   case SpvExecutionModeOutputTriangleStrip:
+                                   case spv::ExecutionMode::OutputPoints:
+                                   case spv::ExecutionMode::OutputLineStrip:
+                                   case spv::ExecutionMode::OutputTriangleStrip:
                                      return true;
                                    default:
                                      return false;
@@ -242,6 +244,39 @@
                     "OutputTriangleStrip execution modes.";
         }
         break;
+      case spv::ExecutionModel::MeshEXT:
+        if (!execution_modes ||
+            1 != std::count_if(execution_modes->begin(), execution_modes->end(),
+                               [](const spv::ExecutionMode& mode) {
+                                 switch (mode) {
+                                   case spv::ExecutionMode::OutputPoints:
+                                   case spv::ExecutionMode::OutputLinesEXT:
+                                   case spv::ExecutionMode::OutputTrianglesEXT:
+                                     return true;
+                                   default:
+                                     return false;
+                                 }
+                               })) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "MeshEXT execution model entry points must specify exactly "
+                    "one of OutputPoints, OutputLinesEXT, or "
+                    "OutputTrianglesEXT Execution Modes.";
+        } else if (2 != std::count_if(
+                            execution_modes->begin(), execution_modes->end(),
+                            [](const spv::ExecutionMode& mode) {
+                              switch (mode) {
+                                case spv::ExecutionMode::OutputPrimitivesEXT:
+                                case spv::ExecutionMode::OutputVertices:
+                                  return true;
+                                default:
+                                  return false;
+                              }
+                            })) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "MeshEXT execution model entry points must specify both "
+                    "OutputPrimitivesEXT and OutputVertices Execution Modes.";
+        }
+        break;
       default:
         break;
     }
@@ -249,23 +284,25 @@
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
     switch (execution_model) {
-      case SpvExecutionModelGLCompute:
+      case spv::ExecutionModel::GLCompute:
         if (!execution_modes ||
-            !execution_modes->count(SpvExecutionModeLocalSize)) {
+            !execution_modes->count(spv::ExecutionMode::LocalSize)) {
           bool ok = false;
           for (auto& i : _.ordered_instructions()) {
-            if (i.opcode() == SpvOpDecorate) {
+            if (i.opcode() == spv::Op::OpDecorate) {
               if (i.operands().size() > 2) {
-                if (i.GetOperandAs<SpvDecoration>(1) == SpvDecorationBuiltIn &&
-                    i.GetOperandAs<SpvBuiltIn>(2) == SpvBuiltInWorkgroupSize) {
+                if (i.GetOperandAs<spv::Decoration>(1) ==
+                        spv::Decoration::BuiltIn &&
+                    i.GetOperandAs<spv::BuiltIn>(2) ==
+                        spv::BuiltIn::WorkgroupSize) {
                   ok = true;
                   break;
                 }
               }
             }
-            if (i.opcode() == SpvOpExecutionModeId) {
-              const auto mode = i.GetOperandAs<SpvExecutionMode>(1);
-              if (mode == SpvExecutionModeLocalSizeId) {
+            if (i.opcode() == spv::Op::OpExecutionModeId) {
+              const auto mode = i.GetOperandAs<spv::ExecutionMode>(1);
+              if (mode == spv::ExecutionMode::LocalSizeId) {
                 ok = true;
                 break;
               }
@@ -296,21 +333,20 @@
                                _.entry_points().cend(), entry_point_id);
   if (found == _.entry_points().cend()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpExecutionMode Entry Point <id> '"
-           << _.getIdName(entry_point_id)
-           << "' is not the Entry Point "
+           << "OpExecutionMode Entry Point <id> " << _.getIdName(entry_point_id)
+           << " is not the Entry Point "
               "operand of an OpEntryPoint.";
   }
 
-  const auto mode = inst->GetOperandAs<SpvExecutionMode>(1);
-  if (inst->opcode() == SpvOpExecutionModeId) {
+  const auto mode = inst->GetOperandAs<spv::ExecutionMode>(1);
+  if (inst->opcode() == spv::Op::OpExecutionModeId) {
     size_t operand_count = inst->operands().size();
     for (size_t i = 2; i < operand_count; ++i) {
       const auto operand_id = inst->GetOperandAs<uint32_t>(2);
       const auto* operand_inst = _.FindDef(operand_id);
-      if (mode == SpvExecutionModeSubgroupsPerWorkgroupId ||
-          mode == SpvExecutionModeLocalSizeHintId ||
-          mode == SpvExecutionModeLocalSizeId) {
+      if (mode == spv::ExecutionMode::SubgroupsPerWorkgroupId ||
+          mode == spv::ExecutionMode::LocalSizeHintId ||
+          mode == spv::ExecutionMode::LocalSizeId) {
         if (!spvOpcodeIsConstant(operand_inst->opcode())) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << "For OpExecutionModeId all Extra Operand ids must be "
@@ -324,9 +360,9 @@
                   "operands.";
       }
     }
-  } else if (mode == SpvExecutionModeSubgroupsPerWorkgroupId ||
-             mode == SpvExecutionModeLocalSizeHintId ||
-             mode == SpvExecutionModeLocalSizeId) {
+  } else if (mode == spv::ExecutionMode::SubgroupsPerWorkgroupId ||
+             mode == spv::ExecutionMode::LocalSizeHintId ||
+             mode == spv::ExecutionMode::LocalSizeId) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "OpExecutionMode is only valid when the Mode operand is an "
               "execution mode that takes no Extra Operands, or takes Extra "
@@ -335,38 +371,42 @@
 
   const auto* models = _.GetExecutionModels(entry_point_id);
   switch (mode) {
-    case SpvExecutionModeInvocations:
-    case SpvExecutionModeInputPoints:
-    case SpvExecutionModeInputLines:
-    case SpvExecutionModeInputLinesAdjacency:
-    case SpvExecutionModeInputTrianglesAdjacency:
-    case SpvExecutionModeOutputLineStrip:
-    case SpvExecutionModeOutputTriangleStrip:
+    case spv::ExecutionMode::Invocations:
+    case spv::ExecutionMode::InputPoints:
+    case spv::ExecutionMode::InputLines:
+    case spv::ExecutionMode::InputLinesAdjacency:
+    case spv::ExecutionMode::InputTrianglesAdjacency:
+    case spv::ExecutionMode::OutputLineStrip:
+    case spv::ExecutionMode::OutputTriangleStrip:
       if (!std::all_of(models->begin(), models->end(),
-                       [](const SpvExecutionModel& model) {
-                         return model == SpvExecutionModelGeometry;
+                       [](const spv::ExecutionModel& model) {
+                         return model == spv::ExecutionModel::Geometry;
                        })) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Execution mode can only be used with the Geometry execution "
                   "model.";
       }
       break;
-    case SpvExecutionModeOutputPoints:
-      if (!std::all_of(models->begin(), models->end(),
-                       [&_](const SpvExecutionModel& model) {
-                         switch (model) {
-                           case SpvExecutionModelGeometry:
-                             return true;
-                           case SpvExecutionModelMeshNV:
-                             return _.HasCapability(SpvCapabilityMeshShadingNV);
-                           default:
-                             return false;
-                         }
-                       })) {
-        if (_.HasCapability(SpvCapabilityMeshShadingNV)) {
+    case spv::ExecutionMode::OutputPoints:
+      if (!std::all_of(
+              models->begin(), models->end(),
+              [&_](const spv::ExecutionModel& model) {
+                switch (model) {
+                  case spv::ExecutionModel::Geometry:
+                    return true;
+                  case spv::ExecutionModel::MeshNV:
+                    return _.HasCapability(spv::Capability::MeshShadingNV);
+                  case spv::ExecutionModel::MeshEXT:
+                    return _.HasCapability(spv::Capability::MeshShadingEXT);
+                  default:
+                    return false;
+                }
+              })) {
+        if (_.HasCapability(spv::Capability::MeshShadingNV) ||
+            _.HasCapability(spv::Capability::MeshShadingEXT)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                 << "Execution mode can only be used with the Geometry or "
-                    "MeshNV execution model.";
+                 << "Execution mode can only be used with the Geometry "
+                    "MeshNV or MeshEXT execution model.";
         } else {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Execution mode can only be used with the Geometry "
@@ -375,32 +415,32 @@
         }
       }
       break;
-    case SpvExecutionModeSpacingEqual:
-    case SpvExecutionModeSpacingFractionalEven:
-    case SpvExecutionModeSpacingFractionalOdd:
-    case SpvExecutionModeVertexOrderCw:
-    case SpvExecutionModeVertexOrderCcw:
-    case SpvExecutionModePointMode:
-    case SpvExecutionModeQuads:
-    case SpvExecutionModeIsolines:
+    case spv::ExecutionMode::SpacingEqual:
+    case spv::ExecutionMode::SpacingFractionalEven:
+    case spv::ExecutionMode::SpacingFractionalOdd:
+    case spv::ExecutionMode::VertexOrderCw:
+    case spv::ExecutionMode::VertexOrderCcw:
+    case spv::ExecutionMode::PointMode:
+    case spv::ExecutionMode::Quads:
+    case spv::ExecutionMode::Isolines:
       if (!std::all_of(
               models->begin(), models->end(),
-              [](const SpvExecutionModel& model) {
-                return (model == SpvExecutionModelTessellationControl) ||
-                       (model == SpvExecutionModelTessellationEvaluation);
+              [](const spv::ExecutionModel& model) {
+                return (model == spv::ExecutionModel::TessellationControl) ||
+                       (model == spv::ExecutionModel::TessellationEvaluation);
               })) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Execution mode can only be used with a tessellation "
                   "execution model.";
       }
       break;
-    case SpvExecutionModeTriangles:
+    case spv::ExecutionMode::Triangles:
       if (!std::all_of(models->begin(), models->end(),
-                       [](const SpvExecutionModel& model) {
+                       [](const spv::ExecutionModel& model) {
                          switch (model) {
-                           case SpvExecutionModelGeometry:
-                           case SpvExecutionModelTessellationControl:
-                           case SpvExecutionModelTessellationEvaluation:
+                           case spv::ExecutionModel::Geometry:
+                           case spv::ExecutionModel::TessellationControl:
+                           case spv::ExecutionModel::TessellationEvaluation:
                              return true;
                            default:
                              return false;
@@ -411,24 +451,28 @@
                   "tessellation execution model.";
       }
       break;
-    case SpvExecutionModeOutputVertices:
-      if (!std::all_of(models->begin(), models->end(),
-                       [&_](const SpvExecutionModel& model) {
-                         switch (model) {
-                           case SpvExecutionModelGeometry:
-                           case SpvExecutionModelTessellationControl:
-                           case SpvExecutionModelTessellationEvaluation:
-                             return true;
-                           case SpvExecutionModelMeshNV:
-                             return _.HasCapability(SpvCapabilityMeshShadingNV);
-                           default:
-                             return false;
-                         }
-                       })) {
-        if (_.HasCapability(SpvCapabilityMeshShadingNV)) {
+    case spv::ExecutionMode::OutputVertices:
+      if (!std::all_of(
+              models->begin(), models->end(),
+              [&_](const spv::ExecutionModel& model) {
+                switch (model) {
+                  case spv::ExecutionModel::Geometry:
+                  case spv::ExecutionModel::TessellationControl:
+                  case spv::ExecutionModel::TessellationEvaluation:
+                    return true;
+                  case spv::ExecutionModel::MeshNV:
+                    return _.HasCapability(spv::Capability::MeshShadingNV);
+                  case spv::ExecutionModel::MeshEXT:
+                    return _.HasCapability(spv::Capability::MeshShadingEXT);
+                  default:
+                    return false;
+                }
+              })) {
+        if (_.HasCapability(spv::Capability::MeshShadingNV) ||
+            _.HasCapability(spv::Capability::MeshShadingEXT)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Execution mode can only be used with a Geometry, "
-                    "tessellation or MeshNV execution model.";
+                    "tessellation, MeshNV or MeshEXT execution model.";
         } else {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Execution mode can only be used with a Geometry or "
@@ -436,72 +480,91 @@
         }
       }
       break;
-    case SpvExecutionModePixelCenterInteger:
-    case SpvExecutionModeOriginUpperLeft:
-    case SpvExecutionModeOriginLowerLeft:
-    case SpvExecutionModeEarlyFragmentTests:
-    case SpvExecutionModeDepthReplacing:
-    case SpvExecutionModeDepthGreater:
-    case SpvExecutionModeDepthLess:
-    case SpvExecutionModeDepthUnchanged:
-    case SpvExecutionModePixelInterlockOrderedEXT:
-    case SpvExecutionModePixelInterlockUnorderedEXT:
-    case SpvExecutionModeSampleInterlockOrderedEXT:
-    case SpvExecutionModeSampleInterlockUnorderedEXT:
-    case SpvExecutionModeShadingRateInterlockOrderedEXT:
-    case SpvExecutionModeShadingRateInterlockUnorderedEXT:
-    case SpvExecutionModeEarlyAndLateFragmentTestsAMD:
-    case SpvExecutionModeStencilRefUnchangedFrontAMD:
-    case SpvExecutionModeStencilRefGreaterFrontAMD:
-    case SpvExecutionModeStencilRefLessFrontAMD:
-    case SpvExecutionModeStencilRefUnchangedBackAMD:
-    case SpvExecutionModeStencilRefGreaterBackAMD:
-    case SpvExecutionModeStencilRefLessBackAMD:
+    case spv::ExecutionMode::OutputLinesEXT:
+    case spv::ExecutionMode::OutputTrianglesEXT:
+    case spv::ExecutionMode::OutputPrimitivesEXT:
       if (!std::all_of(models->begin(), models->end(),
-                       [](const SpvExecutionModel& model) {
-                         return model == SpvExecutionModelFragment;
+                       [](const spv::ExecutionModel& model) {
+                         return (model == spv::ExecutionModel::MeshEXT ||
+                                 model == spv::ExecutionModel::MeshNV);
+                       })) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Execution mode can only be used with the MeshEXT or MeshNV "
+                  "execution "
+                  "model.";
+      }
+      break;
+    case spv::ExecutionMode::PixelCenterInteger:
+    case spv::ExecutionMode::OriginUpperLeft:
+    case spv::ExecutionMode::OriginLowerLeft:
+    case spv::ExecutionMode::EarlyFragmentTests:
+    case spv::ExecutionMode::DepthReplacing:
+    case spv::ExecutionMode::DepthGreater:
+    case spv::ExecutionMode::DepthLess:
+    case spv::ExecutionMode::DepthUnchanged:
+    case spv::ExecutionMode::PixelInterlockOrderedEXT:
+    case spv::ExecutionMode::PixelInterlockUnorderedEXT:
+    case spv::ExecutionMode::SampleInterlockOrderedEXT:
+    case spv::ExecutionMode::SampleInterlockUnorderedEXT:
+    case spv::ExecutionMode::ShadingRateInterlockOrderedEXT:
+    case spv::ExecutionMode::ShadingRateInterlockUnorderedEXT:
+    case spv::ExecutionMode::EarlyAndLateFragmentTestsAMD:
+    case spv::ExecutionMode::StencilRefUnchangedFrontAMD:
+    case spv::ExecutionMode::StencilRefGreaterFrontAMD:
+    case spv::ExecutionMode::StencilRefLessFrontAMD:
+    case spv::ExecutionMode::StencilRefUnchangedBackAMD:
+    case spv::ExecutionMode::StencilRefGreaterBackAMD:
+    case spv::ExecutionMode::StencilRefLessBackAMD:
+      if (!std::all_of(models->begin(), models->end(),
+                       [](const spv::ExecutionModel& model) {
+                         return model == spv::ExecutionModel::Fragment;
                        })) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Execution mode can only be used with the Fragment execution "
                   "model.";
       }
       break;
-    case SpvExecutionModeLocalSizeHint:
-    case SpvExecutionModeVecTypeHint:
-    case SpvExecutionModeContractionOff:
-    case SpvExecutionModeLocalSizeHintId:
+    case spv::ExecutionMode::LocalSizeHint:
+    case spv::ExecutionMode::VecTypeHint:
+    case spv::ExecutionMode::ContractionOff:
+    case spv::ExecutionMode::LocalSizeHintId:
       if (!std::all_of(models->begin(), models->end(),
-                       [](const SpvExecutionModel& model) {
-                         return model == SpvExecutionModelKernel;
+                       [](const spv::ExecutionModel& model) {
+                         return model == spv::ExecutionModel::Kernel;
                        })) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Execution mode can only be used with the Kernel execution "
                   "model.";
       }
       break;
-    case SpvExecutionModeLocalSize:
-    case SpvExecutionModeLocalSizeId:
-      if (mode == SpvExecutionModeLocalSizeId && !_.IsLocalSizeIdAllowed())
+    case spv::ExecutionMode::LocalSize:
+    case spv::ExecutionMode::LocalSizeId:
+      if (mode == spv::ExecutionMode::LocalSizeId && !_.IsLocalSizeIdAllowed())
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "LocalSizeId mode is not allowed by the current environment.";
 
-      if (!std::all_of(models->begin(), models->end(),
-                       [&_](const SpvExecutionModel& model) {
-                         switch (model) {
-                           case SpvExecutionModelKernel:
-                           case SpvExecutionModelGLCompute:
-                             return true;
-                           case SpvExecutionModelTaskNV:
-                           case SpvExecutionModelMeshNV:
-                             return _.HasCapability(SpvCapabilityMeshShadingNV);
-                           default:
-                             return false;
-                         }
-                       })) {
-        if (_.HasCapability(SpvCapabilityMeshShadingNV)) {
+      if (!std::all_of(
+              models->begin(), models->end(),
+              [&_](const spv::ExecutionModel& model) {
+                switch (model) {
+                  case spv::ExecutionModel::Kernel:
+                  case spv::ExecutionModel::GLCompute:
+                    return true;
+                  case spv::ExecutionModel::TaskNV:
+                  case spv::ExecutionModel::MeshNV:
+                    return _.HasCapability(spv::Capability::MeshShadingNV);
+                  case spv::ExecutionModel::TaskEXT:
+                  case spv::ExecutionModel::MeshEXT:
+                    return _.HasCapability(spv::Capability::MeshShadingEXT);
+                  default:
+                    return false;
+                }
+              })) {
+        if (_.HasCapability(spv::Capability::MeshShadingNV) ||
+            _.HasCapability(spv::Capability::MeshShadingEXT)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Execution mode can only be used with a Kernel, GLCompute, "
-                    "MeshNV, or TaskNV execution model.";
+                    "MeshNV, MeshEXT, TaskNV or TaskEXT execution model.";
         } else {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Execution mode can only be used with a Kernel or "
@@ -514,13 +577,13 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (mode == SpvExecutionModeOriginLowerLeft) {
+    if (mode == spv::ExecutionMode::OriginLowerLeft) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4653)
              << "In the Vulkan environment, the OriginLowerLeft execution mode "
                 "must not be used.";
     }
-    if (mode == SpvExecutionModePixelCenterInteger) {
+    if (mode == spv::ExecutionMode::PixelCenterInteger) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4654)
              << "In the Vulkan environment, the PixelCenterInteger execution "
@@ -535,29 +598,30 @@
                                  const Instruction* inst) {
   // Already produced an error if multiple memory model instructions are
   // present.
-  if (_.memory_model() != SpvMemoryModelVulkanKHR &&
-      _.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (_.memory_model() != spv::MemoryModel::VulkanKHR &&
+      _.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "VulkanMemoryModelKHR capability must only be specified if "
               "the VulkanKHR memory model is used.";
   }
 
   if (spvIsOpenCLEnv(_.context()->target_env)) {
-    if ((_.addressing_model() != SpvAddressingModelPhysical32) &&
-        (_.addressing_model() != SpvAddressingModelPhysical64)) {
+    if ((_.addressing_model() != spv::AddressingModel::Physical32) &&
+        (_.addressing_model() != spv::AddressingModel::Physical64)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Addressing model must be Physical32 or Physical64 "
              << "in the OpenCL environment.";
     }
-    if (_.memory_model() != SpvMemoryModelOpenCL) {
+    if (_.memory_model() != spv::MemoryModel::OpenCL) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Memory model must be OpenCL in the OpenCL environment.";
     }
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if ((_.addressing_model() != SpvAddressingModelLogical) &&
-        (_.addressing_model() != SpvAddressingModelPhysicalStorageBuffer64)) {
+    if ((_.addressing_model() != spv::AddressingModel::Logical) &&
+        (_.addressing_model() !=
+         spv::AddressingModel::PhysicalStorageBuffer64)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4635)
              << "Addressing model must be Logical or PhysicalStorageBuffer64 "
@@ -571,14 +635,14 @@
 
 spv_result_t ModeSettingPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpEntryPoint:
+    case spv::Op::OpEntryPoint:
       if (auto error = ValidateEntryPoint(_, inst)) return error;
       break;
-    case SpvOpExecutionMode:
-    case SpvOpExecutionModeId:
+    case spv::Op::OpExecutionMode:
+    case spv::Op::OpExecutionModeId:
       if (auto error = ValidateExecutionMode(_, inst)) return error;
       break;
-    case SpvOpMemoryModel:
+    case spv::Op::OpMemoryModel:
       if (auto error = ValidateMemoryModel(_, inst)) return error;
       break;
     default:
diff --git a/third_party/SPIRV-Tools/source/val/validate_non_uniform.cpp b/third_party/SPIRV-Tools/source/val/validate_non_uniform.cpp
index 6d4f8a2..5c5e9bd 100644
--- a/third_party/SPIRV-Tools/source/val/validate_non_uniform.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_non_uniform.cpp
@@ -48,11 +48,11 @@
                                                    "of integer type scalar";
   }
 
-  const auto group = inst->GetOperandAs<uint32_t>(3);
+  const auto group = inst->GetOperandAs<spv::GroupOperation>(3);
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if ((group != SpvGroupOperationReduce) &&
-        (group != SpvGroupOperationInclusiveScan) &&
-        (group != SpvGroupOperationExclusiveScan)) {
+    if ((group != spv::GroupOperation::Reduce) &&
+        (group != spv::GroupOperation::InclusiveScan) &&
+        (group != spv::GroupOperation::ExclusiveScan)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4685)
              << "In Vulkan: The OpGroupNonUniformBallotBitCount group "
@@ -120,7 +120,7 @@
 
 // Validates correctness of non-uniform group instructions.
 spv_result_t NonUniformPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   if (spvOpcodeIsNonUniformGroupOperation(opcode)) {
     const uint32_t execution_scope = inst->word(3);
@@ -130,9 +130,9 @@
   }
 
   switch (opcode) {
-    case SpvOpGroupNonUniformBallotBitCount:
+    case spv::Op::OpGroupNonUniformBallotBitCount:
       return ValidateGroupNonUniformBallotBitCount(_, inst);
-    case SpvOpGroupNonUniformRotateKHR:
+    case spv::Op::OpGroupNonUniformRotateKHR:
       return ValidateGroupNonUniformRotateKHR(_, inst);
     default:
       break;
diff --git a/third_party/SPIRV-Tools/source/val/validate_primitives.cpp b/third_party/SPIRV-Tools/source/val/validate_primitives.cpp
index 7d11f2e..5e598c3 100644
--- a/third_party/SPIRV-Tools/source/val/validate_primitives.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_primitives.cpp
@@ -28,16 +28,16 @@
 
 // Validates correctness of primitive instructions.
 spv_result_t PrimitivesPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   switch (opcode) {
-    case SpvOpEmitVertex:
-    case SpvOpEndPrimitive:
-    case SpvOpEmitStreamVertex:
-    case SpvOpEndStreamPrimitive:
+    case spv::Op::OpEmitVertex:
+    case spv::Op::OpEndPrimitive:
+    case spv::Op::OpEmitStreamVertex:
+    case spv::Op::OpEndStreamPrimitive:
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              SpvExecutionModelGeometry,
+              spv::ExecutionModel::Geometry,
               std::string(spvOpcodeString(opcode)) +
                   " instructions require Geometry execution model");
       break;
@@ -46,8 +46,8 @@
   }
 
   switch (opcode) {
-    case SpvOpEmitStreamVertex:
-    case SpvOpEndStreamPrimitive: {
+    case spv::Op::OpEmitStreamVertex:
+    case spv::Op::OpEndStreamPrimitive: {
       const uint32_t stream_id = inst->word(1);
       const uint32_t stream_type = _.GetTypeId(stream_id);
       if (!_.IsIntScalarType(stream_type)) {
@@ -56,7 +56,7 @@
                << ": expected Stream to be int scalar";
       }
 
-      const SpvOp stream_opcode = _.GetIdOpcode(stream_id);
+      const spv::Op stream_opcode = _.GetIdOpcode(stream_id);
       if (!spvOpcodeIsConstant(stream_opcode)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
diff --git a/third_party/SPIRV-Tools/source/val/validate_ray_query.cpp b/third_party/SPIRV-Tools/source/val/validate_ray_query.cpp
index f92bf01..9b67fc9 100644
--- a/third_party/SPIRV-Tools/source/val/validate_ray_query.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_ray_query.cpp
@@ -28,18 +28,20 @@
                                      uint32_t ray_query_index) {
   const uint32_t ray_query_id = inst->GetOperandAs<uint32_t>(ray_query_index);
   auto variable = _.FindDef(ray_query_id);
-  if (!variable || (variable->opcode() != SpvOpVariable &&
-                    variable->opcode() != SpvOpFunctionParameter)) {
+  const auto var_opcode = variable->opcode();
+  if (!variable || (var_opcode != spv::Op::OpVariable &&
+                    var_opcode != spv::Op::OpFunctionParameter &&
+                    var_opcode != spv::Op::OpAccessChain)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Ray Query must be a memory object declaration";
   }
   auto pointer = _.FindDef(variable->GetOperandAs<uint32_t>(0));
-  if (!pointer || pointer->opcode() != SpvOpTypePointer) {
+  if (!pointer || pointer->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Ray Query must be a pointer";
   }
   auto type = _.FindDef(pointer->GetOperandAs<uint32_t>(2));
-  if (!type || type->opcode() != SpvOpTypeRayQueryKHR) {
+  if (!type || type->opcode() != spv::Op::OpTypeRayQueryKHR) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Ray Query must be a pointer to OpTypeRayQueryKHR";
   }
@@ -52,7 +54,7 @@
   const uint32_t intersection_id =
       inst->GetOperandAs<uint32_t>(intersection_index);
   const uint32_t intersection_type = _.GetTypeId(intersection_id);
-  const SpvOp intersection_opcode = _.GetIdOpcode(intersection_id);
+  const spv::Op intersection_opcode = _.GetIdOpcode(intersection_id);
   if (!_.IsIntScalarType(intersection_type) ||
       _.GetBitWidth(intersection_type) != 32 ||
       !spvOpcodeIsConstant(intersection_opcode)) {
@@ -66,15 +68,15 @@
 }  // namespace
 
 spv_result_t RayQueryPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpRayQueryInitializeKHR: {
+    case spv::Op::OpRayQueryInitializeKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 0)) return error;
 
       if (_.GetIdOpcode(_.GetOperandTypeId(inst, 1)) !=
-          SpvOpTypeAccelerationStructureKHR) {
+          spv::Op::OpTypeAccelerationStructureKHR) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Acceleration Structure to be of type "
                   "OpTypeAccelerationStructureKHR";
@@ -121,13 +123,13 @@
       break;
     }
 
-    case SpvOpRayQueryTerminateKHR:
-    case SpvOpRayQueryConfirmIntersectionKHR: {
+    case spv::Op::OpRayQueryTerminateKHR:
+    case spv::Op::OpRayQueryConfirmIntersectionKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 0)) return error;
       break;
     }
 
-    case SpvOpRayQueryGenerateIntersectionKHR: {
+    case spv::Op::OpRayQueryGenerateIntersectionKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 0)) return error;
 
       const uint32_t hit_t_id = _.GetOperandTypeId(inst, 1);
@@ -139,9 +141,9 @@
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionFrontFaceKHR:
-    case SpvOpRayQueryProceedKHR:
-    case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: {
+    case spv::Op::OpRayQueryGetIntersectionFrontFaceKHR:
+    case spv::Op::OpRayQueryProceedKHR:
+    case spv::Op::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
 
       if (!_.IsBoolScalarType(result_type)) {
@@ -149,15 +151,15 @@
                << "expected Result Type to be bool scalar type";
       }
 
-      if (opcode == SpvOpRayQueryGetIntersectionFrontFaceKHR) {
+      if (opcode == spv::Op::OpRayQueryGetIntersectionFrontFaceKHR) {
         if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
       }
 
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionTKHR:
-    case SpvOpRayQueryGetRayTMinKHR: {
+    case spv::Op::OpRayQueryGetIntersectionTKHR:
+    case spv::Op::OpRayQueryGetRayTMinKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
 
       if (!_.IsFloatScalarType(result_type) ||
@@ -166,20 +168,21 @@
                << "expected Result Type to be 32-bit float scalar type";
       }
 
-      if (opcode == SpvOpRayQueryGetIntersectionTKHR) {
+      if (opcode == spv::Op::OpRayQueryGetIntersectionTKHR) {
         if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
       }
 
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionTypeKHR:
-    case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR:
-    case SpvOpRayQueryGetIntersectionInstanceIdKHR:
-    case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR:
-    case SpvOpRayQueryGetIntersectionGeometryIndexKHR:
-    case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR:
-    case SpvOpRayQueryGetRayFlagsKHR: {
+    case spv::Op::OpRayQueryGetIntersectionTypeKHR:
+    case spv::Op::OpRayQueryGetIntersectionInstanceCustomIndexKHR:
+    case spv::Op::OpRayQueryGetIntersectionInstanceIdKHR:
+    case spv::Op::
+        OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR:
+    case spv::Op::OpRayQueryGetIntersectionGeometryIndexKHR:
+    case spv::Op::OpRayQueryGetIntersectionPrimitiveIndexKHR:
+    case spv::Op::OpRayQueryGetRayFlagsKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
 
       if (!_.IsIntScalarType(result_type) || _.GetBitWidth(result_type) != 32) {
@@ -187,17 +190,17 @@
                << "expected Result Type to be 32-bit int scalar type";
       }
 
-      if (opcode != SpvOpRayQueryGetRayFlagsKHR) {
+      if (opcode != spv::Op::OpRayQueryGetRayFlagsKHR) {
         if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
       }
 
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR:
-    case SpvOpRayQueryGetIntersectionObjectRayOriginKHR:
-    case SpvOpRayQueryGetWorldRayDirectionKHR:
-    case SpvOpRayQueryGetWorldRayOriginKHR: {
+    case spv::Op::OpRayQueryGetIntersectionObjectRayDirectionKHR:
+    case spv::Op::OpRayQueryGetIntersectionObjectRayOriginKHR:
+    case spv::Op::OpRayQueryGetWorldRayDirectionKHR:
+    case spv::Op::OpRayQueryGetWorldRayOriginKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
 
       if (!_.IsFloatVectorType(result_type) ||
@@ -208,15 +211,15 @@
                   "vector type";
       }
 
-      if (opcode == SpvOpRayQueryGetIntersectionObjectRayDirectionKHR ||
-          opcode == SpvOpRayQueryGetIntersectionObjectRayOriginKHR) {
+      if (opcode == spv::Op::OpRayQueryGetIntersectionObjectRayDirectionKHR ||
+          opcode == spv::Op::OpRayQueryGetIntersectionObjectRayOriginKHR) {
         if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
       }
 
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionBarycentricsKHR: {
+    case spv::Op::OpRayQueryGetIntersectionBarycentricsKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
       if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
 
@@ -231,8 +234,8 @@
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionObjectToWorldKHR:
-    case SpvOpRayQueryGetIntersectionWorldToObjectKHR: {
+    case spv::Op::OpRayQueryGetIntersectionObjectToWorldKHR:
+    case spv::Op::OpRayQueryGetIntersectionWorldToObjectKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
       if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_ray_tracing.cpp b/third_party/SPIRV-Tools/source/val/validate_ray_tracing.cpp
new file mode 100644
index 0000000..f74e9d4
--- /dev/null
+++ b/third_party/SPIRV-Tools/source/val/validate_ray_tracing.cpp
@@ -0,0 +1,209 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Validates ray tracing instructions from SPV_KHR_ray_tracing
+
+#include "source/opcode.h"
+#include "source/val/instruction.h"
+#include "source/val/validate.h"
+#include "source/val/validation_state.h"
+
+namespace spvtools {
+namespace val {
+
+spv_result_t RayTracingPass(ValidationState_t& _, const Instruction* inst) {
+  const spv::Op opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
+
+  switch (opcode) {
+    case spv::Op::OpTraceRayKHR: {
+      _.function(inst->function()->id())
+          ->RegisterExecutionModelLimitation(
+              [](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::RayGenerationKHR &&
+                    model != spv::ExecutionModel::ClosestHitKHR &&
+                    model != spv::ExecutionModel::MissKHR) {
+                  if (message) {
+                    *message =
+                        "OpTraceRayKHR requires RayGenerationKHR, "
+                        "ClosestHitKHR and MissKHR execution models";
+                  }
+                  return false;
+                }
+                return true;
+              });
+
+      if (_.GetIdOpcode(_.GetOperandTypeId(inst, 0)) !=
+          spv::Op::OpTypeAccelerationStructureKHR) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Expected Acceleration Structure to be of type "
+                  "OpTypeAccelerationStructureKHR";
+      }
+
+      const uint32_t ray_flags = _.GetOperandTypeId(inst, 1);
+      if (!_.IsIntScalarType(ray_flags) || _.GetBitWidth(ray_flags) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Ray Flags must be a 32-bit int scalar";
+      }
+
+      const uint32_t cull_mask = _.GetOperandTypeId(inst, 2);
+      if (!_.IsIntScalarType(cull_mask) || _.GetBitWidth(cull_mask) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Cull Mask must be a 32-bit int scalar";
+      }
+
+      const uint32_t sbt_offset = _.GetOperandTypeId(inst, 3);
+      if (!_.IsIntScalarType(sbt_offset) || _.GetBitWidth(sbt_offset) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "SBT Offset must be a 32-bit int scalar";
+      }
+
+      const uint32_t sbt_stride = _.GetOperandTypeId(inst, 4);
+      if (!_.IsIntScalarType(sbt_stride) || _.GetBitWidth(sbt_stride) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "SBT Stride must be a 32-bit int scalar";
+      }
+
+      const uint32_t miss_index = _.GetOperandTypeId(inst, 5);
+      if (!_.IsIntScalarType(miss_index) || _.GetBitWidth(miss_index) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Miss Index must be a 32-bit int scalar";
+      }
+
+      const uint32_t ray_origin = _.GetOperandTypeId(inst, 6);
+      if (!_.IsFloatVectorType(ray_origin) || _.GetDimension(ray_origin) != 3 ||
+          _.GetBitWidth(ray_origin) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Ray Origin must be a 32-bit float 3-component vector";
+      }
+
+      const uint32_t ray_tmin = _.GetOperandTypeId(inst, 7);
+      if (!_.IsFloatScalarType(ray_tmin) || _.GetBitWidth(ray_tmin) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Ray TMin must be a 32-bit float scalar";
+      }
+
+      const uint32_t ray_direction = _.GetOperandTypeId(inst, 8);
+      if (!_.IsFloatVectorType(ray_direction) ||
+          _.GetDimension(ray_direction) != 3 ||
+          _.GetBitWidth(ray_direction) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Ray Direction must be a 32-bit float 3-component vector";
+      }
+
+      const uint32_t ray_tmax = _.GetOperandTypeId(inst, 9);
+      if (!_.IsFloatScalarType(ray_tmax) || _.GetBitWidth(ray_tmax) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Ray TMax must be a 32-bit float scalar";
+      }
+
+      const Instruction* payload = _.FindDef(inst->GetOperandAs<uint32_t>(10));
+      if (payload->opcode() != spv::Op::OpVariable) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Payload must be the result of a OpVariable";
+      } else if (payload->GetOperandAs<spv::StorageClass>(2) !=
+                     spv::StorageClass::RayPayloadKHR &&
+                 payload->GetOperandAs<spv::StorageClass>(2) !=
+                     spv::StorageClass::IncomingRayPayloadKHR) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Payload must have storage class RayPayloadKHR or "
+                  "IncomingRayPayloadKHR";
+      }
+      break;
+    }
+
+    case spv::Op::OpReportIntersectionKHR: {
+      _.function(inst->function()->id())
+          ->RegisterExecutionModelLimitation(
+              [](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::IntersectionKHR) {
+                  if (message) {
+                    *message =
+                        "OpReportIntersectionKHR requires IntersectionKHR "
+                        "execution model";
+                  }
+                  return false;
+                }
+                return true;
+              });
+
+      if (!_.IsBoolScalarType(result_type)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "expected Result Type to be bool scalar type";
+      }
+
+      const uint32_t hit = _.GetOperandTypeId(inst, 2);
+      if (!_.IsFloatScalarType(hit) || _.GetBitWidth(hit) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Hit must be a 32-bit int scalar";
+      }
+
+      const uint32_t hit_kind = _.GetOperandTypeId(inst, 3);
+      if (!_.IsUnsignedIntScalarType(hit_kind) ||
+          _.GetBitWidth(hit_kind) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Hit Kind must be a 32-bit unsigned int scalar";
+      }
+      break;
+    }
+
+    case spv::Op::OpExecuteCallableKHR: {
+      _.function(inst->function()->id())
+          ->RegisterExecutionModelLimitation([](spv::ExecutionModel model,
+                                                std::string* message) {
+            if (model != spv::ExecutionModel::RayGenerationKHR &&
+                model != spv::ExecutionModel::ClosestHitKHR &&
+                model != spv::ExecutionModel::MissKHR &&
+                model != spv::ExecutionModel::CallableKHR) {
+              if (message) {
+                *message =
+                    "OpExecuteCallableKHR requires RayGenerationKHR, "
+                    "ClosestHitKHR, MissKHR and CallableKHR execution models";
+              }
+              return false;
+            }
+            return true;
+          });
+
+      const uint32_t sbt_index = _.GetOperandTypeId(inst, 0);
+      if (!_.IsUnsignedIntScalarType(sbt_index) ||
+          _.GetBitWidth(sbt_index) != 32) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "SBT Index must be a 32-bit unsigned int scalar";
+      }
+
+      const auto callable_data = _.FindDef(inst->GetOperandAs<uint32_t>(1));
+      if (callable_data->opcode() != spv::Op::OpVariable) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Callable Data must be the result of a OpVariable";
+      } else if (callable_data->GetOperandAs<spv::StorageClass>(2) !=
+                     spv::StorageClass::CallableDataKHR &&
+                 callable_data->GetOperandAs<spv::StorageClass>(2) !=
+                     spv::StorageClass::IncomingCallableDataKHR) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Callable Data must have storage class CallableDataKHR or "
+                  "IncomingCallableDataKHR";
+      }
+
+      break;
+    }
+
+    default:
+      break;
+  }
+
+  return SPV_SUCCESS;
+}
+}  // namespace val
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/source/val/validate_scopes.cpp b/third_party/SPIRV-Tools/source/val/validate_scopes.cpp
index 887e8d1..fa1dad9 100644
--- a/third_party/SPIRV-Tools/source/val/validate_scopes.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_scopes.cpp
@@ -25,16 +25,16 @@
 bool IsValidScope(uint32_t scope) {
   // Deliberately avoid a default case so we have to update the list when the
   // scopes list changes.
-  switch (static_cast<SpvScope>(scope)) {
-    case SpvScopeCrossDevice:
-    case SpvScopeDevice:
-    case SpvScopeWorkgroup:
-    case SpvScopeSubgroup:
-    case SpvScopeInvocation:
-    case SpvScopeQueueFamilyKHR:
-    case SpvScopeShaderCallKHR:
+  switch (static_cast<spv::Scope>(scope)) {
+    case spv::Scope::CrossDevice:
+    case spv::Scope::Device:
+    case spv::Scope::Workgroup:
+    case spv::Scope::Subgroup:
+    case spv::Scope::Invocation:
+    case spv::Scope::QueueFamilyKHR:
+    case spv::Scope::ShaderCallKHR:
       return true;
-    case SpvScopeMax:
+    case spv::Scope::Max:
       break;
   }
   return false;
@@ -42,7 +42,7 @@
 
 spv_result_t ValidateScope(ValidationState_t& _, const Instruction* inst,
                            uint32_t scope) {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
@@ -53,14 +53,14 @@
   }
 
   if (!is_const_int32) {
-    if (_.HasCapability(SpvCapabilityShader) &&
-        !_.HasCapability(SpvCapabilityCooperativeMatrixNV)) {
+    if (_.HasCapability(spv::Capability::Shader) &&
+        !_.HasCapability(spv::Capability::CooperativeMatrixNV)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Scope ids must be OpConstant when Shader capability is "
              << "present";
     }
-    if (_.HasCapability(SpvCapabilityShader) &&
-        _.HasCapability(SpvCapabilityCooperativeMatrixNV) &&
+    if (_.HasCapability(spv::Capability::Shader) &&
+        _.HasCapability(spv::Capability::CooperativeMatrixNV) &&
         !spvOpcodeIsConstant(_.GetIdOpcode(scope))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Scope ids must be constant or specialization constant when "
@@ -78,10 +78,10 @@
 
 spv_result_t ValidateExecutionScope(ValidationState_t& _,
                                     const Instruction* inst, uint32_t scope) {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
-  uint32_t value = 0;
-  std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
+  uint32_t tmp_value = 0;
+  std::tie(is_int32, is_const_int32, tmp_value) = _.EvalInt32IfConst(scope);
 
   if (auto error = ValidateScope(_, inst, scope)) {
     return error;
@@ -91,13 +91,15 @@
     return SPV_SUCCESS;
   }
 
+  spv::Scope value = spv::Scope(tmp_value);
+
   // Vulkan specific rules
   if (spvIsVulkanEnv(_.context()->target_env)) {
     // Vulkan 1.1 specific rules
     if (_.context()->target_env != SPV_ENV_VULKAN_1_0) {
       // Scope for Non Uniform Group Operations must be limited to Subgroup
       if (spvOpcodeIsNonUniformGroupOperation(opcode) &&
-          value != SpvScopeSubgroup) {
+          value != spv::Scope::Subgroup) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << _.VkErrorID(4642) << spvOpcodeString(opcode)
                << ": in Vulkan environment Execution scope is limited to "
@@ -107,21 +109,21 @@
 
     // OpControlBarrier must only use Subgroup execution scope for a subset of
     // execution models.
-    if (opcode == SpvOpControlBarrier && value != SpvScopeSubgroup) {
+    if (opcode == spv::Op::OpControlBarrier && value != spv::Scope::Subgroup) {
       std::string errorVUID = _.VkErrorID(4682);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation([errorVUID](
-                                                 SpvExecutionModel model,
+                                                 spv::ExecutionModel model,
                                                  std::string* message) {
-            if (model == SpvExecutionModelFragment ||
-                model == SpvExecutionModelVertex ||
-                model == SpvExecutionModelGeometry ||
-                model == SpvExecutionModelTessellationEvaluation ||
-                model == SpvExecutionModelRayGenerationKHR ||
-                model == SpvExecutionModelIntersectionKHR ||
-                model == SpvExecutionModelAnyHitKHR ||
-                model == SpvExecutionModelClosestHitKHR ||
-                model == SpvExecutionModelMissKHR) {
+            if (model == spv::ExecutionModel::Fragment ||
+                model == spv::ExecutionModel::Vertex ||
+                model == spv::ExecutionModel::Geometry ||
+                model == spv::ExecutionModel::TessellationEvaluation ||
+                model == spv::ExecutionModel::RayGenerationKHR ||
+                model == spv::ExecutionModel::IntersectionKHR ||
+                model == spv::ExecutionModel::AnyHitKHR ||
+                model == spv::ExecutionModel::ClosestHitKHR ||
+                model == spv::ExecutionModel::MissKHR) {
               if (message) {
                 *message =
                     errorVUID +
@@ -137,21 +139,23 @@
     }
 
     // Only subset of execution models support Workgroup.
-    if (value == SpvScopeWorkgroup) {
+    if (value == spv::Scope::Workgroup) {
       std::string errorVUID = _.VkErrorID(4637);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [errorVUID](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelTaskNV &&
-                    model != SpvExecutionModelMeshNV &&
-                    model != SpvExecutionModelTessellationControl &&
-                    model != SpvExecutionModelGLCompute) {
+              [errorVUID](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::TaskNV &&
+                    model != spv::ExecutionModel::MeshNV &&
+                    model != spv::ExecutionModel::TaskEXT &&
+                    model != spv::ExecutionModel::MeshEXT &&
+                    model != spv::ExecutionModel::TessellationControl &&
+                    model != spv::ExecutionModel::GLCompute) {
                   if (message) {
                     *message =
                         errorVUID +
                         "in Vulkan environment, Workgroup execution scope is "
-                        "only for TaskNV, MeshNV, TessellationControl, and "
-                        "GLCompute execution models";
+                        "only for TaskNV, MeshNV, TaskEXT, MeshEXT, "
+                        "TessellationControl, and GLCompute execution models";
                   }
                   return false;
                 }
@@ -161,7 +165,7 @@
 
     // Vulkan generic rules
     // Scope for execution must be limited to Workgroup or Subgroup
-    if (value != SpvScopeWorkgroup && value != SpvScopeSubgroup) {
+    if (value != spv::Scope::Workgroup && value != spv::Scope::Subgroup) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4636) << spvOpcodeString(opcode)
              << ": in Vulkan environment Execution Scope is limited to "
@@ -175,7 +179,7 @@
   // Scope for execution must be limited to Workgroup or Subgroup for
   // non-uniform operations
   if (spvOpcodeIsNonUniformGroupOperation(opcode) &&
-      value != SpvScopeSubgroup && value != SpvScopeWorkgroup) {
+      value != spv::Scope::Subgroup && value != spv::Scope::Workgroup) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Execution scope is limited to Subgroup or Workgroup";
@@ -186,10 +190,10 @@
 
 spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst,
                                  uint32_t scope) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
-  uint32_t value = 0;
-  std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
+  uint32_t tmp_value = 0;
+  std::tie(is_int32, is_const_int32, tmp_value) = _.EvalInt32IfConst(scope);
 
   if (auto error = ValidateScope(_, inst, scope)) {
     return error;
@@ -199,8 +203,10 @@
     return SPV_SUCCESS;
   }
 
-  if (value == SpvScopeQueueFamilyKHR) {
-    if (_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  spv::Scope value = spv::Scope(tmp_value);
+
+  if (value == spv::Scope::QueueFamilyKHR) {
+    if (_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
       return SPV_SUCCESS;
     } else {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -210,9 +216,9 @@
     }
   }
 
-  if (value == SpvScopeDevice &&
-      _.HasCapability(SpvCapabilityVulkanMemoryModelKHR) &&
-      !_.HasCapability(SpvCapabilityVulkanMemoryModelDeviceScopeKHR)) {
+  if (value == spv::Scope::Device &&
+      _.HasCapability(spv::Capability::VulkanMemoryModelKHR) &&
+      !_.HasCapability(spv::Capability::VulkanMemoryModelDeviceScopeKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Use of device scope with VulkanKHR memory model requires the "
            << "VulkanMemoryModelDeviceScopeKHR capability";
@@ -220,36 +226,37 @@
 
   // Vulkan Specific rules
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (value != SpvScopeDevice && value != SpvScopeWorkgroup &&
-        value != SpvScopeSubgroup && value != SpvScopeInvocation &&
-        value != SpvScopeShaderCallKHR && value != SpvScopeQueueFamily) {
+    if (value != spv::Scope::Device && value != spv::Scope::Workgroup &&
+        value != spv::Scope::Subgroup && value != spv::Scope::Invocation &&
+        value != spv::Scope::ShaderCallKHR &&
+        value != spv::Scope::QueueFamily) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4638) << spvOpcodeString(opcode)
              << ": in Vulkan environment Memory Scope is limited to Device, "
                 "QueueFamily, Workgroup, ShaderCallKHR, Subgroup, or "
                 "Invocation";
     } else if (_.context()->target_env == SPV_ENV_VULKAN_1_0 &&
-               value == SpvScopeSubgroup &&
-               !_.HasCapability(SpvCapabilitySubgroupBallotKHR) &&
-               !_.HasCapability(SpvCapabilitySubgroupVoteKHR)) {
+               value == spv::Scope::Subgroup &&
+               !_.HasCapability(spv::Capability::SubgroupBallotKHR) &&
+               !_.HasCapability(spv::Capability::SubgroupVoteKHR)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << spvOpcodeString(opcode)
+             << _.VkErrorID(6997) << spvOpcodeString(opcode)
              << ": in Vulkan 1.0 environment Memory Scope is can not be "
                 "Subgroup without SubgroupBallotKHR or SubgroupVoteKHR "
                 "declared";
     }
 
-    if (value == SpvScopeShaderCallKHR) {
+    if (value == spv::Scope::ShaderCallKHR) {
       std::string errorVUID = _.VkErrorID(4640);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [errorVUID](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelRayGenerationKHR &&
-                    model != SpvExecutionModelIntersectionKHR &&
-                    model != SpvExecutionModelAnyHitKHR &&
-                    model != SpvExecutionModelClosestHitKHR &&
-                    model != SpvExecutionModelMissKHR &&
-                    model != SpvExecutionModelCallableKHR) {
+              [errorVUID](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::RayGenerationKHR &&
+                    model != spv::ExecutionModel::IntersectionKHR &&
+                    model != spv::ExecutionModel::AnyHitKHR &&
+                    model != spv::ExecutionModel::ClosestHitKHR &&
+                    model != spv::ExecutionModel::MissKHR &&
+                    model != spv::ExecutionModel::CallableKHR) {
                   if (message) {
                     *message =
                         errorVUID +
@@ -262,23 +269,45 @@
               });
     }
 
-    if (value == SpvScopeWorkgroup) {
-      std::string errorVUID = _.VkErrorID(4639);
+    if (value == spv::Scope::Workgroup) {
+      std::string errorVUID = _.VkErrorID(7321);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [errorVUID](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelGLCompute &&
-                    model != SpvExecutionModelTaskNV &&
-                    model != SpvExecutionModelMeshNV) {
+              [errorVUID](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::GLCompute &&
+                    model != spv::ExecutionModel::TessellationControl &&
+                    model != spv::ExecutionModel::TaskNV &&
+                    model != spv::ExecutionModel::MeshNV &&
+                    model != spv::ExecutionModel::TaskEXT &&
+                    model != spv::ExecutionModel::MeshEXT) {
                   if (message) {
                     *message = errorVUID +
                                "Workgroup Memory Scope is limited to MeshNV, "
-                               "TaskNV, and GLCompute execution model";
+                               "TaskNV, MeshEXT, TaskEXT, TessellationControl, "
+                               "and GLCompute execution model";
                   }
                   return false;
                 }
                 return true;
               });
+
+      if (_.memory_model() == spv::MemoryModel::GLSL450) {
+        errorVUID = _.VkErrorID(7320);
+        _.function(inst->function()->id())
+            ->RegisterExecutionModelLimitation(
+                [errorVUID](spv::ExecutionModel model, std::string* message) {
+                  if (model == spv::ExecutionModel::TessellationControl) {
+                    if (message) {
+                      *message =
+                          errorVUID +
+                          "Workgroup Memory Scope can't be used with "
+                          "TessellationControl using GLSL450 Memory Model";
+                    }
+                    return false;
+                  }
+                  return true;
+                });
+      }
     }
   }
 
diff --git a/third_party/SPIRV-Tools/source/val/validate_small_type_uses.cpp b/third_party/SPIRV-Tools/source/val/validate_small_type_uses.cpp
index 9db82e7..69f61ee 100644
--- a/third_party/SPIRV-Tools/source/val/validate_small_type_uses.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_small_type_uses.cpp
@@ -22,7 +22,7 @@
 
 spv_result_t ValidateSmallTypeUses(ValidationState_t& _,
                                    const Instruction* inst) {
-  if (!_.HasCapability(SpvCapabilityShader) || inst->type_id() == 0 ||
+  if (!_.HasCapability(spv::Capability::Shader) || inst->type_id() == 0 ||
       !_.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return SPV_SUCCESS;
   }
@@ -36,13 +36,13 @@
   for (auto use : inst->uses()) {
     const auto* user = use.first;
     switch (user->opcode()) {
-      case SpvOpDecorate:
-      case SpvOpDecorateId:
-      case SpvOpCopyObject:
-      case SpvOpStore:
-      case SpvOpFConvert:
-      case SpvOpUConvert:
-      case SpvOpSConvert:
+      case spv::Op::OpDecorate:
+      case spv::Op::OpDecorateId:
+      case spv::Op::OpCopyObject:
+      case spv::Op::OpStore:
+      case spv::Op::OpFConvert:
+      case spv::Op::OpUConvert:
+      case spv::Op::OpSConvert:
         break;
       default:
         return _.diag(SPV_ERROR_INVALID_ID, user)
diff --git a/third_party/SPIRV-Tools/source/val/validate_type.cpp b/third_party/SPIRV-Tools/source/val/validate_type.cpp
index b0b6079..e7adab8 100644
--- a/third_party/SPIRV-Tools/source/val/validate_type.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_type.cpp
@@ -19,7 +19,6 @@
 #include "source/val/instruction.h"
 #include "source/val/validate.h"
 #include "source/val/validation_state.h"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 namespace val {
@@ -50,8 +49,8 @@
     return SPV_SUCCESS;
 
   const auto opcode = inst->opcode();
-  if (opcode != SpvOpTypeArray && opcode != SpvOpTypeRuntimeArray &&
-      opcode != SpvOpTypeStruct && opcode != SpvOpTypePointer &&
+  if (opcode != spv::Op::OpTypeArray && opcode != spv::Op::OpTypeRuntimeArray &&
+      opcode != spv::Op::OpTypeStruct && opcode != spv::Op::OpTypePointer &&
       !_.RegisterUniqueTypeDeclaration(inst)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Duplicate non-aggregate type declarations are not allowed. "
@@ -84,7 +83,7 @@
              << "Using a 16-bit integer type requires the Int16 capability,"
                 " or an extension that explicitly enables 16-bit integers.";
     } else if (num_bits == 64) {
-      if (_.HasCapability(SpvCapabilityInt64)) {
+      if (_.HasCapability(spv::Capability::Int64)) {
         return SPV_SUCCESS;
       }
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -105,7 +104,8 @@
 
   // SPIR-V Spec 2.16.3: Validation Rules for Kernel Capabilities: The
   // Signedness in OpTypeInt must always be 0.
-  if (SpvOpTypeInt == inst->opcode() && _.HasCapability(SpvCapabilityKernel) &&
+  if (spv::Op::OpTypeInt == inst->opcode() &&
+      _.HasCapability(spv::Capability::Kernel) &&
       inst->GetOperandAs<uint32_t>(2) != 0u) {
     return _.diag(SPV_ERROR_INVALID_BINARY, inst)
            << "The Signedness in OpTypeInt "
@@ -135,7 +135,7 @@
               " or an extension that explicitly enables 16-bit floating point.";
   }
   if (num_bits == 64) {
-    if (_.HasCapability(SpvCapabilityFloat64)) {
+    if (_.HasCapability(spv::Capability::Float64)) {
       return SPV_SUCCESS;
     }
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -152,8 +152,8 @@
   const auto component_type = _.FindDef(component_id);
   if (!component_type || !spvOpcodeIsScalarType(component_type->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeVector Component Type <id> '" << _.getIdName(component_id)
-           << "' is not a scalar type.";
+           << "OpTypeVector Component Type <id> " << _.getIdName(component_id)
+           << " is not a scalar type.";
   }
 
   // Validates that the number of components in the vector is valid.
@@ -163,7 +163,7 @@
   if (num_components == 2 || num_components == 3 || num_components == 4) {
     return SPV_SUCCESS;
   } else if (num_components == 8 || num_components == 16) {
-    if (_.HasCapability(SpvCapabilityVector16)) {
+    if (_.HasCapability(spv::Capability::Vector16)) {
       return SPV_SUCCESS;
     }
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -183,7 +183,7 @@
   const auto column_type_index = 1;
   const auto column_type_id = inst->GetOperandAs<uint32_t>(column_type_index);
   const auto column_type = _.FindDef(column_type_id);
-  if (!column_type || SpvOpTypeVector != column_type->opcode()) {
+  if (!column_type || spv::Op::OpTypeVector != column_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Columns in a matrix must be of type vector.";
   }
@@ -192,7 +192,7 @@
   // Operand 1 is the <id> of the type of data in the vector.
   const auto comp_type_id = column_type->GetOperandAs<uint32_t>(1);
   auto comp_type_instruction = _.FindDef(comp_type_id);
-  if (comp_type_instruction->opcode() != SpvOpTypeFloat) {
+  if (comp_type_instruction->opcode() != spv::Op::OpTypeFloat) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Matrix types can only be "
                                                    "parameterized with "
                                                    "floating-point types.";
@@ -215,21 +215,21 @@
   const auto element_type = _.FindDef(element_type_id);
   if (!element_type || !spvOpcodeGeneratesType(element_type->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeArray Element Type <id> '" << _.getIdName(element_type_id)
-           << "' is not a type.";
+           << "OpTypeArray Element Type <id> " << _.getIdName(element_type_id)
+           << " is not a type.";
   }
 
-  if (element_type->opcode() == SpvOpTypeVoid) {
+  if (element_type->opcode() == spv::Op::OpTypeVoid) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeArray Element Type <id> '" << _.getIdName(element_type_id)
-           << "' is a void type.";
+           << "OpTypeArray Element Type <id> " << _.getIdName(element_type_id)
+           << " is a void type.";
   }
 
   if (spvIsVulkanEnv(_.context()->target_env) &&
-      element_type->opcode() == SpvOpTypeRuntimeArray) {
+      element_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << _.VkErrorID(4680) << "OpTypeArray Element Type <id> '"
-           << _.getIdName(element_type_id) << "' is not valid in "
+           << _.VkErrorID(4680) << "OpTypeArray Element Type <id> "
+           << _.getIdName(element_type_id) << " is not valid in "
            << spvLogStringForEnv(_.context()->target_env) << " environments.";
   }
 
@@ -238,38 +238,38 @@
   const auto length = _.FindDef(length_id);
   if (!length || !spvOpcodeIsConstant(length->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeArray Length <id> '" << _.getIdName(length_id)
-           << "' is not a scalar constant type.";
+           << "OpTypeArray Length <id> " << _.getIdName(length_id)
+           << " is not a scalar constant type.";
   }
 
   // NOTE: Check the initialiser value of the constant
   const auto const_inst = length->words();
   const auto const_result_type_index = 1;
   const auto const_result_type = _.FindDef(const_inst[const_result_type_index]);
-  if (!const_result_type || SpvOpTypeInt != const_result_type->opcode()) {
+  if (!const_result_type || spv::Op::OpTypeInt != const_result_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeArray Length <id> '" << _.getIdName(length_id)
-           << "' is not a constant integer type.";
+           << "OpTypeArray Length <id> " << _.getIdName(length_id)
+           << " is not a constant integer type.";
   }
 
   switch (length->opcode()) {
-    case SpvOpSpecConstant:
-    case SpvOpConstant: {
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpConstant: {
       auto& type_words = const_result_type->words();
       const bool is_signed = type_words[3] > 0;
       const uint32_t width = type_words[2];
       const int64_t ivalue = ConstantLiteralAsInt64(width, length->words());
       if (ivalue == 0 || (ivalue < 0 && is_signed)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
-               << "OpTypeArray Length <id> '" << _.getIdName(length_id)
-               << "' default value must be at least 1: found " << ivalue;
+               << "OpTypeArray Length <id> " << _.getIdName(length_id)
+               << " default value must be at least 1: found " << ivalue;
       }
     } break;
-    case SpvOpConstantNull:
+    case spv::Op::OpConstantNull:
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpTypeArray Length <id> '" << _.getIdName(length_id)
-             << "' default value must be at least 1.";
-    case SpvOpSpecConstantOp:
+             << "OpTypeArray Length <id> " << _.getIdName(length_id)
+             << " default value must be at least 1.";
+    case spv::Op::OpSpecConstantOp:
       // Assume it's OK, rather than try to evaluate the operation.
       break;
     default:
@@ -285,21 +285,21 @@
   const auto element_type = _.FindDef(element_id);
   if (!element_type || !spvOpcodeGeneratesType(element_type->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeRuntimeArray Element Type <id> '"
-           << _.getIdName(element_id) << "' is not a type.";
+           << "OpTypeRuntimeArray Element Type <id> " << _.getIdName(element_id)
+           << " is not a type.";
   }
 
-  if (element_type->opcode() == SpvOpTypeVoid) {
+  if (element_type->opcode() == spv::Op::OpTypeVoid) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeRuntimeArray Element Type <id> '"
-           << _.getIdName(element_id) << "' is a void type.";
+           << "OpTypeRuntimeArray Element Type <id> " << _.getIdName(element_id)
+           << " is a void type.";
   }
 
   if (spvIsVulkanEnv(_.context()->target_env) &&
-      element_type->opcode() == SpvOpTypeRuntimeArray) {
+      element_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << _.VkErrorID(4680) << "OpTypeRuntimeArray Element Type <id> '"
-           << _.getIdName(element_id) << "' is not valid in "
+           << _.VkErrorID(4680) << "OpTypeRuntimeArray Element Type <id> "
+           << _.getIdName(element_id) << " is not valid in "
            << spvLogStringForEnv(_.context()->target_env) << " environments.";
   }
 
@@ -319,14 +319,14 @@
     auto member_type = _.FindDef(member_type_id);
     if (!member_type || !spvOpcodeGeneratesType(member_type->opcode())) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpTypeStruct Member Type <id> '" << _.getIdName(member_type_id)
-             << "' is not a type.";
+             << "OpTypeStruct Member Type <id> " << _.getIdName(member_type_id)
+             << " is not a type.";
     }
-    if (member_type->opcode() == SpvOpTypeVoid) {
+    if (member_type->opcode() == spv::Op::OpTypeVoid) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Structures cannot contain a void type.";
     }
-    if (SpvOpTypeStruct == member_type->opcode() &&
+    if (spv::Op::OpTypeStruct == member_type->opcode() &&
         _.IsStructTypeWithBuiltInMember(member_type_id)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Structure <id> " << _.getIdName(member_type_id)
@@ -339,7 +339,7 @@
     }
 
     if (spvIsVulkanEnv(_.context()->target_env) &&
-        member_type->opcode() == SpvOpTypeRuntimeArray) {
+        member_type->opcode() == spv::Op::OpTypeRuntimeArray) {
       const bool is_last_member =
           member_type_index == inst->operands().size() - 1;
       if (!is_last_member) {
@@ -357,9 +357,10 @@
   for (size_t word_i = 2; word_i < inst->words().size(); ++word_i) {
     auto member = inst->word(word_i);
     auto memberTypeInstr = _.FindDef(member);
-    if (memberTypeInstr && SpvOpTypeStruct == memberTypeInstr->opcode()) {
-      if (_.HasDecoration(memberTypeInstr->id(), SpvDecorationBlock) ||
-          _.HasDecoration(memberTypeInstr->id(), SpvDecorationBufferBlock) ||
+    if (memberTypeInstr && spv::Op::OpTypeStruct == memberTypeInstr->opcode()) {
+      if (_.HasDecoration(memberTypeInstr->id(), spv::Decoration::Block) ||
+          _.HasDecoration(memberTypeInstr->id(),
+                          spv::Decoration::BufferBlock) ||
           _.GetHasNestedBlockOrBufferBlockStruct(memberTypeInstr->id()))
         has_nested_blockOrBufferBlock_struct = true;
     }
@@ -368,8 +369,8 @@
   _.SetHasNestedBlockOrBufferBlockStruct(inst->id(),
                                          has_nested_blockOrBufferBlock_struct);
   if (_.GetHasNestedBlockOrBufferBlockStruct(inst->id()) &&
-      (_.HasDecoration(inst->id(), SpvDecorationBufferBlock) ||
-       _.HasDecoration(inst->id(), SpvDecorationBlock))) {
+      (_.HasDecoration(inst->id(), spv::Decoration::BufferBlock) ||
+       _.HasDecoration(inst->id(), spv::Decoration::Block))) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "rules: A Block or BufferBlock cannot be nested within another "
               "Block or BufferBlock. ";
@@ -377,7 +378,7 @@
 
   std::unordered_set<uint32_t> built_in_members;
   for (auto decoration : _.id_decorations(struct_id)) {
-    if (decoration.dec_type() == SpvDecorationBuiltIn &&
+    if (decoration.dec_type() == spv::Decoration::BuiltIn &&
         decoration.struct_member_index() != Decoration::kInvalidMember) {
       built_in_members.insert(decoration.struct_member_index());
     }
@@ -398,9 +399,9 @@
 
   const auto isOpaqueType = [&_](const Instruction* opaque_inst) {
     auto opcode = opaque_inst->opcode();
-    if (_.HasCapability(SpvCapabilityBindlessTextureNV) &&
-        (opcode == SpvOpTypeImage || opcode == SpvOpTypeSampler ||
-         opcode == SpvOpTypeSampledImage)) {
+    if (_.HasCapability(spv::Capability::BindlessTextureNV) &&
+        (opcode == spv::Op::OpTypeImage || opcode == spv::Op::OpTypeSampler ||
+         opcode == spv::Op::OpTypeSampledImage)) {
       return false;
     } else if (spvOpcodeIsBaseOpaqueType(opcode)) {
       return true;
@@ -426,19 +427,19 @@
   auto type = _.FindDef(type_id);
   if (!type || !spvOpcodeGeneratesType(type->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypePointer Type <id> '" << _.getIdName(type_id)
-           << "' is not a type.";
+           << "OpTypePointer Type <id> " << _.getIdName(type_id)
+           << " is not a type.";
   }
   // See if this points to a storage image.
-  const auto storage_class = inst->GetOperandAs<SpvStorageClass>(1);
-  if (storage_class == SpvStorageClassUniformConstant) {
+  const auto storage_class = inst->GetOperandAs<spv::StorageClass>(1);
+  if (storage_class == spv::StorageClass::UniformConstant) {
     // Unpack an optional level of arraying.
-    if (type->opcode() == SpvOpTypeArray ||
-        type->opcode() == SpvOpTypeRuntimeArray) {
+    if (type->opcode() == spv::Op::OpTypeArray ||
+        type->opcode() == spv::Op::OpTypeRuntimeArray) {
       type_id = type->GetOperandAs<uint32_t>(1);
       type = _.FindDef(type_id);
     }
-    if (type->opcode() == SpvOpTypeImage) {
+    if (type->opcode() == spv::Op::OpTypeImage) {
       const auto sampled = type->GetOperandAs<uint32_t>(6);
       // 2 indicates this image is known to be be used without a sampler, i.e.
       // a storage image.
@@ -461,8 +462,8 @@
   const auto return_type = _.FindDef(return_type_id);
   if (!return_type || !spvOpcodeGeneratesType(return_type->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeFunction Return Type <id> '" << _.getIdName(return_type_id)
-           << "' is not a type.";
+           << "OpTypeFunction Return Type <id> " << _.getIdName(return_type_id)
+           << " is not a type.";
   }
   size_t num_args = 0;
   for (size_t param_type_index = 2; param_type_index < inst->operands().size();
@@ -471,14 +472,14 @@
     const auto param_type = _.FindDef(param_id);
     if (!param_type || !spvOpcodeGeneratesType(param_type->opcode())) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpTypeFunction Parameter Type <id> '" << _.getIdName(param_id)
-             << "' is not a type.";
+             << "OpTypeFunction Parameter Type <id> " << _.getIdName(param_id)
+             << " is not a type.";
     }
 
-    if (param_type->opcode() == SpvOpTypeVoid) {
+    if (param_type->opcode() == spv::Op::OpTypeVoid) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpTypeFunction Parameter Type <id> '" << _.getIdName(param_id)
-             << "' cannot be OpTypeVoid.";
+             << "OpTypeFunction Parameter Type <id> " << _.getIdName(param_id)
+             << " cannot be OpTypeVoid.";
     }
   }
   const uint32_t num_function_args_limit =
@@ -486,8 +487,8 @@
   if (num_args > num_function_args_limit) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpTypeFunction may not take more than "
-           << num_function_args_limit << " arguments. OpTypeFunction <id> '"
-           << _.getIdName(inst->GetOperandAs<uint32_t>(0)) << "' has "
+           << num_function_args_limit << " arguments. OpTypeFunction <id> "
+           << _.getIdName(inst->GetOperandAs<uint32_t>(0)) << " has "
            << num_args << " arguments.";
   }
 
@@ -495,8 +496,9 @@
   // decoration instruction.
   for (auto& pair : inst->uses()) {
     const auto* use = pair.first;
-    if (use->opcode() != SpvOpFunction && !spvOpcodeIsDebug(use->opcode()) &&
-        !use->IsNonSemantic() && !spvOpcodeIsDecoration(use->opcode())) {
+    if (use->opcode() != spv::Op::OpFunction &&
+        !spvOpcodeIsDebug(use->opcode()) && !use->IsNonSemantic() &&
+        !spvOpcodeIsDecoration(use->opcode())) {
       return _.diag(SPV_ERROR_INVALID_ID, use)
              << "Invalid use of function type result id "
              << _.getIdName(inst->id()) << ".";
@@ -510,13 +512,13 @@
                                         const Instruction* inst) {
   const auto pointer_type_id = inst->GetOperandAs<uint32_t>(0);
   const auto pointer_type_inst = _.FindDef(pointer_type_id);
-  if (pointer_type_inst->opcode() != SpvOpTypePointer) {
+  if (pointer_type_inst->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Pointer type in OpTypeForwardPointer is not a pointer type.";
   }
 
-  const auto storage_class = inst->GetOperandAs<SpvStorageClass>(1);
-  if (storage_class != pointer_type_inst->GetOperandAs<uint32_t>(1)) {
+  const auto storage_class = inst->GetOperandAs<spv::StorageClass>(1);
+  if (storage_class != pointer_type_inst->GetOperandAs<spv::StorageClass>(1)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Storage class in OpTypeForwardPointer does not match the "
            << "pointer definition.";
@@ -524,13 +526,13 @@
 
   const auto pointee_type_id = pointer_type_inst->GetOperandAs<uint32_t>(2);
   const auto pointee_type = _.FindDef(pointee_type_id);
-  if (!pointee_type || pointee_type->opcode() != SpvOpTypeStruct) {
+  if (!pointee_type || pointee_type->opcode() != spv::Op::OpTypeStruct) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Forward pointers must point to a structure";
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (storage_class != SpvStorageClassPhysicalStorageBuffer) {
+    if (storage_class != spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << _.VkErrorID(4711)
              << "In Vulkan, OpTypeForwardPointer must have "
@@ -547,12 +549,12 @@
   const auto component_type_id =
       inst->GetOperandAs<uint32_t>(component_type_index);
   const auto component_type = _.FindDef(component_type_id);
-  if (!component_type || (SpvOpTypeFloat != component_type->opcode() &&
-                          SpvOpTypeInt != component_type->opcode())) {
+  if (!component_type || (spv::Op::OpTypeFloat != component_type->opcode() &&
+                          spv::Op::OpTypeInt != component_type->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeCooperativeMatrixNV Component Type <id> '"
+           << "OpTypeCooperativeMatrixNV Component Type <id> "
            << _.getIdName(component_type_id)
-           << "' is not a scalar numerical type.";
+           << " is not a scalar numerical type.";
   }
 
   const auto scope_index = 2;
@@ -561,8 +563,8 @@
   if (!scope || !_.IsIntScalarType(scope->type_id()) ||
       !spvOpcodeIsConstant(scope->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeCooperativeMatrixNV Scope <id> '" << _.getIdName(scope_id)
-           << "' is not a constant instruction with scalar integer type.";
+           << "OpTypeCooperativeMatrixNV Scope <id> " << _.getIdName(scope_id)
+           << " is not a constant instruction with scalar integer type.";
   }
 
   const auto rows_index = 3;
@@ -571,8 +573,8 @@
   if (!rows || !_.IsIntScalarType(rows->type_id()) ||
       !spvOpcodeIsConstant(rows->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeCooperativeMatrixNV Rows <id> '" << _.getIdName(rows_id)
-           << "' is not a constant instruction with scalar integer type.";
+           << "OpTypeCooperativeMatrixNV Rows <id> " << _.getIdName(rows_id)
+           << " is not a constant instruction with scalar integer type.";
   }
 
   const auto cols_index = 4;
@@ -581,8 +583,8 @@
   if (!cols || !_.IsIntScalarType(cols->type_id()) ||
       !spvOpcodeIsConstant(cols->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpTypeCooperativeMatrixNV Cols <id> '" << _.getIdName(cols_id)
-           << "' is not a constant instruction with scalar integer type.";
+           << "OpTypeCooperativeMatrixNV Cols <id> " << _.getIdName(cols_id)
+           << " is not a constant instruction with scalar integer type.";
   }
 
   return SPV_SUCCESS;
@@ -591,44 +593,44 @@
 
 spv_result_t TypePass(ValidationState_t& _, const Instruction* inst) {
   if (!spvOpcodeGeneratesType(inst->opcode()) &&
-      inst->opcode() != SpvOpTypeForwardPointer) {
+      inst->opcode() != spv::Op::OpTypeForwardPointer) {
     return SPV_SUCCESS;
   }
 
   if (auto error = ValidateUniqueness(_, inst)) return error;
 
   switch (inst->opcode()) {
-    case SpvOpTypeInt:
+    case spv::Op::OpTypeInt:
       if (auto error = ValidateTypeInt(_, inst)) return error;
       break;
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeFloat:
       if (auto error = ValidateTypeFloat(_, inst)) return error;
       break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       if (auto error = ValidateTypeVector(_, inst)) return error;
       break;
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       if (auto error = ValidateTypeMatrix(_, inst)) return error;
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       if (auto error = ValidateTypeArray(_, inst)) return error;
       break;
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       if (auto error = ValidateTypeRuntimeArray(_, inst)) return error;
       break;
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       if (auto error = ValidateTypeStruct(_, inst)) return error;
       break;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       if (auto error = ValidateTypePointer(_, inst)) return error;
       break;
-    case SpvOpTypeFunction:
+    case spv::Op::OpTypeFunction:
       if (auto error = ValidateTypeFunction(_, inst)) return error;
       break;
-    case SpvOpTypeForwardPointer:
+    case spv::Op::OpTypeForwardPointer:
       if (auto error = ValidateTypeForwardPointer(_, inst)) return error;
       break;
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       if (auto error = ValidateTypeCooperativeMatrixNV(_, inst)) return error;
       break;
     default:
diff --git a/third_party/SPIRV-Tools/source/val/validation_state.cpp b/third_party/SPIRV-Tools/source/val/validation_state.cpp
index adfe75b..d7a196c 100644
--- a/third_party/SPIRV-Tools/source/val/validation_state.cpp
+++ b/third_party/SPIRV-Tools/source/val/validation_state.cpp
@@ -31,66 +31,66 @@
 namespace {
 
 ModuleLayoutSection InstructionLayoutSection(
-    ModuleLayoutSection current_section, SpvOp op) {
+    ModuleLayoutSection current_section, spv::Op op) {
   // See Section 2.4
   if (spvOpcodeGeneratesType(op) || spvOpcodeIsConstant(op))
     return kLayoutTypes;
 
   switch (op) {
-    case SpvOpCapability:
+    case spv::Op::OpCapability:
       return kLayoutCapabilities;
-    case SpvOpExtension:
+    case spv::Op::OpExtension:
       return kLayoutExtensions;
-    case SpvOpExtInstImport:
+    case spv::Op::OpExtInstImport:
       return kLayoutExtInstImport;
-    case SpvOpMemoryModel:
+    case spv::Op::OpMemoryModel:
       return kLayoutMemoryModel;
-    case SpvOpEntryPoint:
+    case spv::Op::OpEntryPoint:
       return kLayoutEntryPoint;
-    case SpvOpExecutionMode:
-    case SpvOpExecutionModeId:
+    case spv::Op::OpExecutionMode:
+    case spv::Op::OpExecutionModeId:
       return kLayoutExecutionMode;
-    case SpvOpSourceContinued:
-    case SpvOpSource:
-    case SpvOpSourceExtension:
-    case SpvOpString:
+    case spv::Op::OpSourceContinued:
+    case spv::Op::OpSource:
+    case spv::Op::OpSourceExtension:
+    case spv::Op::OpString:
       return kLayoutDebug1;
-    case SpvOpName:
-    case SpvOpMemberName:
+    case spv::Op::OpName:
+    case spv::Op::OpMemberName:
       return kLayoutDebug2;
-    case SpvOpModuleProcessed:
+    case spv::Op::OpModuleProcessed:
       return kLayoutDebug3;
-    case SpvOpDecorate:
-    case SpvOpMemberDecorate:
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate:
-    case SpvOpDecorationGroup:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorateStringGOOGLE:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate:
+    case spv::Op::OpDecorationGroup:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorateStringGOOGLE:
       return kLayoutAnnotations;
-    case SpvOpTypeForwardPointer:
+    case spv::Op::OpTypeForwardPointer:
       return kLayoutTypes;
-    case SpvOpVariable:
+    case spv::Op::OpVariable:
       if (current_section == kLayoutTypes) return kLayoutTypes;
       return kLayoutFunctionDefinitions;
-    case SpvOpExtInst:
-      // SpvOpExtInst is only allowed in types section for certain extended
-      // instruction sets. This will be checked separately.
+    case spv::Op::OpExtInst:
+      // spv::Op::OpExtInst is only allowed in types section for certain
+      // extended instruction sets. This will be checked separately.
       if (current_section == kLayoutTypes) return kLayoutTypes;
       return kLayoutFunctionDefinitions;
-    case SpvOpLine:
-    case SpvOpNoLine:
-    case SpvOpUndef:
+    case spv::Op::OpLine:
+    case spv::Op::OpNoLine:
+    case spv::Op::OpUndef:
       if (current_section == kLayoutTypes) return kLayoutTypes;
       return kLayoutFunctionDefinitions;
-    case SpvOpFunction:
-    case SpvOpFunctionParameter:
-    case SpvOpFunctionEnd:
+    case spv::Op::OpFunction:
+    case spv::Op::OpFunctionParameter:
+    case spv::Op::OpFunctionEnd:
       if (current_section == kLayoutFunctionDeclarations)
         return kLayoutFunctionDeclarations;
       return kLayoutFunctionDefinitions;
-    case SpvOpSamplerImageAddressingModeNV:
+    case spv::Op::OpSamplerImageAddressingModeNV:
       return kLayoutSamplerImageAddressMode;
     default:
       break;
@@ -98,7 +98,7 @@
   return kLayoutFunctionDefinitions;
 }
 
-bool IsInstructionInLayoutSection(ModuleLayoutSection layout, SpvOp op) {
+bool IsInstructionInLayoutSection(ModuleLayoutSection layout, spv::Op op) {
   return layout == InstructionLayoutSection(layout, op);
 }
 
@@ -106,7 +106,9 @@
 spv_result_t CountInstructions(void* user_data,
                                const spv_parsed_instruction_t* inst) {
   ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
-  if (inst->opcode == SpvOpFunction) _.increment_total_functions();
+  if (spv::Op(inst->opcode) == spv::Op::OpFunction) {
+    _.increment_total_functions();
+  }
   _.increment_total_instructions();
 
   return SPV_SUCCESS;
@@ -160,8 +162,8 @@
       struct_nesting_depth_(),
       struct_has_nested_blockorbufferblock_struct_(),
       grammar_(ctx),
-      addressing_model_(SpvAddressingModelMax),
-      memory_model_(SpvMemoryModelMax),
+      addressing_model_(spv::AddressingModel::Max),
+      memory_model_(spv::MemoryModel::Max),
       pointer_size_and_alignment_(0),
       sampler_image_addressing_mode_(0),
       in_function_(false),
@@ -208,9 +210,12 @@
   }
   UpdateFeaturesBasedOnSpirvVersion(&features_, version_);
 
-  friendly_mapper_ = spvtools::MakeUnique<spvtools::FriendlyNameMapper>(
-      context_, words_, num_words_);
-  name_mapper_ = friendly_mapper_->GetNameMapper();
+  name_mapper_ = spvtools::GetTrivialNameMapper();
+  if (options_->use_friendly_names) {
+    friendly_mapper_ = spvtools::MakeUnique<spvtools::FriendlyNameMapper>(
+        context_, words_, num_words_);
+    name_mapper_ = friendly_mapper_->GetNameMapper();
+  }
 }
 
 void ValidationState_t::preallocateStorage() {
@@ -245,7 +250,7 @@
   const std::string id_name = name_mapper_(id);
 
   std::stringstream out;
-  out << id << "[%" << id_name << "]";
+  out << "'" << id << "[%" << id_name << "]'";
   return out.str();
 }
 
@@ -287,13 +292,13 @@
   }
 }
 
-bool ValidationState_t::IsOpcodeInPreviousLayoutSection(SpvOp op) {
+bool ValidationState_t::IsOpcodeInPreviousLayoutSection(spv::Op op) {
   ModuleLayoutSection section =
       InstructionLayoutSection(current_layout_section_, op);
   return section < current_layout_section_;
 }
 
-bool ValidationState_t::IsOpcodeInCurrentLayoutSection(SpvOp op) {
+bool ValidationState_t::IsOpcodeInCurrentLayoutSection(spv::Op op) {
   return IsInstructionInLayoutSection(current_layout_section_, op);
 }
 
@@ -350,7 +355,7 @@
          module_functions_.back().current_block() != nullptr;
 }
 
-void ValidationState_t::RegisterCapability(SpvCapability cap) {
+void ValidationState_t::RegisterCapability(spv::Capability cap) {
   // Avoid redundant work.  Otherwise the recursion could induce work
   // quadrdatic in the capability dependency depth. (Ok, not much, but
   // it's something.)
@@ -358,51 +363,51 @@
 
   module_capabilities_.Add(cap);
   spv_operand_desc desc;
-  if (SPV_SUCCESS ==
-      grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc)) {
+  if (SPV_SUCCESS == grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
+                                            uint32_t(cap), &desc)) {
     CapabilitySet(desc->numCapabilities, desc->capabilities)
-        .ForEach([this](SpvCapability c) { RegisterCapability(c); });
+        .ForEach([this](spv::Capability c) { RegisterCapability(c); });
   }
 
   switch (cap) {
-    case SpvCapabilityKernel:
+    case spv::Capability::Kernel:
       features_.group_ops_reduce_and_scans = true;
       break;
-    case SpvCapabilityInt8:
+    case spv::Capability::Int8:
       features_.use_int8_type = true;
       features_.declare_int8_type = true;
       break;
-    case SpvCapabilityStorageBuffer8BitAccess:
-    case SpvCapabilityUniformAndStorageBuffer8BitAccess:
-    case SpvCapabilityStoragePushConstant8:
-    case SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:
+    case spv::Capability::StorageBuffer8BitAccess:
+    case spv::Capability::UniformAndStorageBuffer8BitAccess:
+    case spv::Capability::StoragePushConstant8:
+    case spv::Capability::WorkgroupMemoryExplicitLayout8BitAccessKHR:
       features_.declare_int8_type = true;
       break;
-    case SpvCapabilityInt16:
+    case spv::Capability::Int16:
       features_.declare_int16_type = true;
       break;
-    case SpvCapabilityFloat16:
-    case SpvCapabilityFloat16Buffer:
+    case spv::Capability::Float16:
+    case spv::Capability::Float16Buffer:
       features_.declare_float16_type = true;
       break;
-    case SpvCapabilityStorageUniformBufferBlock16:
-    case SpvCapabilityStorageUniform16:
-    case SpvCapabilityStoragePushConstant16:
-    case SpvCapabilityStorageInputOutput16:
-    case SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR:
+    case spv::Capability::StorageUniformBufferBlock16:
+    case spv::Capability::StorageUniform16:
+    case spv::Capability::StoragePushConstant16:
+    case spv::Capability::StorageInputOutput16:
+    case spv::Capability::WorkgroupMemoryExplicitLayout16BitAccessKHR:
       features_.declare_int16_type = true;
       features_.declare_float16_type = true;
       features_.free_fp_rounding_mode = true;
       break;
-    case SpvCapabilityVariablePointers:
-    case SpvCapabilityVariablePointersStorageBuffer:
+    case spv::Capability::VariablePointers:
+    case spv::Capability::VariablePointersStorageBuffer:
       features_.variable_pointers = true;
       break;
     default:
       // TODO(dneto): For now don't validate SPV_NV_ray_tracing, which uses
-      // capability SpvCapabilityRayTracingNV.
-      // SpvCapabilityRayTracingProvisionalKHR would need the same treatment.
-      // One of the differences going from SPV_KHR_ray_tracing from
+      // capability spv::Capability::RayTracingNV.
+      // spv::Capability::RayTracingProvisionalKHR would need the same
+      // treatment. One of the differences going from SPV_KHR_ray_tracing from
       // provisional to final spec was the provisional spec uses Locations
       // for variables in certain storage classes, just like the
       // SPV_NV_ray_tracing extension.  So it mimics the NVIDIA extension.
@@ -451,30 +456,32 @@
   return module_extensions_.HasAnyOf(extensions);
 }
 
-void ValidationState_t::set_addressing_model(SpvAddressingModel am) {
+void ValidationState_t::set_addressing_model(spv::AddressingModel am) {
   addressing_model_ = am;
   switch (am) {
-    case SpvAddressingModelPhysical32:
+    case spv::AddressingModel::Physical32:
       pointer_size_and_alignment_ = 4;
       break;
     default:
     // fall through
-    case SpvAddressingModelPhysical64:
-    case SpvAddressingModelPhysicalStorageBuffer64:
+    case spv::AddressingModel::Physical64:
+    case spv::AddressingModel::PhysicalStorageBuffer64:
       pointer_size_and_alignment_ = 8;
       break;
   }
 }
 
-SpvAddressingModel ValidationState_t::addressing_model() const {
+spv::AddressingModel ValidationState_t::addressing_model() const {
   return addressing_model_;
 }
 
-void ValidationState_t::set_memory_model(SpvMemoryModel mm) {
+void ValidationState_t::set_memory_model(spv::MemoryModel mm) {
   memory_model_ = mm;
 }
 
-SpvMemoryModel ValidationState_t::memory_model() const { return memory_model_; }
+spv::MemoryModel ValidationState_t::memory_model() const {
+  return memory_model_;
+}
 
 void ValidationState_t::set_samplerimage_variable_address_mode(
     uint32_t bit_width) {
@@ -486,8 +493,8 @@
 }
 
 spv_result_t ValidationState_t::RegisterFunction(
-    uint32_t id, uint32_t ret_type_id, SpvFunctionControlMask function_control,
-    uint32_t function_type_id) {
+    uint32_t id, uint32_t ret_type_id,
+    spv::FunctionControlMask function_control, uint32_t function_type_id) {
   assert(in_function_body() == false &&
          "RegisterFunction can only be called when parsing the binary outside "
          "of another function");
@@ -523,24 +530,24 @@
 // Improves diagnostic messages by collecting names of IDs
 void ValidationState_t::RegisterDebugInstruction(const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpName: {
+    case spv::Op::OpName: {
       const auto target = inst->GetOperandAs<uint32_t>(0);
       const std::string str = inst->GetOperandAs<std::string>(1);
       AssignNameToId(target, str);
       break;
     }
-    case SpvOpMemberName: {
+    case spv::Op::OpMemberName: {
       const auto target = inst->GetOperandAs<uint32_t>(0);
       const std::string str = inst->GetOperandAs<std::string>(2);
       AssignNameToId(target, str);
       break;
     }
-    case SpvOpSourceContinued:
-    case SpvOpSource:
-    case SpvOpSourceExtension:
-    case SpvOpString:
-    case SpvOpLine:
-    case SpvOpNoLine:
+    case spv::Op::OpSourceContinued:
+    case spv::Op::OpSource:
+    case spv::Op::OpSourceExtension:
+    case spv::Op::OpString:
+    case spv::Op::OpLine:
+    case spv::Op::OpNoLine:
     default:
       break;
   }
@@ -564,7 +571,7 @@
       // should be recorded. The validator will ensure that all usages of an
       // OpTypeSampledImage and its definition are in the same basic block.
       if ((SPV_OPERAND_TYPE_ID == operand.type) &&
-          (SpvOpSampledImage == operand_inst->opcode())) {
+          (spv::Op::OpSampledImage == operand_inst->opcode())) {
         RegisterSampledImageConsumer(operand_word, inst);
       }
 
@@ -574,12 +581,12 @@
       // Instead just need to register storage class usage for consumers in a
       // function block.
       if (inst->function()) {
-        if (operand_inst->opcode() == SpvOpTypePointer) {
+        if (operand_inst->opcode() == spv::Op::OpTypePointer) {
           RegisterStorageClassConsumer(
-              operand_inst->GetOperandAs<SpvStorageClass>(1), inst);
-        } else if (operand_inst->opcode() == SpvOpVariable) {
+              operand_inst->GetOperandAs<spv::StorageClass>(1), inst);
+        } else if (operand_inst->opcode() == spv::Op::OpVariable) {
           RegisterStorageClassConsumer(
-              operand_inst->GetOperandAs<SpvStorageClass>(2), inst);
+              operand_inst->GetOperandAs<spv::StorageClass>(2), inst);
         }
       }
     }
@@ -602,20 +609,21 @@
 }
 
 void ValidationState_t::RegisterStorageClassConsumer(
-    SpvStorageClass storage_class, Instruction* consumer) {
+    spv::StorageClass storage_class, Instruction* consumer) {
   if (spvIsVulkanEnv(context()->target_env)) {
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       std::string errorVUID = VkErrorID(4644);
       function(consumer->function()->id())
           ->RegisterExecutionModelLimitation([errorVUID](
-              SpvExecutionModel model, std::string* message) {
-            if (model == SpvExecutionModelGLCompute ||
-                model == SpvExecutionModelRayGenerationKHR ||
-                model == SpvExecutionModelIntersectionKHR ||
-                model == SpvExecutionModelAnyHitKHR ||
-                model == SpvExecutionModelClosestHitKHR ||
-                model == SpvExecutionModelMissKHR ||
-                model == SpvExecutionModelCallableKHR) {
+                                                 spv::ExecutionModel model,
+                                                 std::string* message) {
+            if (model == spv::ExecutionModel::GLCompute ||
+                model == spv::ExecutionModel::RayGenerationKHR ||
+                model == spv::ExecutionModel::IntersectionKHR ||
+                model == spv::ExecutionModel::AnyHitKHR ||
+                model == spv::ExecutionModel::ClosestHitKHR ||
+                model == spv::ExecutionModel::MissKHR ||
+                model == spv::ExecutionModel::CallableKHR) {
               if (message) {
                 *message =
                     errorVUID +
@@ -630,14 +638,17 @@
           });
     }
 
-    if (storage_class == SpvStorageClassWorkgroup) {
+    if (storage_class == spv::StorageClass::Workgroup) {
       std::string errorVUID = VkErrorID(4645);
       function(consumer->function()->id())
           ->RegisterExecutionModelLimitation([errorVUID](
-              SpvExecutionModel model, std::string* message) {
-            if (model != SpvExecutionModelGLCompute &&
-                model != SpvExecutionModelTaskNV &&
-                model != SpvExecutionModelMeshNV) {
+                                                 spv::ExecutionModel model,
+                                                 std::string* message) {
+            if (model != spv::ExecutionModel::GLCompute &&
+                model != spv::ExecutionModel::TaskNV &&
+                model != spv::ExecutionModel::MeshNV &&
+                model != spv::ExecutionModel::TaskEXT &&
+                model != spv::ExecutionModel::MeshEXT) {
               if (message) {
                 *message =
                     errorVUID +
@@ -650,6 +661,136 @@
           });
     }
   }
+
+  if (storage_class == spv::StorageClass::CallableDataKHR) {
+    std::string errorVUID = VkErrorID(4704);
+    function(consumer->function()->id())
+        ->RegisterExecutionModelLimitation([errorVUID](
+                                               spv::ExecutionModel model,
+                                               std::string* message) {
+          if (model != spv::ExecutionModel::RayGenerationKHR &&
+              model != spv::ExecutionModel::ClosestHitKHR &&
+              model != spv::ExecutionModel::CallableKHR &&
+              model != spv::ExecutionModel::MissKHR) {
+            if (message) {
+              *message = errorVUID +
+                         "CallableDataKHR Storage Class is limited to "
+                         "RayGenerationKHR, ClosestHitKHR, CallableKHR, and "
+                         "MissKHR execution model";
+            }
+            return false;
+          }
+          return true;
+        });
+  } else if (storage_class == spv::StorageClass::IncomingCallableDataKHR) {
+    std::string errorVUID = VkErrorID(4705);
+    function(consumer->function()->id())
+        ->RegisterExecutionModelLimitation([errorVUID](
+                                               spv::ExecutionModel model,
+                                               std::string* message) {
+          if (model != spv::ExecutionModel::CallableKHR) {
+            if (message) {
+              *message = errorVUID +
+                         "IncomingCallableDataKHR Storage Class is limited to "
+                         "CallableKHR execution model";
+            }
+            return false;
+          }
+          return true;
+        });
+  } else if (storage_class == spv::StorageClass::RayPayloadKHR) {
+    std::string errorVUID = VkErrorID(4698);
+    function(consumer->function()->id())
+        ->RegisterExecutionModelLimitation([errorVUID](
+                                               spv::ExecutionModel model,
+                                               std::string* message) {
+          if (model != spv::ExecutionModel::RayGenerationKHR &&
+              model != spv::ExecutionModel::ClosestHitKHR &&
+              model != spv::ExecutionModel::MissKHR) {
+            if (message) {
+              *message =
+                  errorVUID +
+                  "RayPayloadKHR Storage Class is limited to RayGenerationKHR, "
+                  "ClosestHitKHR, and MissKHR execution model";
+            }
+            return false;
+          }
+          return true;
+        });
+  } else if (storage_class == spv::StorageClass::HitAttributeKHR) {
+    std::string errorVUID = VkErrorID(4701);
+    function(consumer->function()->id())
+        ->RegisterExecutionModelLimitation(
+            [errorVUID](spv::ExecutionModel model, std::string* message) {
+              if (model != spv::ExecutionModel::IntersectionKHR &&
+                  model != spv::ExecutionModel::AnyHitKHR &&
+                  model != spv::ExecutionModel::ClosestHitKHR) {
+                if (message) {
+                  *message = errorVUID +
+                             "HitAttributeKHR Storage Class is limited to "
+                             "IntersectionKHR, AnyHitKHR, sand ClosestHitKHR "
+                             "execution model";
+                }
+                return false;
+              }
+              return true;
+            });
+  } else if (storage_class == spv::StorageClass::IncomingRayPayloadKHR) {
+    std::string errorVUID = VkErrorID(4699);
+    function(consumer->function()->id())
+        ->RegisterExecutionModelLimitation(
+            [errorVUID](spv::ExecutionModel model, std::string* message) {
+              if (model != spv::ExecutionModel::AnyHitKHR &&
+                  model != spv::ExecutionModel::ClosestHitKHR &&
+                  model != spv::ExecutionModel::MissKHR) {
+                if (message) {
+                  *message =
+                      errorVUID +
+                      "IncomingRayPayloadKHR Storage Class is limited to "
+                      "AnyHitKHR, ClosestHitKHR, and MissKHR execution model";
+                }
+                return false;
+              }
+              return true;
+            });
+  } else if (storage_class == spv::StorageClass::ShaderRecordBufferKHR) {
+    std::string errorVUID = VkErrorID(7119);
+    function(consumer->function()->id())
+        ->RegisterExecutionModelLimitation(
+            [errorVUID](spv::ExecutionModel model, std::string* message) {
+              if (model != spv::ExecutionModel::RayGenerationKHR &&
+                  model != spv::ExecutionModel::IntersectionKHR &&
+                  model != spv::ExecutionModel::AnyHitKHR &&
+                  model != spv::ExecutionModel::ClosestHitKHR &&
+                  model != spv::ExecutionModel::CallableKHR &&
+                  model != spv::ExecutionModel::MissKHR) {
+                if (message) {
+                  *message =
+                      errorVUID +
+                      "ShaderRecordBufferKHR Storage Class is limited to "
+                      "RayGenerationKHR, IntersectionKHR, AnyHitKHR, "
+                      "ClosestHitKHR, CallableKHR, and MissKHR execution model";
+                }
+                return false;
+              }
+              return true;
+            });
+  } else if (storage_class == spv::StorageClass::TaskPayloadWorkgroupEXT) {
+    function(consumer->function()->id())
+        ->RegisterExecutionModelLimitation(
+            [](spv::ExecutionModel model, std::string* message) {
+              if (model != spv::ExecutionModel::TaskEXT &&
+                  model != spv::ExecutionModel::MeshEXT) {
+                if (message) {
+                  *message =
+                      "TaskPayloadWorkgroupEXT Storage Class is limited to "
+                      "TaskEXT and MeshKHR execution model";
+                }
+                return false;
+              }
+              return true;
+            });
+  }
 }
 
 uint32_t ValidationState_t::getIdBound() const { return id_bound_; }
@@ -680,9 +821,9 @@
   return inst ? inst->type_id() : 0;
 }
 
-SpvOp ValidationState_t::GetIdOpcode(uint32_t id) const {
+spv::Op ValidationState_t::GetIdOpcode(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst ? inst->opcode() : SpvOpNop;
+  return inst ? inst->opcode() : spv::Op::OpNop;
 }
 
 uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
@@ -690,18 +831,18 @@
   assert(inst);
 
   switch (inst->opcode()) {
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeBool:
       return id;
 
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       return inst->word(2);
 
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       return GetComponentType(inst->word(2));
 
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       return inst->word(2);
 
     default:
@@ -719,16 +860,16 @@
   assert(inst);
 
   switch (inst->opcode()) {
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeBool:
       return 1;
 
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
       return inst->word(3);
 
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       // Actual dimension isn't known, return 0
       return 0;
 
@@ -747,10 +888,11 @@
   const Instruction* inst = FindDef(component_type_id);
   assert(inst);
 
-  if (inst->opcode() == SpvOpTypeFloat || inst->opcode() == SpvOpTypeInt)
+  if (inst->opcode() == spv::Op::OpTypeFloat ||
+      inst->opcode() == spv::Op::OpTypeInt)
     return inst->word(2);
 
-  if (inst->opcode() == SpvOpTypeBool) return 1;
+  if (inst->opcode() == spv::Op::OpTypeBool) return 1;
 
   assert(0);
   return 0;
@@ -758,12 +900,12 @@
 
 bool ValidationState_t::IsVoidType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeVoid;
+  return inst && inst->opcode() == spv::Op::OpTypeVoid;
 }
 
 bool ValidationState_t::IsFloatScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeFloat;
+  return inst && inst->opcode() == spv::Op::OpTypeFloat;
 }
 
 bool ValidationState_t::IsFloatVectorType(uint32_t id) const {
@@ -772,7 +914,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsFloatScalarType(GetComponentType(id));
   }
 
@@ -785,11 +927,11 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeFloat) {
+  if (inst->opcode() == spv::Op::OpTypeFloat) {
     return true;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsFloatScalarType(GetComponentType(id));
   }
 
@@ -798,7 +940,7 @@
 
 bool ValidationState_t::IsIntScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeInt;
+  return inst && inst->opcode() == spv::Op::OpTypeInt;
 }
 
 bool ValidationState_t::IsIntVectorType(uint32_t id) const {
@@ -807,7 +949,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsIntScalarType(GetComponentType(id));
   }
 
@@ -820,11 +962,11 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeInt) {
+  if (inst->opcode() == spv::Op::OpTypeInt) {
     return true;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsIntScalarType(GetComponentType(id));
   }
 
@@ -833,7 +975,7 @@
 
 bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeInt && inst->word(3) == 0;
+  return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 0;
 }
 
 bool ValidationState_t::IsUnsignedIntVectorType(uint32_t id) const {
@@ -842,7 +984,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsUnsignedIntScalarType(GetComponentType(id));
   }
 
@@ -851,7 +993,7 @@
 
 bool ValidationState_t::IsSignedIntScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeInt && inst->word(3) == 1;
+  return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 1;
 }
 
 bool ValidationState_t::IsSignedIntVectorType(uint32_t id) const {
@@ -860,7 +1002,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsSignedIntScalarType(GetComponentType(id));
   }
 
@@ -869,7 +1011,7 @@
 
 bool ValidationState_t::IsBoolScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeBool;
+  return inst && inst->opcode() == spv::Op::OpTypeBool;
 }
 
 bool ValidationState_t::IsBoolVectorType(uint32_t id) const {
@@ -878,7 +1020,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsBoolScalarType(GetComponentType(id));
   }
 
@@ -891,11 +1033,11 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeBool) {
+  if (inst->opcode() == spv::Op::OpTypeBool) {
     return true;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsBoolScalarType(GetComponentType(id));
   }
 
@@ -908,7 +1050,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeMatrix) {
+  if (inst->opcode() == spv::Op::OpTypeMatrix) {
     return IsFloatScalarType(GetComponentType(id));
   }
 
@@ -923,13 +1065,13 @@
 
   const Instruction* mat_inst = FindDef(id);
   assert(mat_inst);
-  if (mat_inst->opcode() != SpvOpTypeMatrix) return false;
+  if (mat_inst->opcode() != spv::Op::OpTypeMatrix) return false;
 
   const uint32_t vec_type = mat_inst->word(2);
   const Instruction* vec_inst = FindDef(vec_type);
   assert(vec_inst);
 
-  if (vec_inst->opcode() != SpvOpTypeVector) {
+  if (vec_inst->opcode() != spv::Op::OpTypeVector) {
     assert(0);
     return false;
   }
@@ -949,7 +1091,7 @@
 
   const Instruction* inst = FindDef(struct_type_id);
   assert(inst);
-  if (inst->opcode() != SpvOpTypeStruct) return false;
+  if (inst->opcode() != spv::Op::OpTypeStruct) return false;
 
   *member_types =
       std::vector<uint32_t>(inst->words().cbegin() + 2, inst->words().cend());
@@ -961,30 +1103,31 @@
 
 bool ValidationState_t::IsPointerType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypePointer;
+  return inst && inst->opcode() == spv::Op::OpTypePointer;
 }
 
-bool ValidationState_t::GetPointerTypeInfo(uint32_t id, uint32_t* data_type,
-                                           uint32_t* storage_class) const {
+bool ValidationState_t::GetPointerTypeInfo(
+    uint32_t id, uint32_t* data_type, spv::StorageClass* storage_class) const {
+  *storage_class = spv::StorageClass::Max;
   if (!id) return false;
 
   const Instruction* inst = FindDef(id);
   assert(inst);
-  if (inst->opcode() != SpvOpTypePointer) return false;
+  if (inst->opcode() != spv::Op::OpTypePointer) return false;
 
-  *storage_class = inst->word(2);
+  *storage_class = spv::StorageClass(inst->word(2));
   *data_type = inst->word(3);
   return true;
 }
 
 bool ValidationState_t::IsAccelerationStructureType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeAccelerationStructureKHR;
+  return inst && inst->opcode() == spv::Op::OpTypeAccelerationStructureKHR;
 }
 
 bool ValidationState_t::IsCooperativeMatrixType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeCooperativeMatrixNV;
+  return inst && inst->opcode() == spv::Op::OpTypeCooperativeMatrixNV;
 }
 
 bool ValidationState_t::IsFloatCooperativeMatrixType(uint32_t id) const {
@@ -1014,8 +1157,8 @@
   const auto m1_type = FindDef(m1);
   const auto m2_type = FindDef(m2);
 
-  if (m1_type->opcode() != SpvOpTypeCooperativeMatrixNV ||
-      m2_type->opcode() != SpvOpTypeCooperativeMatrixNV) {
+  if (m1_type->opcode() != spv::Op::OpTypeCooperativeMatrixNV ||
+      m2_type->opcode() != spv::Op::OpTypeCooperativeMatrixNV) {
     return diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected cooperative matrix types";
   }
@@ -1080,7 +1223,8 @@
     return false;
   }
 
-  if (inst->opcode() != SpvOpConstant && inst->opcode() != SpvOpSpecConstant)
+  if (inst->opcode() != spv::Op::OpConstant &&
+      inst->opcode() != spv::Op::OpSpecConstant)
     return false;
 
   if (!IsIntScalarType(inst->type_id())) return false;
@@ -1112,7 +1256,7 @@
     return std::make_tuple(true, false, 0);
   }
 
-  if (inst->opcode() == SpvOpConstantNull) {
+  if (inst->opcode() == spv::Op::OpConstantNull) {
     return std::make_tuple(true, true, 0);
   }
 
@@ -1246,7 +1390,7 @@
     }
   }
 
-  if (lhs->opcode() == SpvOpTypeArray) {
+  if (lhs->opcode() == spv::Op::OpTypeArray) {
     // Size operands must match.
     if (lhs->GetOperandAs<uint32_t>(2u) != rhs->GetOperandAs<uint32_t>(2u)) {
       return false;
@@ -1265,7 +1409,7 @@
       return false;
     }
     return LogicallyMatch(lhs_ele, rhs_ele, check_decorations);
-  } else if (lhs->opcode() == SpvOpTypeStruct) {
+  } else if (lhs->opcode() == spv::Op::OpTypeStruct) {
     // Number of elements must match.
     if (lhs->operands().size() != rhs->operands().size()) {
       return false;
@@ -1303,11 +1447,11 @@
 const Instruction* ValidationState_t::TracePointer(
     const Instruction* inst) const {
   auto base_ptr = inst;
-  while (base_ptr->opcode() == SpvOpAccessChain ||
-         base_ptr->opcode() == SpvOpInBoundsAccessChain ||
-         base_ptr->opcode() == SpvOpPtrAccessChain ||
-         base_ptr->opcode() == SpvOpInBoundsPtrAccessChain ||
-         base_ptr->opcode() == SpvOpCopyObject) {
+  while (base_ptr->opcode() == spv::Op::OpAccessChain ||
+         base_ptr->opcode() == spv::Op::OpInBoundsAccessChain ||
+         base_ptr->opcode() == spv::Op::OpPtrAccessChain ||
+         base_ptr->opcode() == spv::Op::OpInBoundsPtrAccessChain ||
+         base_ptr->opcode() == spv::Op::OpCopyObject) {
     base_ptr = FindDef(base_ptr->GetOperandAs<uint32_t>(2u));
   }
   return base_ptr;
@@ -1322,25 +1466,25 @@
   if (f(inst)) return true;
 
   switch (inst->opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeImage:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       return ContainsType(inst->GetOperandAs<uint32_t>(1u), f,
                           traverse_all_types);
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       if (IsForwardPointer(id)) return false;
       if (traverse_all_types) {
         return ContainsType(inst->GetOperandAs<uint32_t>(2u), f,
                             traverse_all_types);
       }
       break;
-    case SpvOpTypeFunction:
-    case SpvOpTypeStruct:
-      if (inst->opcode() == SpvOpTypeFunction && !traverse_all_types) {
+    case spv::Op::OpTypeFunction:
+    case spv::Op::OpTypeStruct:
+      if (inst->opcode() == spv::Op::OpTypeFunction && !traverse_all_types) {
         return false;
       }
       for (uint32_t i = 1; i < inst->operands().size(); ++i) {
@@ -1357,9 +1501,9 @@
   return false;
 }
 
-bool ValidationState_t::ContainsSizedIntOrFloatType(uint32_t id, SpvOp type,
+bool ValidationState_t::ContainsSizedIntOrFloatType(uint32_t id, spv::Op type,
                                                     uint32_t width) const {
-  if (type != SpvOpTypeInt && type != SpvOpTypeFloat) return false;
+  if (type != spv::Op::OpTypeInt && type != spv::Op::OpTypeFloat) return false;
 
   const auto f = [type, width](const Instruction* inst) {
     if (inst->opcode() == type) {
@@ -1371,12 +1515,12 @@
 }
 
 bool ValidationState_t::ContainsLimitedUseIntOrFloatType(uint32_t id) const {
-  if ((!HasCapability(SpvCapabilityInt16) &&
-       ContainsSizedIntOrFloatType(id, SpvOpTypeInt, 16)) ||
-      (!HasCapability(SpvCapabilityInt8) &&
-       ContainsSizedIntOrFloatType(id, SpvOpTypeInt, 8)) ||
-      (!HasCapability(SpvCapabilityFloat16) &&
-       ContainsSizedIntOrFloatType(id, SpvOpTypeFloat, 16))) {
+  if ((!HasCapability(spv::Capability::Int16) &&
+       ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 16)) ||
+      (!HasCapability(spv::Capability::Int8) &&
+       ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 8)) ||
+      (!HasCapability(spv::Capability::Float16) &&
+       ContainsSizedIntOrFloatType(id, spv::Op::OpTypeFloat, 16))) {
     return true;
   }
   return false;
@@ -1384,32 +1528,33 @@
 
 bool ValidationState_t::ContainsRuntimeArray(uint32_t id) const {
   const auto f = [](const Instruction* inst) {
-    return inst->opcode() == SpvOpTypeRuntimeArray;
+    return inst->opcode() == spv::Op::OpTypeRuntimeArray;
   };
   return ContainsType(id, f, /* traverse_all_types = */ false);
 }
 
 bool ValidationState_t::IsValidStorageClass(
-    SpvStorageClass storage_class) const {
+    spv::StorageClass storage_class) const {
   if (spvIsVulkanEnv(context()->target_env)) {
     switch (storage_class) {
-      case SpvStorageClassUniformConstant:
-      case SpvStorageClassUniform:
-      case SpvStorageClassStorageBuffer:
-      case SpvStorageClassInput:
-      case SpvStorageClassOutput:
-      case SpvStorageClassImage:
-      case SpvStorageClassWorkgroup:
-      case SpvStorageClassPrivate:
-      case SpvStorageClassFunction:
-      case SpvStorageClassPushConstant:
-      case SpvStorageClassPhysicalStorageBuffer:
-      case SpvStorageClassRayPayloadKHR:
-      case SpvStorageClassIncomingRayPayloadKHR:
-      case SpvStorageClassHitAttributeKHR:
-      case SpvStorageClassCallableDataKHR:
-      case SpvStorageClassIncomingCallableDataKHR:
-      case SpvStorageClassShaderRecordBufferKHR:
+      case spv::StorageClass::UniformConstant:
+      case spv::StorageClass::Uniform:
+      case spv::StorageClass::StorageBuffer:
+      case spv::StorageClass::Input:
+      case spv::StorageClass::Output:
+      case spv::StorageClass::Image:
+      case spv::StorageClass::Workgroup:
+      case spv::StorageClass::Private:
+      case spv::StorageClass::Function:
+      case spv::StorageClass::PushConstant:
+      case spv::StorageClass::PhysicalStorageBuffer:
+      case spv::StorageClass::RayPayloadKHR:
+      case spv::StorageClass::IncomingRayPayloadKHR:
+      case spv::StorageClass::HitAttributeKHR:
+      case spv::StorageClass::CallableDataKHR:
+      case spv::StorageClass::IncomingCallableDataKHR:
+      case spv::StorageClass::ShaderRecordBufferKHR:
+      case spv::StorageClass::TaskPayloadWorkgroupEXT:
         return true;
       default:
         return false;
@@ -1853,8 +1998,8 @@
       return VUID_WRAP(VUID-StandaloneSpirv-None-04637);
     case 4638:
       return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
-    case 4639:
-      return VUID_WRAP(VUID-StandaloneSpirv-None-04639);
+    case 7321:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-07321);
     case 4640:
       return VUID_WRAP(VUID-StandaloneSpirv-None-04640);
     case 4641:
@@ -1911,6 +2056,26 @@
       return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685);
     case 4686:
       return VUID_WRAP(VUID-StandaloneSpirv-None-04686);
+    case 4698:
+      return VUID_WRAP(VUID-StandaloneSpirv-RayPayloadKHR-04698);
+    case 4699:
+      return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699);
+    case 4700:
+      return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04700);
+    case 4701:
+      return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04701);
+    case 4702:
+      return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04702);
+    case 4703:
+      return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04703);
+    case 4704:
+      return VUID_WRAP(VUID-StandaloneSpirv-CallableDataKHR-04704);
+    case 4705:
+      return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04705);
+    case 4706:
+      return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04706);
+    case 7119:
+      return VUID_WRAP(VUID-StandaloneSpirv-ShaderRecordBufferKHR-07119);
     case 4708:
       return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708);
     case 4710:
@@ -1945,6 +2110,16 @@
       return VUID_WRAP(VUID-StandaloneSpirv-Location-04918);
     case 4919:
       return VUID_WRAP(VUID-StandaloneSpirv-Location-04919);
+    case 4920:
+      return VUID_WRAP(VUID-StandaloneSpirv-Component-04920);
+    case 4921:
+      return VUID_WRAP(VUID-StandaloneSpirv-Component-04921);
+    case 4922:
+      return VUID_WRAP(VUID-StandaloneSpirv-Component-04922);
+    case 4923:
+      return VUID_WRAP(VUID-StandaloneSpirv-Component-04923);
+    case 4924:
+      return VUID_WRAP(VUID-StandaloneSpirv-Component-04924);
     case 6201:
       return VUID_WRAP(VUID-StandaloneSpirv-Flat-06201);
     case 6202:
@@ -1957,6 +2132,8 @@
       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeSampledImage-06671);
     case 6672:
       return VUID_WRAP(VUID-StandaloneSpirv-Location-06672);
+    case 6673:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-06673);
     case 6674:
       return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-06674);
     case 6675:
@@ -1977,6 +2154,22 @@
       return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06808);
     case 6925:
       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06925);
+    case 6997:
+      return VUID_WRAP(VUID-StandaloneSpirv-SubgroupVoteKHR-06997);
+    case 7102:
+      return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07102);
+    case 7320:
+      return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07320);
+    case 7290:
+      return VUID_WRAP(VUID-StandaloneSpirv-Input-07290);
+    case 7650:
+      return VUID_WRAP(VUID-StandaloneSpirv-Base-07650);
+    case 7651:
+      return VUID_WRAP(VUID-StandaloneSpirv-Base-07651);
+    case 7652:
+      return VUID_WRAP(VUID-StandaloneSpirv-Base-07652);
+    case 7703:
+      return VUID_WRAP(VUID-StandaloneSpirv-Component-07703);
     default:
       return "";  // unknown id
   }
diff --git a/third_party/SPIRV-Tools/source/val/validation_state.h b/third_party/SPIRV-Tools/source/val/validation_state.h
index b4d343d..4d5ac00 100644
--- a/third_party/SPIRV-Tools/source/val/validation_state.h
+++ b/third_party/SPIRV-Tools/source/val/validation_state.h
@@ -185,10 +185,10 @@
   void ProgressToNextLayoutSectionOrder();
 
   /// Determines if the op instruction is in a previous layout section
-  bool IsOpcodeInPreviousLayoutSection(SpvOp op);
+  bool IsOpcodeInPreviousLayoutSection(spv::Op op);
 
   /// Determines if the op instruction is part of the current section
-  bool IsOpcodeInCurrentLayoutSection(SpvOp op);
+  bool IsOpcodeInCurrentLayoutSection(spv::Op op);
 
   DiagnosticStream diag(spv_result_t error_code, const Instruction* inst);
 
@@ -217,7 +217,8 @@
   };
 
   /// Registers |id| as an entry point with |execution_model| and |interfaces|.
-  void RegisterEntryPoint(const uint32_t id, SpvExecutionModel execution_model,
+  void RegisterEntryPoint(const uint32_t id,
+                          spv::ExecutionModel execution_model,
                           EntryPointDescription&& desc) {
     entry_points_.push_back(id);
     entry_point_to_execution_models_[id].insert(execution_model);
@@ -235,7 +236,7 @@
 
   /// Registers execution mode for the given entry point.
   void RegisterExecutionModeForEntryPoint(uint32_t entry_point,
-                                          SpvExecutionMode execution_mode) {
+                                          spv::ExecutionMode execution_mode) {
     entry_point_to_execution_modes_[entry_point].insert(execution_mode);
   }
 
@@ -247,7 +248,7 @@
 
   /// Returns Execution Models for the given Entry Point.
   /// Returns nullptr if none found (would trigger assertion).
-  const std::set<SpvExecutionModel>* GetExecutionModels(
+  const std::set<spv::ExecutionModel>* GetExecutionModels(
       uint32_t entry_point) const {
     const auto it = entry_point_to_execution_models_.find(entry_point);
     if (it == entry_point_to_execution_models_.end()) {
@@ -259,7 +260,7 @@
 
   /// Returns Execution Modes for the given Entry Point.
   /// Returns nullptr if none found.
-  const std::set<SpvExecutionMode>* GetExecutionModes(
+  const std::set<spv::ExecutionMode>* GetExecutionModes(
       uint32_t entry_point) const {
     const auto it = entry_point_to_execution_modes_.find(entry_point);
     if (it == entry_point_to_execution_modes_.end()) {
@@ -300,7 +301,7 @@
     return (id_to_function_.find(id) != id_to_function_.end());
   }
   /// Registers the capability and its dependent capabilities
-  void RegisterCapability(SpvCapability cap);
+  void RegisterCapability(spv::Capability cap);
 
   /// Registers the extension.
   void RegisterExtension(Extension ext);
@@ -308,14 +309,14 @@
   /// Registers the function in the module. Subsequent instructions will be
   /// called against this function
   spv_result_t RegisterFunction(uint32_t id, uint32_t ret_type_id,
-                                SpvFunctionControlMask function_control,
+                                spv::FunctionControlMask function_control,
                                 uint32_t function_type_id);
 
   /// Register a function end instruction
   spv_result_t RegisterFunctionEnd();
 
   /// Returns true if the capability is enabled in the module.
-  bool HasCapability(SpvCapability cap) const {
+  bool HasCapability(spv::Capability cap) const {
     return module_capabilities_.Contains(cap);
   }
 
@@ -339,16 +340,16 @@
   bool HasAnyOfExtensions(const ExtensionSet& extensions) const;
 
   /// Sets the addressing model of this module (logical/physical).
-  void set_addressing_model(SpvAddressingModel am);
+  void set_addressing_model(spv::AddressingModel am);
 
   /// Returns true if the OpMemoryModel was found.
   bool has_memory_model_specified() const {
-    return addressing_model_ != SpvAddressingModelMax &&
-           memory_model_ != SpvMemoryModelMax;
+    return addressing_model_ != spv::AddressingModel::Max &&
+           memory_model_ != spv::MemoryModel::Max;
   }
 
   /// Returns the addressing model of this module, or Logical if uninitialized.
-  SpvAddressingModel addressing_model() const;
+  spv::AddressingModel addressing_model() const;
 
   /// Returns the addressing model of this module, or Logical if uninitialized.
   uint32_t pointer_size_and_alignment() const {
@@ -356,10 +357,10 @@
   }
 
   /// Sets the memory model of this module.
-  void set_memory_model(SpvMemoryModel mm);
+  void set_memory_model(spv::MemoryModel mm);
 
   /// Returns the memory model of this module, or Simple if uninitialized.
-  SpvMemoryModel memory_model() const;
+  spv::MemoryModel memory_model() const;
 
   /// Sets the bit width for sampler/image type variables. If not set, they are
   /// considered opaque
@@ -432,8 +433,8 @@
 
     // The decorations are sorted by member_index, so this look up will give the
     // exact range of decorations for this member index.
-    Decoration min_decoration((SpvDecoration)0, {}, member_index);
-    Decoration max_decoration(SpvDecorationMax, {}, member_index);
+    Decoration min_decoration((spv::Decoration)0, {}, member_index);
+    Decoration max_decoration(spv::Decoration::Max, {}, member_index);
 
     FieldDecorationsIter result;
     result.begin = decorations.lower_bound(min_decoration);
@@ -449,7 +450,7 @@
 
   /// Returns true if the given id <id> has the given decoration <dec>,
   /// otherwise returns false.
-  bool HasDecoration(uint32_t id, SpvDecoration dec) {
+  bool HasDecoration(uint32_t id, spv::Decoration dec) {
     const auto& decorations = id_decorations_.find(id);
     if (decorations == id_decorations_.end()) return false;
 
@@ -485,7 +486,7 @@
                                     Instruction* consumer);
 
   // Record a function's storage class consumer instruction
-  void RegisterStorageClassConsumer(SpvStorageClass storage_class,
+  void RegisterStorageClassConsumer(spv::StorageClass storage_class,
                                     Instruction* consumer);
 
   /// Returns the set of Global Variables.
@@ -616,7 +617,7 @@
 
   // Returns true if |id| is a type id that contains |type| (or integer or
   // floating point type) of |width| bits.
-  bool ContainsSizedIntOrFloatType(uint32_t id, SpvOp type,
+  bool ContainsSizedIntOrFloatType(uint32_t id, spv::Op type,
                                    uint32_t width) const;
   // Returns true if |id| is a type id that contains a 8- or 16-bit int or
   // 16-bit float that is not generally enabled for use.
@@ -642,7 +643,7 @@
 
   // Returns opcode of the instruction which issued the id or OpNop if the
   // instruction is not registered.
-  SpvOp GetIdOpcode(uint32_t id) const;
+  spv::Op GetIdOpcode(uint32_t id) const;
 
   // Returns type_id for given id operand if it has a type or zero otherwise.
   // |operand_index| is expected to be pointing towards an operand which is an
@@ -652,7 +653,7 @@
 
   // Provides information on pointer type. Returns false iff not pointer type.
   bool GetPointerTypeInfo(uint32_t id, uint32_t* data_type,
-                          uint32_t* storage_class) const;
+                          spv::StorageClass* storage_class) const;
 
   // Is the ID the type of a pointer to a uniform block: Block-decorated struct
   // in uniform storage class? The result is only valid after internal method
@@ -723,6 +724,19 @@
   // Returns the disassembly string for the given instruction.
   std::string Disassemble(const uint32_t* words, uint16_t num_words) const;
 
+  // Returns the string name for |decoration|.
+  std::string SpvDecorationString(uint32_t decoration) {
+    spv_operand_desc desc = nullptr;
+    if (grammar_.lookupOperand(SPV_OPERAND_TYPE_DECORATION, decoration,
+                               &desc) != SPV_SUCCESS) {
+      return std::string("Unknown");
+    }
+    return std::string(desc->name);
+  }
+  std::string SpvDecorationString(spv::Decoration decoration) {
+    return SpvDecorationString(uint32_t(decoration));
+  }
+
   // Returns whether type m1 and type m2 are cooperative matrices with
   // the same "shape" (matching scope, rows, cols). If any are specialization
   // constants, we assume they can match because we can't prove they don't.
@@ -754,7 +768,7 @@
   const Instruction* TracePointer(const Instruction* inst) const;
 
   // Validates the storage class for the target environment.
-  bool IsValidStorageClass(SpvStorageClass storage_class) const;
+  bool IsValidStorageClass(spv::StorageClass storage_class) const;
 
   // Takes a Vulkan Valid Usage ID (VUID) as |id| and optional |reference| and
   // will return a non-empty string only if ID is known and targeting Vulkan.
@@ -873,8 +887,8 @@
 
   AssemblyGrammar grammar_;
 
-  SpvAddressingModel addressing_model_;
-  SpvMemoryModel memory_model_;
+  spv::AddressingModel addressing_model_;
+  spv::MemoryModel memory_model_;
   // pointer size derived from addressing model. Assumes all storage classes
   // have the same pointer size (for physical pointer types).
   uint32_t pointer_size_and_alignment_;
@@ -895,11 +909,11 @@
   /// Mapping entry point -> execution models. It is presumed that the same
   /// function could theoretically be used as 'main' by multiple OpEntryPoint
   /// instructions.
-  std::unordered_map<uint32_t, std::set<SpvExecutionModel>>
+  std::unordered_map<uint32_t, std::set<spv::ExecutionModel>>
       entry_point_to_execution_models_;
 
   /// Mapping entry point -> execution modes.
-  std::unordered_map<uint32_t, std::set<SpvExecutionMode>>
+  std::unordered_map<uint32_t, std::set<spv::ExecutionMode>>
       entry_point_to_execution_modes_;
 
   /// Mapping function -> array of entry points inside this
diff --git a/third_party/SPIRV-Tools/test/binary_header_get_test.cpp b/third_party/SPIRV-Tools/test/binary_header_get_test.cpp
index f94f0c1..aca09b0 100644
--- a/third_party/SPIRV-Tools/test/binary_header_get_test.cpp
+++ b/third_party/SPIRV-Tools/test/binary_header_get_test.cpp
@@ -23,8 +23,8 @@
   BinaryHeaderGet() { memset(code, 0, sizeof(code)); }
 
   virtual void SetUp() {
-    code[0] = SpvMagicNumber;
-    code[1] = SpvVersion;
+    code[0] = static_cast<uint32_t>(spv::MagicNumber);
+    code[1] = static_cast<uint32_t>(spv::Version);
     code[2] = SPV_GENERATOR_CODEPLAY;
     code[3] = 1;  // NOTE: Bound
     code[4] = 0;  // NOTE: Schema; reserved
@@ -50,7 +50,7 @@
   spv_header_t header;
   ASSERT_EQ(SPV_SUCCESS, spvBinaryHeaderGet(&const_bin, endian, &header));
 
-  ASSERT_EQ(static_cast<uint32_t>(SpvMagicNumber), header.magic);
+  ASSERT_EQ(static_cast<uint32_t>(spv::MagicNumber), header.magic);
   // Expect SPIRV-Headers updated to SPIR-V 1.6.
   ASSERT_EQ(0x00010600u, header.version);
   ASSERT_EQ(static_cast<uint32_t>(SPV_GENERATOR_CODEPLAY), header.generator);
diff --git a/third_party/SPIRV-Tools/test/binary_parse_test.cpp b/third_party/SPIRV-Tools/test/binary_parse_test.cpp
index f0810a3..4c699c1 100644
--- a/third_party/SPIRV-Tools/test/binary_parse_test.cpp
+++ b/third_party/SPIRV-Tools/test/binary_parse_test.cpp
@@ -54,14 +54,14 @@
 struct ParsedInstruction {
   explicit ParsedInstruction(const spv_parsed_instruction_t& inst)
       : words(inst.words, inst.words + inst.num_words),
-        opcode(static_cast<SpvOp>(inst.opcode)),
+        opcode(static_cast<spv::Op>(inst.opcode)),
         ext_inst_type(inst.ext_inst_type),
         type_id(inst.type_id),
         result_id(inst.result_id),
         operands(inst.operands, inst.operands + inst.num_operands) {}
 
   std::vector<uint32_t> words;
-  SpvOp opcode;
+  spv::Op opcode;
   spv_ext_inst_type_t ext_inst_type;
   uint32_t type_id;
   uint32_t result_id;
@@ -127,14 +127,14 @@
 // The SPIR-V module header words for the Khronos Assembler generator,
 // for a module with an ID bound of 1.
 const uint32_t kHeaderForBound1[] = {
-    SpvMagicNumber, SpvVersion,
+    spv::MagicNumber, spv::Version,
     SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0), 1 /*bound*/,
     0 /*schema*/};
 
 // Returns the expected SPIR-V module header words for the Khronos
 // Assembler generator, and with a given Id bound.
 std::vector<uint32_t> ExpectedHeaderForBound(uint32_t bound) {
-  return {SpvMagicNumber, 0x10000,
+  return {spv::MagicNumber, 0x10000,
           SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0), bound, 0};
 }
 
@@ -162,13 +162,13 @@
 // Returns a ParsedInstruction for an OpTypeVoid instruction that would
 // generate the given result Id.
 ParsedInstruction MakeParsedVoidTypeInstruction(uint32_t result_id) {
-  const auto void_inst = MakeInstruction(SpvOpTypeVoid, {result_id});
+  const auto void_inst = MakeInstruction(spv::Op::OpTypeVoid, {result_id});
   const auto void_operands = std::vector<spv_parsed_operand_t>{
       MakeSimpleOperand(1, SPV_OPERAND_TYPE_RESULT_ID)};
   const spv_parsed_instruction_t parsed_void_inst = {
       void_inst.data(),
       static_cast<uint16_t>(void_inst.size()),
-      SpvOpTypeVoid,
+      uint16_t(spv::Op::OpTypeVoid),
       SPV_EXT_INST_TYPE_NONE,
       0,  // type id
       result_id,
@@ -180,14 +180,14 @@
 // Returns a ParsedInstruction for an OpTypeInt instruction that generates
 // the given result Id for a 32-bit signed integer scalar type.
 ParsedInstruction MakeParsedInt32TypeInstruction(uint32_t result_id) {
-  const auto i32_inst = MakeInstruction(SpvOpTypeInt, {result_id, 32, 1});
+  const auto i32_inst = MakeInstruction(spv::Op::OpTypeInt, {result_id, 32, 1});
   const auto i32_operands = std::vector<spv_parsed_operand_t>{
       MakeSimpleOperand(1, SPV_OPERAND_TYPE_RESULT_ID),
       MakeLiteralNumberOperand(2), MakeLiteralNumberOperand(3)};
   spv_parsed_instruction_t parsed_i32_inst = {
       i32_inst.data(),
       static_cast<uint16_t>(i32_inst.size()),
-      SpvOpTypeInt,
+      uint16_t(spv::Op::OpTypeInt),
       SPV_EXT_INST_TYPE_NONE,
       0,  // type id
       result_id,
@@ -216,12 +216,12 @@
 
 // Adds an EXPECT_CALL to client_->Header() with appropriate parameters,
 // including bound.  Returns the EXPECT_CALL result.
-#define EXPECT_HEADER(bound)                                                   \
-  EXPECT_CALL(                                                                 \
-      client_,                                                                 \
-      Header(AnyOf(SPV_ENDIANNESS_LITTLE, SPV_ENDIANNESS_BIG), SpvMagicNumber, \
-             0x10000, SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0),  \
-             bound, 0 /*reserved*/))
+#define EXPECT_HEADER(bound)                                                 \
+  EXPECT_CALL(client_,                                                       \
+              Header(AnyOf(SPV_ENDIANNESS_LITTLE, SPV_ENDIANNESS_BIG),       \
+                     spv::MagicNumber, 0x10000,                              \
+                     SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0), \
+                     bound, 0 /*reserved*/))
 
 static const bool kSwapEndians[] = {false, true};
 
@@ -481,19 +481,20 @@
     const std::string str =
         "the future is already here, it's just not evenly distributed";
     const auto str_words = MakeVector(str);
-    const auto instruction = MakeInstruction(SpvOpName, {99}, str_words);
+    const auto instruction = MakeInstruction(spv::Op::OpName, {99}, str_words);
     const auto words = Concatenate({ExpectedHeaderForBound(100), instruction});
     InSequence calls_expected_in_specific_order;
     EXPECT_HEADER(100).WillOnce(Return(SPV_SUCCESS));
     const auto operands = std::vector<spv_parsed_operand_t>{
         MakeSimpleOperand(1, SPV_OPERAND_TYPE_ID),
         MakeLiteralStringOperand(2, static_cast<uint16_t>(str_words.size()))};
-    EXPECT_CALL(client_, Instruction(ParsedInstruction(spv_parsed_instruction_t{
-                             instruction.data(),
-                             static_cast<uint16_t>(instruction.size()),
-                             SpvOpName, SPV_EXT_INST_TYPE_NONE, 0 /*type id*/,
-                             0 /* No result id for OpName*/, operands.data(),
-                             static_cast<uint16_t>(operands.size())})))
+    EXPECT_CALL(
+        client_,
+        Instruction(ParsedInstruction(spv_parsed_instruction_t{
+            instruction.data(), static_cast<uint16_t>(instruction.size()),
+            uint16_t(spv::Op::OpName), SPV_EXT_INST_TYPE_NONE, 0 /*type id*/,
+            0 /* No result id for OpName*/, operands.data(),
+            static_cast<uint16_t>(operands.size())})))
         .WillOnce(Return(SPV_SUCCESS));
     Parse(words, SPV_SUCCESS, endian_swap);
     EXPECT_EQ(nullptr, diagnostic_);
@@ -518,13 +519,13 @@
       MakeSimpleOperand(5, SPV_OPERAND_TYPE_ID),  // Id of the argument
   };
   const auto instruction = MakeInstruction(
-      SpvOpExtInst,
+      spv::Op::OpExtInst,
       {2, 3, 1, static_cast<uint32_t>(OpenCLLIB::Entrypoints::Sqrt), 4});
   EXPECT_CALL(client_,
               Instruction(ParsedInstruction(spv_parsed_instruction_t{
                   instruction.data(), static_cast<uint16_t>(instruction.size()),
-                  SpvOpExtInst, SPV_EXT_INST_TYPE_OPENCL_STD, 2 /*type id*/,
-                  3 /*result id*/, operands.data(),
+                  uint16_t(spv::Op::OpExtInst), SPV_EXT_INST_TYPE_OPENCL_STD,
+                  2 /*type id*/, 3 /*result id*/, operands.data(),
                   static_cast<uint16_t>(operands.size())})))
       .WillOnce(Return(SPV_SUCCESS));
   // Since we are actually checking the output, don't test the
@@ -593,36 +594,38 @@
 INSTANTIATE_TEST_SUITE_P(
     BinaryParseDiagnostic, BinaryParseWordVectorDiagnosticTest,
     ::testing::ValuesIn(std::vector<WordVectorDiagnosticCase>{
-        {Concatenate({ExpectedHeaderForBound(1), {spvOpcodeMake(0, SpvOpNop)}}),
+        {Concatenate({ExpectedHeaderForBound(1),
+                      {spvOpcodeMake(0, spv::Op::OpNop)}}),
          "Invalid instruction word count: 0"},
         {Concatenate(
              {ExpectedHeaderForBound(1),
-              {spvOpcodeMake(1, static_cast<SpvOp>(
+              {spvOpcodeMake(1, static_cast<spv::Op>(
                                     std::numeric_limits<uint16_t>::max()))}}),
          "Invalid opcode: 65535"},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpNop, {42})}),
+                      MakeInstruction(spv::Op::OpNop, {42})}),
          "Invalid instruction OpNop starting at word 5: expected "
          "no more operands after 1 words, but stated word count is 2."},
         // Supply several more unexpected words.
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpNop, {42, 43, 44, 45, 46, 47})}),
+                      MakeInstruction(spv::Op::OpNop,
+                                      {42, 43, 44, 45, 46, 47})}),
          "Invalid instruction OpNop starting at word 5: expected "
          "no more operands after 1 words, but stated word count is 7."},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpTypeVoid, {1, 2})}),
+                      MakeInstruction(spv::Op::OpTypeVoid, {1, 2})}),
          "Invalid instruction OpTypeVoid starting at word 5: expected "
          "no more operands after 2 words, but stated word count is 3."},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpTypeVoid, {1, 2, 5, 9, 10})}),
+                      MakeInstruction(spv::Op::OpTypeVoid, {1, 2, 5, 9, 10})}),
          "Invalid instruction OpTypeVoid starting at word 5: expected "
          "no more operands after 2 words, but stated word count is 6."},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpTypeInt, {1, 32, 1, 9})}),
+                      MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1, 9})}),
          "Invalid instruction OpTypeInt starting at word 5: expected "
          "no more operands after 4 words, but stated word count is 5."},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpTypeInt, {1})}),
+                      MakeInstruction(spv::Op::OpTypeInt, {1})}),
          "End of input reached while decoding OpTypeInt starting at word 5:"
          " expected more operands after 2 words."},
 
@@ -630,7 +633,7 @@
 
         // Detect a missing single word operand.
         {Concatenate({ExpectedHeaderForBound(1),
-                      {spvOpcodeMake(2, SpvOpTypeStruct)}}),
+                      {spvOpcodeMake(2, spv::Op::OpTypeStruct)}}),
          "End of input reached while decoding OpTypeStruct starting at word"
          " 5: missing result ID operand at word offset 1."},
         // Detect this a missing a multi-word operand to OpConstant.
@@ -639,29 +642,29 @@
         //    %1 = OpTypeInt 64 0
         //    %2 = OpConstant %1 <missing>
         {Concatenate({ExpectedHeaderForBound(3),
-                      {MakeInstruction(SpvOpTypeInt, {1, 64, 0})},
-                      {spvOpcodeMake(5, SpvOpConstant), 1, 2}}),
+                      {MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0})},
+                      {spvOpcodeMake(5, spv::Op::OpConstant), 1, 2}}),
          "End of input reached while decoding OpConstant starting at word"
          " 9: missing possibly multi-word literal number operand at word "
          "offset 3."},
         // Detect when we provide only one word from the 64-bit literal,
         // and again lie about the number of words in the instruction.
         {Concatenate({ExpectedHeaderForBound(3),
-                      {MakeInstruction(SpvOpTypeInt, {1, 64, 0})},
-                      {spvOpcodeMake(5, SpvOpConstant), 1, 2, 42}}),
+                      {MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0})},
+                      {spvOpcodeMake(5, spv::Op::OpConstant), 1, 2, 42}}),
          "End of input reached while decoding OpConstant starting at word"
          " 9: truncated possibly multi-word literal number operand at word "
          "offset 3."},
         // Detect when a required string operand is missing.
         // Also, lie about the length of the instruction.
         {Concatenate({ExpectedHeaderForBound(3),
-                      {spvOpcodeMake(3, SpvOpString), 1}}),
+                      {spvOpcodeMake(3, spv::Op::OpString), 1}}),
          "End of input reached while decoding OpString starting at word"
          " 5: missing literal string operand at word offset 2."},
         // Detect when a required string operand is truncated: it's missing
         // a null terminator.  Catching the error avoids a buffer overrun.
         {Concatenate({ExpectedHeaderForBound(3),
-                      {spvOpcodeMake(4, SpvOpString), 1, 0x41414141,
+                      {spvOpcodeMake(4, spv::Op::OpString), 1, 0x41414141,
                        0x41414141}}),
          "End of input reached while decoding OpString starting at word"
          " 5: truncated literal string operand at word offset 2."},
@@ -669,9 +672,9 @@
         // a null terminator.  Catching the error avoids a buffer overrun.
         // (It is valid for an optional string operand to be absent.)
         {Concatenate({ExpectedHeaderForBound(3),
-                      {spvOpcodeMake(6, SpvOpSource),
-                       static_cast<uint32_t>(SpvSourceLanguageOpenCL_C), 210,
-                       1 /* file id */,
+                      {spvOpcodeMake(6, spv::Op::OpSource),
+                       static_cast<uint32_t>(spv::SourceLanguage::OpenCL_C),
+                       210, 1 /* file id */,
                        /*start of string*/ 0x41414141, 0x41414141}}),
          "End of input reached while decoding OpSource starting at word"
          " 5: truncated literal string operand at word offset 4."},
@@ -681,19 +684,19 @@
         // In this case the instruction word count is too small, where
         // it would truncate a multi-word operand to OpConstant.
         {Concatenate({ExpectedHeaderForBound(3),
-                      {MakeInstruction(SpvOpTypeInt, {1, 64, 0})},
-                      {spvOpcodeMake(4, SpvOpConstant), 1, 2, 44, 44}}),
+                      {MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0})},
+                      {spvOpcodeMake(4, spv::Op::OpConstant), 1, 2, 44, 44}}),
          "Invalid word count: OpConstant starting at word 9 says it has 4"
          " words, but found 5 words instead."},
         // Word count is to small, where it would truncate a literal string.
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(3, SpvOpString), 1, 0x41414141, 0}}),
+                      {spvOpcodeMake(3, spv::Op::OpString), 1, 0x41414141, 0}}),
          "Invalid word count: OpString starting at word 5 says it has 3"
          " words, but found 4 words instead."},
         // Word count is too large.  The string terminates before the last
         // word.
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(4, SpvOpString), 1 /* result id */},
+                      {spvOpcodeMake(4, spv::Op::OpString), 1 /* result id */},
                       MakeVector("abc"),
                       {0 /* this word does not belong*/}}),
          "Invalid instruction OpString starting at word 5: expected no more"
@@ -701,111 +704,116 @@
         // Word count is too large.  There are too many words after the string
         // literal.  A linkage attribute decoration is the only case in SPIR-V
         // where a string operand is followed by another operand.
-        {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(6, SpvOpDecorate), 1 /* target id */,
-                       static_cast<uint32_t>(SpvDecorationLinkageAttributes)},
-                      MakeVector("abc"),
-                      {static_cast<uint32_t>(SpvLinkageTypeImport),
-                       0 /* does not belong */}}),
+        {Concatenate(
+             {ExpectedHeaderForBound(2),
+              {spvOpcodeMake(6, spv::Op::OpDecorate), 1 /* target id */,
+               static_cast<uint32_t>(spv::Decoration::LinkageAttributes)},
+              MakeVector("abc"),
+              {static_cast<uint32_t>(spv::LinkageType::Import),
+               0 /* does not belong */}}),
          "Invalid instruction OpDecorate starting at word 5: expected no more"
          " operands after 5 words, but stated word count is 6."},
         // Like the previous case, but with 5 extra words.
-        {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(10, SpvOpDecorate), 1 /* target id */,
-                       static_cast<uint32_t>(SpvDecorationLinkageAttributes)},
-                      MakeVector("abc"),
-                      {static_cast<uint32_t>(SpvLinkageTypeImport),
-                       /* don't belong */ 0, 1, 2, 3, 4}}),
+        {Concatenate(
+             {ExpectedHeaderForBound(2),
+              {spvOpcodeMake(10, spv::Op::OpDecorate), 1 /* target id */,
+               static_cast<uint32_t>(spv::Decoration::LinkageAttributes)},
+              MakeVector("abc"),
+              {static_cast<uint32_t>(spv::LinkageType::Import),
+               /* don't belong */ 0, 1, 2, 3, 4}}),
          "Invalid instruction OpDecorate starting at word 5: expected no more"
          " operands after 5 words, but stated word count is 10."},
         // Like the previous two cases, but with OpMemberDecorate.
-        {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(7, SpvOpMemberDecorate), 1 /* target id */,
-                       42 /* member index */,
-                       static_cast<uint32_t>(SpvDecorationLinkageAttributes)},
-                      MakeVector("abc"),
-                      {static_cast<uint32_t>(SpvLinkageTypeImport),
-                       0 /* does not belong */}}),
+        {Concatenate(
+             {ExpectedHeaderForBound(2),
+              {spvOpcodeMake(7, spv::Op::OpMemberDecorate), 1 /* target id */,
+               42 /* member index */,
+               static_cast<uint32_t>(spv::Decoration::LinkageAttributes)},
+              MakeVector("abc"),
+              {static_cast<uint32_t>(spv::LinkageType::Import),
+               0 /* does not belong */}}),
          "Invalid instruction OpMemberDecorate starting at word 5: expected no"
          " more operands after 6 words, but stated word count is 7."},
-        {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(11, SpvOpMemberDecorate),
-                       1 /* target id */, 42 /* member index */,
-                       static_cast<uint32_t>(SpvDecorationLinkageAttributes)},
-                      MakeVector("abc"),
-                      {static_cast<uint32_t>(SpvLinkageTypeImport),
-                       /* don't belong */ 0, 1, 2, 3, 4}}),
+        {Concatenate(
+             {ExpectedHeaderForBound(2),
+              {spvOpcodeMake(11, spv::Op::OpMemberDecorate), 1 /* target id */,
+               42 /* member index */,
+               static_cast<uint32_t>(spv::Decoration::LinkageAttributes)},
+              MakeVector("abc"),
+              {static_cast<uint32_t>(spv::LinkageType::Import),
+               /* don't belong */ 0, 1, 2, 3, 4}}),
          "Invalid instruction OpMemberDecorate starting at word 5: expected no"
          " more operands after 6 words, but stated word count is 11."},
         // Word count is too large.  There should be no more words
         // after the RelaxedPrecision decoration.
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(4, SpvOpDecorate), 1 /* target id */,
-                       static_cast<uint32_t>(SpvDecorationRelaxedPrecision),
+                      {spvOpcodeMake(4, spv::Op::OpDecorate), 1 /* target id */,
+                       static_cast<uint32_t>(spv::Decoration::RelaxedPrecision),
                        0 /* does not belong */}}),
          "Invalid instruction OpDecorate starting at word 5: expected no"
          " more operands after 3 words, but stated word count is 4."},
         // Word count is too large.  There should be only one word after
         // the SpecId decoration enum word.
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(5, SpvOpDecorate), 1 /* target id */,
-                       static_cast<uint32_t>(SpvDecorationSpecId),
+                      {spvOpcodeMake(5, spv::Op::OpDecorate), 1 /* target id */,
+                       static_cast<uint32_t>(spv::Decoration::SpecId),
                        42 /* the spec id */, 0 /* does not belong */}}),
          "Invalid instruction OpDecorate starting at word 5: expected no"
          " more operands after 4 words, but stated word count is 5."},
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(2, SpvOpTypeVoid), 0}}),
+                      {spvOpcodeMake(2, spv::Op::OpTypeVoid), 0}}),
          "Error: Result Id is 0"},
         {Concatenate({
              ExpectedHeaderForBound(2),
-             {spvOpcodeMake(2, SpvOpTypeVoid), 1},
-             {spvOpcodeMake(2, SpvOpTypeBool), 1},
+             {spvOpcodeMake(2, spv::Op::OpTypeVoid), 1},
+             {spvOpcodeMake(2, spv::Op::OpTypeBool), 1},
          }),
          "Id 1 is defined more than once"},
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpExtInst, {2, 3, 100, 4, 5})}),
+                      MakeInstruction(spv::Op::OpExtInst, {2, 3, 100, 4, 5})}),
          "OpExtInst set Id 100 does not reference an OpExtInstImport result "
          "Id"},
         {Concatenate({ExpectedHeaderForBound(101),
-                      MakeInstruction(SpvOpExtInstImport, {100},
+                      MakeInstruction(spv::Op::OpExtInstImport, {100},
                                       MakeVector("OpenCL.std")),
                       // OpenCL cos is #14
-                      MakeInstruction(SpvOpExtInst, {2, 3, 100, 14, 5, 999})}),
+                      MakeInstruction(spv::Op::OpExtInst,
+                                      {2, 3, 100, 14, 5, 999})}),
          "Invalid instruction OpExtInst starting at word 10: expected no "
          "more operands after 6 words, but stated word count is 7."},
         // In this case, the OpSwitch selector refers to an invalid ID.
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpSwitch, {1, 2, 42, 3})}),
+                      MakeInstruction(spv::Op::OpSwitch, {1, 2, 42, 3})}),
          "Invalid OpSwitch: selector id 1 has no type"},
         // In this case, the OpSwitch selector refers to an ID that has
         // no type.
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpLabel, {1}),
-                      MakeInstruction(SpvOpSwitch, {1, 2, 42, 3})}),
+                      MakeInstruction(spv::Op::OpLabel, {1}),
+                      MakeInstruction(spv::Op::OpSwitch, {1, 2, 42, 3})}),
          "Invalid OpSwitch: selector id 1 has no type"},
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-                      MakeInstruction(SpvOpSwitch, {1, 3, 42, 3})}),
+                      MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+                      MakeInstruction(spv::Op::OpSwitch, {1, 3, 42, 3})}),
          "Invalid OpSwitch: selector id 1 is a type, not a value"},
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpTypeFloat, {1, 32}),
-                      MakeInstruction(SpvOpConstant, {1, 2, 0x78f00000}),
-                      MakeInstruction(SpvOpSwitch, {2, 3, 42, 3})}),
+                      MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+                      MakeInstruction(spv::Op::OpConstant, {1, 2, 0x78f00000}),
+                      MakeInstruction(spv::Op::OpSwitch, {2, 3, 42, 3})}),
          "Invalid OpSwitch: selector id 2 is not a scalar integer"},
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpExtInstImport, {1},
+                      MakeInstruction(spv::Op::OpExtInstImport, {1},
                                       MakeVector("invalid-import"))}),
          "Invalid extended instruction import 'invalid-import'"},
         {Concatenate({
              ExpectedHeaderForBound(3),
-             MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-             MakeInstruction(SpvOpConstant, {2, 2, 42}),
+             MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+             MakeInstruction(spv::Op::OpConstant, {2, 2, 42}),
          }),
          "Type Id 2 is not a type"},
         {Concatenate({
              ExpectedHeaderForBound(3),
-             MakeInstruction(SpvOpTypeBool, {1}),
-             MakeInstruction(SpvOpConstant, {1, 2, 42}),
+             MakeInstruction(spv::Op::OpTypeBool, {1}),
+             MakeInstruction(spv::Op::OpConstant, {1, 2, 42}),
          }),
          "Type Id 1 is not a scalar numeric type"},
     }));
diff --git a/third_party/SPIRV-Tools/test/binary_to_text_test.cpp b/third_party/SPIRV-Tools/test/binary_to_text_test.cpp
index 44705f2..85d5bd1 100644
--- a/third_party/SPIRV-Tools/test/binary_to_text_test.cpp
+++ b/third_party/SPIRV-Tools/test/binary_to_text_test.cpp
@@ -185,43 +185,43 @@
 INSTANTIATE_TEST_SUITE_P(
     InvalidIds, BinaryToTextFail,
     ::testing::ValuesIn(std::vector<FailedDecodeCase>{
-        {"", spvtest::MakeInstruction(SpvOpTypeVoid, {0}),
+        {"", spvtest::MakeInstruction(spv::Op::OpTypeVoid, {0}),
          "Error: Result Id is 0"},
-        {"", spvtest::MakeInstruction(SpvOpConstant, {0, 1, 42}),
+        {"", spvtest::MakeInstruction(spv::Op::OpConstant, {0, 1, 42}),
          "Error: Type Id is 0"},
-        {"%1 = OpTypeVoid", spvtest::MakeInstruction(SpvOpTypeVoid, {1}),
+        {"%1 = OpTypeVoid", spvtest::MakeInstruction(spv::Op::OpTypeVoid, {1}),
          "Id 1 is defined more than once"},
         {"%1 = OpTypeVoid\n"
          "%2 = OpNot %1 %foo",
-         spvtest::MakeInstruction(SpvOpNot, {1, 2, 3}),
+         spvtest::MakeInstruction(spv::Op::OpNot, {1, 2, 3}),
          "Id 2 is defined more than once"},
         {"%1 = OpTypeVoid\n"
          "%2 = OpNot %1 %foo",
-         spvtest::MakeInstruction(SpvOpNot, {1, 1, 3}),
+         spvtest::MakeInstruction(spv::Op::OpNot, {1, 1, 3}),
          "Id 1 is defined more than once"},
         // The following are the two failure cases for
         // Parser::setNumericTypeInfoForType.
-        {"", spvtest::MakeInstruction(SpvOpConstant, {500, 1, 42}),
+        {"", spvtest::MakeInstruction(spv::Op::OpConstant, {500, 1, 42}),
          "Type Id 500 is not a type"},
         {"%1 = OpTypeInt 32 0\n"
          "%2 = OpTypeVector %1 4",
-         spvtest::MakeInstruction(SpvOpConstant, {2, 3, 999}),
+         spvtest::MakeInstruction(spv::Op::OpConstant, {2, 3, 999}),
          "Type Id 2 is not a scalar numeric type"},
     }));
 
 INSTANTIATE_TEST_SUITE_P(
     InvalidIdsCheckedDuringLiteralCaseParsing, BinaryToTextFail,
     ::testing::ValuesIn(std::vector<FailedDecodeCase>{
-        {"", spvtest::MakeInstruction(SpvOpSwitch, {1, 2, 3, 4}),
+        {"", spvtest::MakeInstruction(spv::Op::OpSwitch, {1, 2, 3, 4}),
          "Invalid OpSwitch: selector id 1 has no type"},
         {"%1 = OpTypeVoid\n",
-         spvtest::MakeInstruction(SpvOpSwitch, {1, 2, 3, 4}),
+         spvtest::MakeInstruction(spv::Op::OpSwitch, {1, 2, 3, 4}),
          "Invalid OpSwitch: selector id 1 is a type, not a value"},
         {"%1 = OpConstantTrue !500",
-         spvtest::MakeInstruction(SpvOpSwitch, {1, 2, 3, 4}),
+         spvtest::MakeInstruction(spv::Op::OpSwitch, {1, 2, 3, 4}),
          "Type Id 500 is not a type"},
         {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 1.5",
-         spvtest::MakeInstruction(SpvOpSwitch, {2, 3, 4, 5}),
+         spvtest::MakeInstruction(spv::Op::OpSwitch, {2, 3, 4, 5}),
          "Invalid OpSwitch: selector id 2 is not a scalar integer"},
     }));
 
diff --git a/third_party/SPIRV-Tools/test/comment_test.cpp b/third_party/SPIRV-Tools/test/comment_test.cpp
index 49f8df6..5cc9b1d 100644
--- a/third_party/SPIRV-Tools/test/comment_test.cpp
+++ b/third_party/SPIRV-Tools/test/comment_test.cpp
@@ -40,10 +40,10 @@
 
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(Concatenate({MakeInstruction(SpvOpMemoryModel,
-                                      {uint32_t(SpvAddressingModelLogical),
-                                       uint32_t(SpvMemoryModelSimple)}),
-                      MakeInstruction(SpvOpExtInstImport, {1},
+      Eq(Concatenate({MakeInstruction(spv::Op::OpMemoryModel,
+                                      {uint32_t(spv::AddressingModel::Logical),
+                                       uint32_t(spv::MemoryModel::Simple)}),
+                      MakeInstruction(spv::Op::OpExtInstImport, {1},
                                       MakeVector("GLSL.std.450"))})));
 }
 
diff --git a/third_party/SPIRV-Tools/test/cpp_interface_test.cpp b/third_party/SPIRV-Tools/test/cpp_interface_test.cpp
index 538d40f..5d11698 100644
--- a/third_party/SPIRV-Tools/test/cpp_interface_test.cpp
+++ b/third_party/SPIRV-Tools/test/cpp_interface_test.cpp
@@ -19,7 +19,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "spirv-tools/optimizer.hpp"
-#include "spirv/1.1/spirv.h"
+#include "spirv/unified1/spirv.hpp11"
 
 namespace spvtools {
 namespace {
@@ -47,7 +47,7 @@
   std::vector<uint32_t> binary;
   EXPECT_TRUE(t.Assemble(input_text, &binary));
   EXPECT_TRUE(binary.size() > 5u);
-  EXPECT_EQ(SpvMagicNumber, binary[0]);
+  EXPECT_EQ(spv::MagicNumber, binary[0]);
   EXPECT_EQ(kExpectedSpvVersion, binary[1]);
 
   // This cannot pass validation since %1 is not defined.
@@ -58,7 +58,7 @@
     EXPECT_EQ(0u, position.line);
     EXPECT_EQ(0u, position.column);
     EXPECT_EQ(1u, position.index);
-    EXPECT_STREQ("ID 1[%1] has not been defined\n  %2 = OpSizeOf %1 %3\n",
+    EXPECT_STREQ("ID '1[%1]' has not been defined\n  %2 = OpSizeOf %1 %3\n",
                  message);
   });
   EXPECT_FALSE(t.Validate(binary));
@@ -74,7 +74,7 @@
   EXPECT_TRUE(t.Assemble("", &binary));
   // We only have the header.
   EXPECT_EQ(5u, binary.size());
-  EXPECT_EQ(SpvMagicNumber, binary[0]);
+  EXPECT_EQ(spv::MagicNumber, binary[0]);
   EXPECT_EQ(kExpectedSpvVersion, binary[1]);
 }
 
@@ -85,21 +85,21 @@
     std::vector<uint32_t> binary;
     EXPECT_TRUE(t.Assemble(input_text, &binary));
     EXPECT_TRUE(binary.size() > 5u);
-    EXPECT_EQ(SpvMagicNumber, binary[0]);
+    EXPECT_EQ(spv::MagicNumber, binary[0]);
     EXPECT_EQ(kExpectedSpvVersion, binary[1]);
   }
   {
     std::vector<uint32_t> binary;
     EXPECT_TRUE(t.Assemble(input_text.data(), input_text.size(), &binary));
     EXPECT_TRUE(binary.size() > 5u);
-    EXPECT_EQ(SpvMagicNumber, binary[0]);
+    EXPECT_EQ(spv::MagicNumber, binary[0]);
     EXPECT_EQ(kExpectedSpvVersion, binary[1]);
   }
   {  // Ignore the last newline.
     std::vector<uint32_t> binary;
     EXPECT_TRUE(t.Assemble(input_text.data(), input_text.size() - 1, &binary));
     EXPECT_TRUE(binary.size() > 5u);
-    EXPECT_EQ(SpvMagicNumber, binary[0]);
+    EXPECT_EQ(spv::MagicNumber, binary[0]);
     EXPECT_EQ(kExpectedSpvVersion, binary[1]);
   }
 }
diff --git a/third_party/SPIRV-Tools/test/diff/diff_files/diff_test_files_autogen.cmake b/third_party/SPIRV-Tools/test/diff/diff_files/diff_test_files_autogen.cmake
index e6d3645..6440d0b 100644
--- a/third_party/SPIRV-Tools/test/diff/diff_files/diff_test_files_autogen.cmake
+++ b/third_party/SPIRV-Tools/test/diff/diff_files/diff_test_files_autogen.cmake
@@ -41,5 +41,7 @@
 "diff_files/small_functions_small_diffs_autogen.cpp"
 "diff_files/spec_constant_array_size_autogen.cpp"
 "diff_files/spec_constant_composite_autogen.cpp"
+"diff_files/spec_constant_op_autogen.cpp"
+"diff_files/spec_constant_specid_autogen.cpp"
 "diff_files/unrelated_shaders_autogen.cpp"
 )
diff --git a/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_op_autogen.cpp b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_op_autogen.cpp
new file mode 100644
index 0000000..e88e15b
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_op_autogen.cpp
@@ -0,0 +1,162 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_tests.py
+//
+// Copyright (c) 2022 Google LLC.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "../diff_test_utils.h"
+
+#include "gtest/gtest.h"
+
+namespace spvtools {
+namespace diff {
+namespace {
+
+// Tests OpSpecConstantOp matching.
+constexpr char kSrc[] = R"(               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %1 "main"
+               OpExecutionMode %1 LocalSize 1 1 1
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpTypeInt 32 0
+          %5 = OpTypeVector %4 3
+          %6 = OpConstant %4 1
+          %7 = OpSpecConstantComposite %5 %6 %6 %6
+          %8 = OpSpecConstantOp %4 CompositeExtract %7 2
+          %9 = OpSpecConstantOp %4 CompositeExtract %7 1
+         %10 = OpSpecConstantOp %4 CompositeExtract %7 0
+          %1 = OpFunction %2 None %3
+         %11 = OpLabel
+               OpReturn
+               OpFunctionEnd)";
+constexpr char kDst[] = R"(               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %1 "main"
+               OpExecutionMode %1 LocalSize 1 1 1
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpTypeInt 32 0
+          %5 = OpTypeVector %4 3
+          %6 = OpConstant %4 1
+          %7 = OpSpecConstantComposite %5 %6 %6 %6
+          %8 = OpSpecConstantOp %4 CompositeExtract %7 2
+          %9 = OpSpecConstantOp %4 CompositeExtract %7 3
+         %10 = OpSpecConstantOp %4 IMul %8 %8
+          %1 = OpFunction %2 None %3
+         %11 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+TEST(DiffTest, SpecConstantOp) {
+  constexpr char kDiff[] = R"( ; SPIR-V
+ ; Version: 1.6
+ ; Generator: Khronos SPIR-V Tools Assembler; 0
+-; Bound: 12
++; Bound: 14
+ ; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %1 "main"
+ OpExecutionMode %1 LocalSize 1 1 1
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %4 = OpTypeInt 32 0
+ %5 = OpTypeVector %4 3
+ %6 = OpConstant %4 1
+ %7 = OpSpecConstantComposite %5 %6 %6 %6
+ %8 = OpSpecConstantOp %4 CompositeExtract %7 2
+-%9 = OpSpecConstantOp %4 CompositeExtract %7 1
+-%10 = OpSpecConstantOp %4 CompositeExtract %7 0
++%12 = OpSpecConstantOp %4 CompositeExtract %7 3
++%13 = OpSpecConstantOp %4 IMul %8 %8
+ %1 = OpFunction %2 None %3
+ %11 = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+  Options options;
+  DoStringDiffTest(kSrc, kDst, kDiff, options);
+}
+
+TEST(DiffTest, SpecConstantOpNoDebug) {
+  constexpr char kSrcNoDebug[] = R"(               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %1 "main"
+               OpExecutionMode %1 LocalSize 1 1 1
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpTypeInt 32 0
+          %5 = OpTypeVector %4 3
+          %6 = OpConstant %4 1
+          %7 = OpSpecConstantComposite %5 %6 %6 %6
+          %8 = OpSpecConstantOp %4 CompositeExtract %7 2
+          %9 = OpSpecConstantOp %4 CompositeExtract %7 1
+         %10 = OpSpecConstantOp %4 CompositeExtract %7 0
+          %1 = OpFunction %2 None %3
+         %11 = OpLabel
+               OpReturn
+               OpFunctionEnd)";
+  constexpr char kDstNoDebug[] = R"(               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %1 "main"
+               OpExecutionMode %1 LocalSize 1 1 1
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpTypeInt 32 0
+          %5 = OpTypeVector %4 3
+          %6 = OpConstant %4 1
+          %7 = OpSpecConstantComposite %5 %6 %6 %6
+          %8 = OpSpecConstantOp %4 CompositeExtract %7 2
+          %9 = OpSpecConstantOp %4 CompositeExtract %7 3
+         %10 = OpSpecConstantOp %4 IMul %8 %8
+          %1 = OpFunction %2 None %3
+         %11 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+  constexpr char kDiff[] = R"( ; SPIR-V
+ ; Version: 1.6
+ ; Generator: Khronos SPIR-V Tools Assembler; 0
+-; Bound: 12
++; Bound: 14
+ ; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %1 "main"
+ OpExecutionMode %1 LocalSize 1 1 1
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %4 = OpTypeInt 32 0
+ %5 = OpTypeVector %4 3
+ %6 = OpConstant %4 1
+ %7 = OpSpecConstantComposite %5 %6 %6 %6
+ %8 = OpSpecConstantOp %4 CompositeExtract %7 2
+-%9 = OpSpecConstantOp %4 CompositeExtract %7 1
+-%10 = OpSpecConstantOp %4 CompositeExtract %7 0
++%12 = OpSpecConstantOp %4 CompositeExtract %7 3
++%13 = OpSpecConstantOp %4 IMul %8 %8
+ %1 = OpFunction %2 None %3
+ %11 = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+  Options options;
+  DoStringDiffTest(kSrcNoDebug, kDstNoDebug, kDiff, options);
+}
+
+}  // namespace
+}  // namespace diff
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_op_dst.spvasm b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_op_dst.spvasm
new file mode 100644
index 0000000..b5b10e5
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_op_dst.spvasm
@@ -0,0 +1,17 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %1 "main"
+               OpExecutionMode %1 LocalSize 1 1 1
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpTypeInt 32 0
+          %5 = OpTypeVector %4 3
+          %6 = OpConstant %4 1
+          %7 = OpSpecConstantComposite %5 %6 %6 %6
+          %8 = OpSpecConstantOp %4 CompositeExtract %7 2
+          %9 = OpSpecConstantOp %4 CompositeExtract %7 3
+         %10 = OpSpecConstantOp %4 IMul %8 %8
+          %1 = OpFunction %2 None %3
+         %11 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_op_src.spvasm b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_op_src.spvasm
new file mode 100644
index 0000000..09306f8
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_op_src.spvasm
@@ -0,0 +1,18 @@
+;; Tests OpSpecConstantOp matching.
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %1 "main"
+               OpExecutionMode %1 LocalSize 1 1 1
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpTypeInt 32 0
+          %5 = OpTypeVector %4 3
+          %6 = OpConstant %4 1
+          %7 = OpSpecConstantComposite %5 %6 %6 %6
+          %8 = OpSpecConstantOp %4 CompositeExtract %7 2
+          %9 = OpSpecConstantOp %4 CompositeExtract %7 1
+         %10 = OpSpecConstantOp %4 CompositeExtract %7 0
+          %1 = OpFunction %2 None %3
+         %11 = OpLabel
+               OpReturn
+               OpFunctionEnd
\ No newline at end of file
diff --git a/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_specid_autogen.cpp b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_specid_autogen.cpp
new file mode 100644
index 0000000..240dc59
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_specid_autogen.cpp
@@ -0,0 +1,141 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_tests.py
+//
+// Copyright (c) 2022 Google LLC.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "../diff_test_utils.h"
+
+#include "gtest/gtest.h"
+
+namespace spvtools {
+namespace diff {
+namespace {
+
+// Tests OpSpecConstantComposite matching.
+constexpr char kSrc[] = R"(               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpDecorate %sc SpecId 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+         %sc = OpSpecConstant %uint 10
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd)";
+constexpr char kDst[] = R"(               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+         %ss = OpSpecConstant %uint 10
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+TEST(DiffTest, SpecConstantSpecid) {
+  constexpr char kDiff[] = R"( ; SPIR-V
+ ; Version: 1.6
+ ; Generator: Khronos SPIR-V Tools Assembler; 0
+-; Bound: 8
++; Bound: 9
+ ; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %1 "main"
+ OpExecutionMode %1 LocalSize 1 1 1
+-OpDecorate %2 SpecId 0
+ %4 = OpTypeVoid
+ %3 = OpTypeFunction %4
+ %6 = OpTypeInt 32 0
+ %7 = OpTypeVector %6 3
+-%2 = OpSpecConstant %6 10
++%8 = OpSpecConstant %6 10
+ %1 = OpFunction %4 None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+  Options options;
+  DoStringDiffTest(kSrc, kDst, kDiff, options);
+}
+
+TEST(DiffTest, SpecConstantSpecidNoDebug) {
+  constexpr char kSrcNoDebug[] = R"(               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpDecorate %sc SpecId 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+         %sc = OpSpecConstant %uint 10
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+  constexpr char kDstNoDebug[] = R"(               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+         %ss = OpSpecConstant %uint 10
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+  constexpr char kDiff[] = R"( ; SPIR-V
+ ; Version: 1.6
+ ; Generator: Khronos SPIR-V Tools Assembler; 0
+-; Bound: 8
++; Bound: 9
+ ; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %1 "main"
+ OpExecutionMode %1 LocalSize 1 1 1
+-OpDecorate %2 SpecId 0
+ %4 = OpTypeVoid
+ %3 = OpTypeFunction %4
+ %6 = OpTypeInt 32 0
+ %7 = OpTypeVector %6 3
+-%2 = OpSpecConstant %6 10
++%8 = OpSpecConstant %6 10
+ %1 = OpFunction %4 None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+  Options options;
+  DoStringDiffTest(kSrcNoDebug, kDstNoDebug, kDiff, options);
+}
+
+}  // namespace
+}  // namespace diff
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_specid_dst.spvasm b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_specid_dst.spvasm
new file mode 100644
index 0000000..0e840ed
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_specid_dst.spvasm
@@ -0,0 +1,13 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+         %ss = OpSpecConstant %uint 10
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_specid_src.spvasm b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_specid_src.spvasm
new file mode 100644
index 0000000..7fdfeba
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/diff/diff_files/spec_constant_specid_src.spvasm
@@ -0,0 +1,15 @@
+;; Tests OpSpecConstantComposite matching.
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpDecorate %sc SpecId 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+         %sc = OpSpecConstant %uint 10
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/third_party/SPIRV-Tools/test/diff/diff_test.cpp b/third_party/SPIRV-Tools/test/diff/diff_test.cpp
index 5b11d0e..3b63c69 100644
--- a/third_party/SPIRV-Tools/test/diff/diff_test.cpp
+++ b/third_party/SPIRV-Tools/test/diff/diff_test.cpp
@@ -195,14 +195,14 @@
 
   // Differentiate them in the header.
   const spvtools::opt::ModuleHeader src_header = {
-      SpvMagicNumber,
+      spv::MagicNumber,
       SPV_SPIRV_VERSION_WORD(1, 3),
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 3),
       src->module()->IdBound(),
       src->module()->schema(),
   };
   const spvtools::opt::ModuleHeader dst_header = {
-      SpvMagicNumber,
+      spv::MagicNumber,
       SPV_SPIRV_VERSION_WORD(1, 2),
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_GLSLANG, 10),
       dst->module()->IdBound(),
diff --git a/third_party/SPIRV-Tools/test/enum_set_test.cpp b/third_party/SPIRV-Tools/test/enum_set_test.cpp
index 047d642..1f72715 100644
--- a/third_party/SPIRV-Tools/test/enum_set_test.cpp
+++ b/third_party/SPIRV-Tools/test/enum_set_test.cpp
@@ -179,60 +179,60 @@
 }
 
 TEST(CapabilitySet, ConstructSingleMemberMatrix) {
-  CapabilitySet s(SpvCapabilityMatrix);
-  EXPECT_TRUE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_FALSE(s.Contains(SpvCapabilityShader));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
+  CapabilitySet s(spv::Capability::Matrix);
+  EXPECT_TRUE(s.Contains(spv::Capability::Matrix));
+  EXPECT_FALSE(s.Contains(spv::Capability::Shader));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
 }
 
 TEST(CapabilitySet, ConstructSingleMemberMaxInMask) {
-  CapabilitySet s(static_cast<SpvCapability>(63));
-  EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_FALSE(s.Contains(SpvCapabilityShader));
-  EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(63)));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(64)));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
+  CapabilitySet s(static_cast<spv::Capability>(63));
+  EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
+  EXPECT_FALSE(s.Contains(spv::Capability::Shader));
+  EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(63)));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(64)));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
 }
 
 TEST(CapabilitySet, ConstructSingleMemberMinOverflow) {
   // Check the first one that forces overflow beyond the mask.
-  CapabilitySet s(static_cast<SpvCapability>(64));
-  EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_FALSE(s.Contains(SpvCapabilityShader));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(63)));
-  EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(64)));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
+  CapabilitySet s(static_cast<spv::Capability>(64));
+  EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
+  EXPECT_FALSE(s.Contains(spv::Capability::Shader));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(63)));
+  EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(64)));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
 }
 
 TEST(CapabilitySet, ConstructSingleMemberMaxOverflow) {
   // Check the max 32-bit signed int.
-  CapabilitySet s(static_cast<SpvCapability>(0x7fffffffu));
-  EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_FALSE(s.Contains(SpvCapabilityShader));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
-  EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(0x7fffffffu)));
+  CapabilitySet s(static_cast<spv::Capability>(0x7fffffffu));
+  EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
+  EXPECT_FALSE(s.Contains(spv::Capability::Shader));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
+  EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(0x7fffffffu)));
 }
 
 TEST(CapabilitySet, AddEnum) {
-  CapabilitySet s(SpvCapabilityShader);
-  s.Add(SpvCapabilityKernel);
-  s.Add(static_cast<SpvCapability>(42));
-  EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_TRUE(s.Contains(SpvCapabilityShader));
-  EXPECT_TRUE(s.Contains(SpvCapabilityKernel));
-  EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(42)));
+  CapabilitySet s(spv::Capability::Shader);
+  s.Add(spv::Capability::Kernel);
+  s.Add(static_cast<spv::Capability>(42));
+  EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
+  EXPECT_TRUE(s.Contains(spv::Capability::Shader));
+  EXPECT_TRUE(s.Contains(spv::Capability::Kernel));
+  EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(42)));
 }
 
 TEST(CapabilitySet, InitializerListEmpty) {
   CapabilitySet s{};
   for (uint32_t i = 0; i < 1000; i++) {
-    EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(i)));
+    EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(i)));
   }
 }
 
 struct ForEachCase {
   CapabilitySet capabilities;
-  std::vector<SpvCapability> expected;
+  std::vector<spv::Capability> expected;
 };
 
 using CapabilitySetForEachTest = ::testing::TestWithParam<ForEachCase>;
@@ -253,7 +253,7 @@
   EXPECT_THAT(ElementsIn(moved), Eq(GetParam().expected));
 
   // The moved-from set is empty.
-  EXPECT_THAT(ElementsIn(copy), Eq(std::vector<SpvCapability>{}));
+  EXPECT_THAT(ElementsIn(copy), Eq(std::vector<spv::Capability>{}));
 }
 
 TEST_P(CapabilitySetForEachTest, OperatorEquals) {
@@ -267,24 +267,25 @@
   EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected));
 }
 
-INSTANTIATE_TEST_SUITE_P(Samples, CapabilitySetForEachTest,
-                         ValuesIn(std::vector<ForEachCase>{
-                             {{}, {}},
-                             {{SpvCapabilityMatrix}, {SpvCapabilityMatrix}},
-                             {{SpvCapabilityKernel, SpvCapabilityShader},
-                              {SpvCapabilityShader, SpvCapabilityKernel}},
-                             {{static_cast<SpvCapability>(999)},
-                              {static_cast<SpvCapability>(999)}},
-                             {{static_cast<SpvCapability>(0x7fffffff)},
-                              {static_cast<SpvCapability>(0x7fffffff)}},
-                             // Mixture and out of order
-                             {{static_cast<SpvCapability>(0x7fffffff),
-                               static_cast<SpvCapability>(100),
-                               SpvCapabilityShader, SpvCapabilityMatrix},
-                              {SpvCapabilityMatrix, SpvCapabilityShader,
-                               static_cast<SpvCapability>(100),
-                               static_cast<SpvCapability>(0x7fffffff)}},
-                         }));
+INSTANTIATE_TEST_SUITE_P(
+    Samples, CapabilitySetForEachTest,
+    ValuesIn(std::vector<ForEachCase>{
+        {{}, {}},
+        {{spv::Capability::Matrix}, {spv::Capability::Matrix}},
+        {{spv::Capability::Kernel, spv::Capability::Shader},
+         {spv::Capability::Shader, spv::Capability::Kernel}},
+        {{static_cast<spv::Capability>(999)},
+         {static_cast<spv::Capability>(999)}},
+        {{static_cast<spv::Capability>(0x7fffffff)},
+         {static_cast<spv::Capability>(0x7fffffff)}},
+        // Mixture and out of order
+        {{static_cast<spv::Capability>(0x7fffffff),
+          static_cast<spv::Capability>(100), spv::Capability::Shader,
+          spv::Capability::Matrix},
+         {spv::Capability::Matrix, spv::Capability::Shader,
+          static_cast<spv::Capability>(100),
+          static_cast<spv::Capability>(0x7fffffff)}},
+    }));
 
 }  // namespace
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/enum_string_mapping_test.cpp b/third_party/SPIRV-Tools/test/enum_string_mapping_test.cpp
index 52aa653..01dede7 100644
--- a/third_party/SPIRV-Tools/test/enum_string_mapping_test.cpp
+++ b/third_party/SPIRV-Tools/test/enum_string_mapping_test.cpp
@@ -34,7 +34,7 @@
     ::testing::TestWithParam<std::pair<Extension, std::string>>;
 using UnknownExtensionTest = ::testing::TestWithParam<std::string>;
 using CapabilityTest =
-    ::testing::TestWithParam<std::pair<SpvCapability, std::string>>;
+    ::testing::TestWithParam<std::pair<spv::Capability, std::string>>;
 
 TEST_P(ExtensionTest, TestExtensionFromString) {
   const std::pair<Extension, std::string>& param = GetParam();
@@ -59,8 +59,8 @@
 }
 
 TEST_P(CapabilityTest, TestCapabilityToString) {
-  const std::pair<SpvCapability, std::string>& param = GetParam();
-  const SpvCapability capability = param.first;
+  const std::pair<spv::Capability, std::string>& param = GetParam();
+  const spv::Capability capability = param.first;
   const std::string capability_str = param.second;
   const std::string result_str = CapabilityToString(capability);
   EXPECT_EQ(capability_str, result_str);
@@ -99,104 +99,105 @@
 
 INSTANTIATE_TEST_SUITE_P(
     AllCapabilities, CapabilityTest,
-    ValuesIn(std::vector<std::pair<SpvCapability, std::string>>(
-        {{SpvCapabilityMatrix, "Matrix"},
-         {SpvCapabilityShader, "Shader"},
-         {SpvCapabilityGeometry, "Geometry"},
-         {SpvCapabilityTessellation, "Tessellation"},
-         {SpvCapabilityAddresses, "Addresses"},
-         {SpvCapabilityLinkage, "Linkage"},
-         {SpvCapabilityKernel, "Kernel"},
-         {SpvCapabilityVector16, "Vector16"},
-         {SpvCapabilityFloat16Buffer, "Float16Buffer"},
-         {SpvCapabilityFloat16, "Float16"},
-         {SpvCapabilityFloat64, "Float64"},
-         {SpvCapabilityInt64, "Int64"},
-         {SpvCapabilityInt64Atomics, "Int64Atomics"},
-         {SpvCapabilityImageBasic, "ImageBasic"},
-         {SpvCapabilityImageReadWrite, "ImageReadWrite"},
-         {SpvCapabilityImageMipmap, "ImageMipmap"},
-         {SpvCapabilityPipes, "Pipes"},
-         {SpvCapabilityGroups, "Groups"},
-         {SpvCapabilityDeviceEnqueue, "DeviceEnqueue"},
-         {SpvCapabilityLiteralSampler, "LiteralSampler"},
-         {SpvCapabilityAtomicStorage, "AtomicStorage"},
-         {SpvCapabilityInt16, "Int16"},
-         {SpvCapabilityTessellationPointSize, "TessellationPointSize"},
-         {SpvCapabilityGeometryPointSize, "GeometryPointSize"},
-         {SpvCapabilityImageGatherExtended, "ImageGatherExtended"},
-         {SpvCapabilityStorageImageMultisample, "StorageImageMultisample"},
-         {SpvCapabilityUniformBufferArrayDynamicIndexing,
+    ValuesIn(std::vector<std::pair<spv::Capability, std::string>>(
+        {{spv::Capability::Matrix, "Matrix"},
+         {spv::Capability::Shader, "Shader"},
+         {spv::Capability::Geometry, "Geometry"},
+         {spv::Capability::Tessellation, "Tessellation"},
+         {spv::Capability::Addresses, "Addresses"},
+         {spv::Capability::Linkage, "Linkage"},
+         {spv::Capability::Kernel, "Kernel"},
+         {spv::Capability::Vector16, "Vector16"},
+         {spv::Capability::Float16Buffer, "Float16Buffer"},
+         {spv::Capability::Float16, "Float16"},
+         {spv::Capability::Float64, "Float64"},
+         {spv::Capability::Int64, "Int64"},
+         {spv::Capability::Int64Atomics, "Int64Atomics"},
+         {spv::Capability::ImageBasic, "ImageBasic"},
+         {spv::Capability::ImageReadWrite, "ImageReadWrite"},
+         {spv::Capability::ImageMipmap, "ImageMipmap"},
+         {spv::Capability::Pipes, "Pipes"},
+         {spv::Capability::Groups, "Groups"},
+         {spv::Capability::DeviceEnqueue, "DeviceEnqueue"},
+         {spv::Capability::LiteralSampler, "LiteralSampler"},
+         {spv::Capability::AtomicStorage, "AtomicStorage"},
+         {spv::Capability::Int16, "Int16"},
+         {spv::Capability::TessellationPointSize, "TessellationPointSize"},
+         {spv::Capability::GeometryPointSize, "GeometryPointSize"},
+         {spv::Capability::ImageGatherExtended, "ImageGatherExtended"},
+         {spv::Capability::StorageImageMultisample, "StorageImageMultisample"},
+         {spv::Capability::UniformBufferArrayDynamicIndexing,
           "UniformBufferArrayDynamicIndexing"},
-         {SpvCapabilitySampledImageArrayDynamicIndexing,
+         {spv::Capability::SampledImageArrayDynamicIndexing,
           "SampledImageArrayDynamicIndexing"},
-         {SpvCapabilityStorageBufferArrayDynamicIndexing,
+         {spv::Capability::StorageBufferArrayDynamicIndexing,
           "StorageBufferArrayDynamicIndexing"},
-         {SpvCapabilityStorageImageArrayDynamicIndexing,
+         {spv::Capability::StorageImageArrayDynamicIndexing,
           "StorageImageArrayDynamicIndexing"},
-         {SpvCapabilityClipDistance, "ClipDistance"},
-         {SpvCapabilityCullDistance, "CullDistance"},
-         {SpvCapabilityImageCubeArray, "ImageCubeArray"},
-         {SpvCapabilitySampleRateShading, "SampleRateShading"},
-         {SpvCapabilityImageRect, "ImageRect"},
-         {SpvCapabilitySampledRect, "SampledRect"},
-         {SpvCapabilityGenericPointer, "GenericPointer"},
-         {SpvCapabilityInt8, "Int8"},
-         {SpvCapabilityInputAttachment, "InputAttachment"},
-         {SpvCapabilitySparseResidency, "SparseResidency"},
-         {SpvCapabilityMinLod, "MinLod"},
-         {SpvCapabilitySampled1D, "Sampled1D"},
-         {SpvCapabilityImage1D, "Image1D"},
-         {SpvCapabilitySampledCubeArray, "SampledCubeArray"},
-         {SpvCapabilitySampledBuffer, "SampledBuffer"},
-         {SpvCapabilityImageBuffer, "ImageBuffer"},
-         {SpvCapabilityImageMSArray, "ImageMSArray"},
-         {SpvCapabilityStorageImageExtendedFormats,
+         {spv::Capability::ClipDistance, "ClipDistance"},
+         {spv::Capability::CullDistance, "CullDistance"},
+         {spv::Capability::ImageCubeArray, "ImageCubeArray"},
+         {spv::Capability::SampleRateShading, "SampleRateShading"},
+         {spv::Capability::ImageRect, "ImageRect"},
+         {spv::Capability::SampledRect, "SampledRect"},
+         {spv::Capability::GenericPointer, "GenericPointer"},
+         {spv::Capability::Int8, "Int8"},
+         {spv::Capability::InputAttachment, "InputAttachment"},
+         {spv::Capability::SparseResidency, "SparseResidency"},
+         {spv::Capability::MinLod, "MinLod"},
+         {spv::Capability::Sampled1D, "Sampled1D"},
+         {spv::Capability::Image1D, "Image1D"},
+         {spv::Capability::SampledCubeArray, "SampledCubeArray"},
+         {spv::Capability::SampledBuffer, "SampledBuffer"},
+         {spv::Capability::ImageBuffer, "ImageBuffer"},
+         {spv::Capability::ImageMSArray, "ImageMSArray"},
+         {spv::Capability::StorageImageExtendedFormats,
           "StorageImageExtendedFormats"},
-         {SpvCapabilityImageQuery, "ImageQuery"},
-         {SpvCapabilityDerivativeControl, "DerivativeControl"},
-         {SpvCapabilityInterpolationFunction, "InterpolationFunction"},
-         {SpvCapabilityTransformFeedback, "TransformFeedback"},
-         {SpvCapabilityGeometryStreams, "GeometryStreams"},
-         {SpvCapabilityStorageImageReadWithoutFormat,
+         {spv::Capability::ImageQuery, "ImageQuery"},
+         {spv::Capability::DerivativeControl, "DerivativeControl"},
+         {spv::Capability::InterpolationFunction, "InterpolationFunction"},
+         {spv::Capability::TransformFeedback, "TransformFeedback"},
+         {spv::Capability::GeometryStreams, "GeometryStreams"},
+         {spv::Capability::StorageImageReadWithoutFormat,
           "StorageImageReadWithoutFormat"},
-         {SpvCapabilityStorageImageWriteWithoutFormat,
+         {spv::Capability::StorageImageWriteWithoutFormat,
           "StorageImageWriteWithoutFormat"},
-         {SpvCapabilityMultiViewport, "MultiViewport"},
-         {SpvCapabilitySubgroupDispatch, "SubgroupDispatch"},
-         {SpvCapabilityNamedBarrier, "NamedBarrier"},
-         {SpvCapabilityPipeStorage, "PipeStorage"},
-         {SpvCapabilitySubgroupBallotKHR, "SubgroupBallotKHR"},
-         {SpvCapabilityDrawParameters, "DrawParameters"},
-         {SpvCapabilitySubgroupVoteKHR, "SubgroupVoteKHR"},
-         {SpvCapabilityStorageBuffer16BitAccess, "StorageBuffer16BitAccess"},
-         {SpvCapabilityStorageUniformBufferBlock16,
+         {spv::Capability::MultiViewport, "MultiViewport"},
+         {spv::Capability::SubgroupDispatch, "SubgroupDispatch"},
+         {spv::Capability::NamedBarrier, "NamedBarrier"},
+         {spv::Capability::PipeStorage, "PipeStorage"},
+         {spv::Capability::SubgroupBallotKHR, "SubgroupBallotKHR"},
+         {spv::Capability::DrawParameters, "DrawParameters"},
+         {spv::Capability::SubgroupVoteKHR, "SubgroupVoteKHR"},
+         {spv::Capability::StorageBuffer16BitAccess,
+          "StorageBuffer16BitAccess"},
+         {spv::Capability::StorageUniformBufferBlock16,
           "StorageBuffer16BitAccess"},  // Preferred name
-         {SpvCapabilityUniformAndStorageBuffer16BitAccess,
+         {spv::Capability::UniformAndStorageBuffer16BitAccess,
           "UniformAndStorageBuffer16BitAccess"},
-         {SpvCapabilityStorageUniform16,
+         {spv::Capability::StorageUniform16,
           "UniformAndStorageBuffer16BitAccess"},  // Preferred name
-         {SpvCapabilityStoragePushConstant16, "StoragePushConstant16"},
-         {SpvCapabilityStorageInputOutput16, "StorageInputOutput16"},
-         {SpvCapabilityDeviceGroup, "DeviceGroup"},
-         {SpvCapabilityAtomicFloat32AddEXT, "AtomicFloat32AddEXT"},
-         {SpvCapabilityAtomicFloat64AddEXT, "AtomicFloat64AddEXT"},
-         {SpvCapabilityAtomicFloat32MinMaxEXT, "AtomicFloat32MinMaxEXT"},
-         {SpvCapabilityAtomicFloat64MinMaxEXT, "AtomicFloat64MinMaxEXT"},
-         {SpvCapabilityMultiView, "MultiView"},
-         {SpvCapabilityInt64ImageEXT, "Int64ImageEXT"},
-         {SpvCapabilitySampleMaskOverrideCoverageNV,
+         {spv::Capability::StoragePushConstant16, "StoragePushConstant16"},
+         {spv::Capability::StorageInputOutput16, "StorageInputOutput16"},
+         {spv::Capability::DeviceGroup, "DeviceGroup"},
+         {spv::Capability::AtomicFloat32AddEXT, "AtomicFloat32AddEXT"},
+         {spv::Capability::AtomicFloat64AddEXT, "AtomicFloat64AddEXT"},
+         {spv::Capability::AtomicFloat32MinMaxEXT, "AtomicFloat32MinMaxEXT"},
+         {spv::Capability::AtomicFloat64MinMaxEXT, "AtomicFloat64MinMaxEXT"},
+         {spv::Capability::MultiView, "MultiView"},
+         {spv::Capability::Int64ImageEXT, "Int64ImageEXT"},
+         {spv::Capability::SampleMaskOverrideCoverageNV,
           "SampleMaskOverrideCoverageNV"},
-         {SpvCapabilityGeometryShaderPassthroughNV,
+         {spv::Capability::GeometryShaderPassthroughNV,
           "GeometryShaderPassthroughNV"},
          // The next two are different names for the same token.
-         {SpvCapabilityShaderViewportIndexLayerNV,
+         {spv::Capability::ShaderViewportIndexLayerNV,
           "ShaderViewportIndexLayerEXT"},
-         {SpvCapabilityShaderViewportIndexLayerEXT,
+         {spv::Capability::ShaderViewportIndexLayerEXT,
           "ShaderViewportIndexLayerEXT"},
-         {SpvCapabilityShaderViewportMaskNV, "ShaderViewportMaskNV"},
-         {SpvCapabilityShaderStereoViewNV, "ShaderStereoViewNV"},
-         {SpvCapabilityPerViewAttributesNV, "PerViewAttributesNV"}})));
+         {spv::Capability::ShaderViewportMaskNV, "ShaderViewportMaskNV"},
+         {spv::Capability::ShaderStereoViewNV, "ShaderStereoViewNV"},
+         {spv::Capability::PerViewAttributesNV, "PerViewAttributesNV"}})));
 
 }  // namespace
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/ext_inst.cldebug100_test.cpp b/third_party/SPIRV-Tools/test/ext_inst.cldebug100_test.cpp
index 0bbdd3a..cfc68e8 100644
--- a/third_party/SPIRV-Tools/test/ext_inst.cldebug100_test.cpp
+++ b/third_party/SPIRV-Tools/test/ext_inst.cldebug100_test.cpp
@@ -18,7 +18,6 @@
 #include "OpenCLDebugInfo100.h"
 #include "gmock/gmock.h"
 #include "source/util/string_utils.h"
-#include "spirv/unified1/spirv.h"
 #include "test/test_fixture.h"
 #include "test/unit_spirv.h"
 
@@ -158,12 +157,13 @@
       GetParam().name + GetParam().operands + "\n";
   // First make sure it assembles correctly.
   std::cout << input << std::endl;
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(Concatenate(
-                  {MakeInstruction(SpvOpExtInstImport, {1},
-                                   MakeVector("OpenCL.DebugInfo.100")),
-                   MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode},
-                                   GetParam().expected_operands)})))
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(Concatenate(
+          {MakeInstruction(spv::Op::OpExtInstImport, {1},
+                           MakeVector("OpenCL.DebugInfo.100")),
+           MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, GetParam().opcode},
+                           GetParam().expected_operands)})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
@@ -297,7 +297,7 @@
   {                                                         \
     uint32_t(OpenCLDebugInfo100Debug##Enum), EPREFIX #Enum, \
         " %4 " #S0 " " Fstr, {                              \
-      4, uint32_t(SpvStorageClass##S0), Fnum                \
+      4, uint32_t(spv::StorageClass::S0), Fnum              \
     }                                                       \
   }
 
@@ -313,7 +313,7 @@
   {                                                         \
     uint32_t(OpenCLDebugInfo100Debug##Enum), EPREFIX #Enum, \
         " " #L0 " " #L1 " %4 " RawEnumName, {               \
-      L0, L1, 4, RawEnumValue                               \
+      L0, L1, 4, (uint32_t)RawEnumValue                     \
     }                                                       \
   }
 
@@ -574,7 +574,7 @@
 INSTANTIATE_TEST_SUITE_P(
     OpenCLDebugInfo100DebugCompilationUnit, ExtInstCLDebugInfo100RoundTripTest,
     ::testing::ValuesIn(std::vector<InstructionCase>({
-        CASE_LLIe(CompilationUnit, 100, 42, "HLSL", SpvSourceLanguageHLSL),
+        CASE_LLIe(CompilationUnit, 100, 42, "HLSL", spv::SourceLanguage::HLSL),
     })));
 
 INSTANTIATE_TEST_SUITE_P(
@@ -612,14 +612,14 @@
   const std::string input = prefix + "FlagIsPublic\n";
   const std::string expected = prefix + "FlagIsProtected|FlagIsPrivate\n";
   // First make sure it assembles correctly.
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(Concatenate(
-          {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")),
-           MakeInstruction(SpvOpExtInst,
-                           {2, 3, 1, OpenCLDebugInfo100DebugTypePointer, 4,
-                            uint32_t(SpvStorageClassPrivate),
-                            OpenCLDebugInfo100FlagIsPublic})})))
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(Concatenate(
+                  {MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                   MakeVector("DebugInfo")),
+                   MakeInstruction(spv::Op::OpExtInst,
+                                   {2, 3, 1, OpenCLDebugInfo100DebugTypePointer,
+                                    4, uint32_t(spv::StorageClass::Private),
+                                    OpenCLDebugInfo100FlagIsPublic})})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(expected)) << input;
diff --git a/third_party/SPIRV-Tools/test/ext_inst.debuginfo_test.cpp b/third_party/SPIRV-Tools/test/ext_inst.debuginfo_test.cpp
index 9090c24..5ccbde6 100644
--- a/third_party/SPIRV-Tools/test/ext_inst.debuginfo_test.cpp
+++ b/third_party/SPIRV-Tools/test/ext_inst.debuginfo_test.cpp
@@ -52,12 +52,12 @@
       "%3 = OpExtInst %2 %1 " +
       GetParam().name + GetParam().operands + "\n";
   // First make sure it assembles correctly.
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(Concatenate(
-          {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")),
-           MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode},
-                           GetParam().expected_operands)})))
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                              MakeVector("DebugInfo")),
+                              MakeInstruction(spv::Op::OpExtInst,
+                                              {2, 3, 1, GetParam().opcode},
+                                              GetParam().expected_operands)})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
@@ -156,7 +156,7 @@
 #define CASE_ISF(Enum, S0, Fstr, Fnum)                                    \
   {                                                                       \
     uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #S0 " " Fstr, { \
-      4, uint32_t(SpvStorageClass##S0), Fnum                              \
+      4, uint32_t(spv::StorageClass::S0), Fnum                            \
     }                                                                     \
   }
 
@@ -408,11 +408,12 @@
   // First make sure it assembles correctly.
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(Concatenate(
-          {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")),
-           MakeInstruction(SpvOpExtInst, {2, 3, 1, DebugInfoDebugTypePointer, 4,
-                                          uint32_t(SpvStorageClassPrivate),
-                                          DebugInfoFlagIsPublic})})))
+      Eq(Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                      MakeVector("DebugInfo")),
+                      MakeInstruction(spv::Op::OpExtInst,
+                                      {2, 3, 1, DebugInfoDebugTypePointer, 4,
+                                       uint32_t(spv::StorageClass::Private),
+                                       DebugInfoFlagIsPublic})})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(expected)) << input;
diff --git a/third_party/SPIRV-Tools/test/ext_inst.opencl_test.cpp b/third_party/SPIRV-Tools/test/ext_inst.opencl_test.cpp
index d80a9bd..51c2b01 100644
--- a/third_party/SPIRV-Tools/test/ext_inst.opencl_test.cpp
+++ b/third_party/SPIRV-Tools/test/ext_inst.opencl_test.cpp
@@ -47,12 +47,12 @@
       "%3 = OpExtInst %2 %1 " +
       GetParam().name + " " + GetParam().operands + "\n";
   // First make sure it assembles correctly.
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(Concatenate(
-          {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("OpenCL.std")),
-           MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode},
-                           GetParam().expected_operands)})))
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                              MakeVector("OpenCL.std")),
+                              MakeInstruction(spv::Op::OpExtInst,
+                                              {2, 3, 1, GetParam().opcode},
+                                              GetParam().expected_operands)})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
@@ -85,7 +85,7 @@
 #define CASE3Round(Enum, Name, Mode)                                    \
   {                                                                     \
     uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 " #Mode, { \
-      4, 5, 6, uint32_t(SpvFPRoundingMode##Mode)                        \
+      4, 5, 6, uint32_t(spv::FPRoundingMode::Mode)                      \
     }                                                                   \
   }
 
diff --git a/third_party/SPIRV-Tools/test/fuzz/available_instructions_test.cpp b/third_party/SPIRV-Tools/test/fuzz/available_instructions_test.cpp
index dc8a3b5..bbe524a 100644
--- a/third_party/SPIRV-Tools/test/fuzz/available_instructions_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/available_instructions_test.cpp
@@ -176,41 +176,41 @@
       auto available = all_instructions.GetAvailableBeforeInstruction(i1);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(30, available.size());
-      ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
-      ASSERT_EQ(SpvOpVariable, available[15]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpVariable, available[15]->opcode());
     }
     {
       auto available = all_instructions.GetAvailableBeforeInstruction(i2);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(46, available.size());
-      ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
-      ASSERT_EQ(SpvOpTypePointer, available[3]->opcode());
-      ASSERT_EQ(SpvOpVariable, available[15]->opcode());
-      ASSERT_EQ(SpvOpFunctionCall, available[40]->opcode());
-      ASSERT_EQ(SpvOpStore, available[45]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpTypePointer, available[3]->opcode());
+      ASSERT_EQ(spv::Op::OpVariable, available[15]->opcode());
+      ASSERT_EQ(spv::Op::OpFunctionCall, available[40]->opcode());
+      ASSERT_EQ(spv::Op::OpStore, available[45]->opcode());
     }
     {
       auto available = all_instructions.GetAvailableBeforeInstruction(i3);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(45, available.size());
-      ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
-      ASSERT_EQ(SpvOpTypePointer, available[3]->opcode());
-      ASSERT_EQ(SpvOpVariable, available[15]->opcode());
-      ASSERT_EQ(SpvOpFunctionCall, available[40]->opcode());
-      ASSERT_EQ(SpvOpBranchConditional, available[44]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpTypePointer, available[3]->opcode());
+      ASSERT_EQ(spv::Op::OpVariable, available[15]->opcode());
+      ASSERT_EQ(spv::Op::OpFunctionCall, available[40]->opcode());
+      ASSERT_EQ(spv::Op::OpBranchConditional, available[44]->opcode());
     }
     {
       auto available = all_instructions.GetAvailableBeforeInstruction(i6);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(33, available.size());
-      ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
-      ASSERT_EQ(SpvOpTypeFloat, available[4]->opcode());
-      ASSERT_EQ(SpvOpTypePointer, available[8]->opcode());
-      ASSERT_EQ(SpvOpConstantComposite, available[12]->opcode());
-      ASSERT_EQ(SpvOpConstant, available[16]->opcode());
-      ASSERT_EQ(SpvOpFunctionParameter, available[30]->opcode());
-      ASSERT_EQ(SpvOpFunctionParameter, available[31]->opcode());
-      ASSERT_EQ(SpvOpVariable, available[32]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeFloat, available[4]->opcode());
+      ASSERT_EQ(spv::Op::OpTypePointer, available[8]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[12]->opcode());
+      ASSERT_EQ(spv::Op::OpConstant, available[16]->opcode());
+      ASSERT_EQ(spv::Op::OpFunctionParameter, available[30]->opcode());
+      ASSERT_EQ(spv::Op::OpFunctionParameter, available[31]->opcode());
+      ASSERT_EQ(spv::Op::OpVariable, available[32]->opcode());
     }
   }
   {
@@ -225,51 +225,51 @@
       auto available = vector_instructions.GetAvailableBeforeInstruction(i4);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(3, available.size());
-      ASSERT_EQ(SpvOpConstantComposite, available[0]->opcode());
-      ASSERT_EQ(SpvOpConstantComposite, available[1]->opcode());
-      ASSERT_EQ(SpvOpCopyObject, available[2]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[1]->opcode());
+      ASSERT_EQ(spv::Op::OpCopyObject, available[2]->opcode());
     }
     {
       auto available = vector_instructions.GetAvailableBeforeInstruction(i5);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(3, available.size());
-      ASSERT_EQ(SpvOpConstantComposite, available[0]->opcode());
-      ASSERT_EQ(SpvOpConstantComposite, available[1]->opcode());
-      ASSERT_EQ(SpvOpCopyObject, available[2]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[1]->opcode());
+      ASSERT_EQ(spv::Op::OpCopyObject, available[2]->opcode());
     }
     {
       auto available = vector_instructions.GetAvailableBeforeInstruction(i6);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(2, available.size());
-      ASSERT_EQ(SpvOpConstantComposite, available[0]->opcode());
-      ASSERT_EQ(SpvOpConstantComposite, available[1]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[1]->opcode());
     }
   }
   {
     AvailableInstructions integer_add_instructions(
         context.get(), [](opt::IRContext*, opt::Instruction* inst) -> bool {
-          return inst->opcode() == SpvOpIAdd;
+          return inst->opcode() == spv::Op::OpIAdd;
         });
     {
       auto available =
           integer_add_instructions.GetAvailableBeforeInstruction(i7);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(1, available.size());
-      ASSERT_EQ(SpvOpIAdd, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpIAdd, available[0]->opcode());
     }
     {
       auto available =
           integer_add_instructions.GetAvailableBeforeInstruction(i8);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(1, available.size());
-      ASSERT_EQ(SpvOpIAdd, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpIAdd, available[0]->opcode());
     }
     {
       auto available =
           integer_add_instructions.GetAvailableBeforeInstruction(i9);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(1, available.size());
-      ASSERT_EQ(SpvOpIAdd, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpIAdd, available[0]->opcode());
     }
   }
 }
diff --git a/third_party/SPIRV-Tools/test/fuzz/data_synonym_transformation_test.cpp b/third_party/SPIRV-Tools/test/fuzz/data_synonym_transformation_test.cpp
index 7e93f29..3ba8093 100644
--- a/third_party/SPIRV-Tools/test/fuzz/data_synonym_transformation_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/data_synonym_transformation_test.cpp
@@ -146,12 +146,12 @@
 
   // Replace %12 with %100[0] in '%25 = OpAccessChain %24 %20 %12'
   auto instruction_descriptor_1 =
-      MakeInstructionDescriptor(25, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpAccessChain, 0);
   auto good_extract_1 =
       TransformationCompositeExtract(instruction_descriptor_1, 102, 100, {0});
   // Bad: id already in use
   auto bad_extract_1 = TransformationCompositeExtract(
-      MakeInstructionDescriptor(25, SpvOpAccessChain, 0), 25, 100, {0});
+      MakeInstructionDescriptor(25, spv::Op::OpAccessChain, 0), 25, 100, {0});
   ASSERT_TRUE(
       good_extract_1.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
@@ -166,7 +166,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %13 with %100[1] in 'OpStore %15 %13'
-  auto instruction_descriptor_2 = MakeInstructionDescriptor(100, SpvOpStore, 0);
+  auto instruction_descriptor_2 =
+      MakeInstructionDescriptor(100, spv::Op::OpStore, 0);
   auto good_extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 103, 100, {1});
   // No bad example provided here.
@@ -183,7 +184,7 @@
 
   // Replace %22 with %100[2] in '%23 = OpConvertSToF %16 %22'
   auto instruction_descriptor_3 =
-      MakeInstructionDescriptor(23, SpvOpConvertSToF, 0);
+      MakeInstructionDescriptor(23, spv::Op::OpConvertSToF, 0);
   auto good_extract_3 =
       TransformationCompositeExtract(instruction_descriptor_3, 104, 100, {2});
   ASSERT_TRUE(
@@ -203,12 +204,13 @@
                                                kConsoleMessageConsumer));
 
   // Replace %28 with %101[0] in 'OpStore %33 %28'
-  auto instruction_descriptor_4 = MakeInstructionDescriptor(33, SpvOpStore, 0);
+  auto instruction_descriptor_4 =
+      MakeInstructionDescriptor(33, spv::Op::OpStore, 0);
   auto good_extract_4 =
       TransformationCompositeExtract(instruction_descriptor_4, 105, 101, {0});
   // Bad: instruction descriptor does not identify an appropriate instruction
   auto bad_extract_4 = TransformationCompositeExtract(
-      MakeInstructionDescriptor(33, SpvOpCopyObject, 0), 105, 101, {0});
+      MakeInstructionDescriptor(33, spv::Op::OpCopyObject, 0), 105, 101, {0});
   ASSERT_TRUE(
       good_extract_4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
@@ -224,7 +226,7 @@
 
   // Replace %23 with %101[1] in '%50 = OpCopyObject %16 %23'
   auto instruction_descriptor_5 =
-      MakeInstructionDescriptor(50, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(50, spv::Op::OpCopyObject, 0);
   auto good_extract_5 =
       TransformationCompositeExtract(instruction_descriptor_5, 106, 101, {1});
   ASSERT_TRUE(
@@ -244,7 +246,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %32 with %101[2] in 'OpStore %33 %32'
-  auto instruction_descriptor_6 = MakeInstructionDescriptor(33, SpvOpStore, 1);
+  auto instruction_descriptor_6 =
+      MakeInstructionDescriptor(33, spv::Op::OpStore, 1);
   auto good_extract_6 =
       TransformationCompositeExtract(instruction_descriptor_6, 107, 101, {2});
   // Bad: id 1001 does not exist
@@ -265,7 +268,7 @@
 
   // Replace %23 with %101[3] in '%51 = OpCopyObject %16 %23'
   auto instruction_descriptor_7 =
-      MakeInstructionDescriptor(51, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(51, spv::Op::OpCopyObject, 0);
   auto good_extract_7 =
       TransformationCompositeExtract(instruction_descriptor_7, 108, 101, {3});
   ASSERT_TRUE(
@@ -431,7 +434,8 @@
       MakeSynonymFact(50, {}, 100, {2}));
 
   // Replace %23 with %100[0] in '%26 = OpFAdd %7 %23 %25'
-  auto instruction_descriptor_1 = MakeInstructionDescriptor(26, SpvOpFAdd, 0);
+  auto instruction_descriptor_1 =
+      MakeInstructionDescriptor(26, spv::Op::OpFAdd, 0);
   auto extract_1 =
       TransformationCompositeExtract(instruction_descriptor_1, 101, 100, {0});
   ASSERT_TRUE(extract_1.IsApplicable(context.get(), transformation_context));
@@ -445,7 +449,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %25 with %100[1] in '%26 = OpFAdd %7 %23 %25'
-  auto instruction_descriptor_2 = MakeInstructionDescriptor(26, SpvOpFAdd, 0);
+  auto instruction_descriptor_2 =
+      MakeInstructionDescriptor(26, spv::Op::OpFAdd, 0);
   auto extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 102, 100, {1});
   ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
@@ -611,7 +616,7 @@
 
   // Replace %45 with %100[1] in '%46 = OpCompositeConstruct %32 %35 %45'
   auto instruction_descriptor_1 =
-      MakeInstructionDescriptor(46, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(46, spv::Op::OpCompositeConstruct, 0);
   auto extract_1 =
       TransformationCompositeExtract(instruction_descriptor_1, 201, 100, {1});
   ASSERT_TRUE(extract_1.IsApplicable(context.get(), transformation_context));
@@ -627,7 +632,7 @@
   // Replace second occurrence of %27 with %101[0] in '%28 =
   // OpCompositeConstruct %8 %27 %27'
   auto instruction_descriptor_2 =
-      MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(28, spv::Op::OpCompositeConstruct, 0);
   auto extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 202, 101, {0});
   ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
@@ -642,7 +647,7 @@
 
   // Replace %36 with %101[1] in '%45 = OpCompositeConstruct %31 %36 %41 %44'
   auto instruction_descriptor_3 =
-      MakeInstructionDescriptor(45, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(45, spv::Op::OpCompositeConstruct, 0);
   auto extract_3 =
       TransformationCompositeExtract(instruction_descriptor_3, 203, 101, {1});
   ASSERT_TRUE(extract_3.IsApplicable(context.get(), transformation_context));
@@ -658,7 +663,7 @@
   // Replace first occurrence of %27 with %101[2] in '%28 = OpCompositeConstruct
   // %8 %27 %27'
   auto instruction_descriptor_4 =
-      MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(28, spv::Op::OpCompositeConstruct, 0);
   auto extract_4 =
       TransformationCompositeExtract(instruction_descriptor_4, 204, 101, {2});
   ASSERT_TRUE(extract_4.IsApplicable(context.get(), transformation_context));
@@ -672,7 +677,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %22 with %102[0] in 'OpStore %23 %22'
-  auto instruction_descriptor_5 = MakeInstructionDescriptor(23, SpvOpStore, 0);
+  auto instruction_descriptor_5 =
+      MakeInstructionDescriptor(23, spv::Op::OpStore, 0);
   auto extract_5 =
       TransformationCompositeExtract(instruction_descriptor_5, 205, 102, {0});
   ASSERT_TRUE(extract_5.IsApplicable(context.get(), transformation_context));
@@ -931,7 +937,7 @@
 
   // Replace %20 with %100[0:2] in '%80 = OpCopyObject %16 %20'
   auto instruction_descriptor_1 =
-      MakeInstructionDescriptor(80, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(80, spv::Op::OpCopyObject, 0);
   auto shuffle_1 = TransformationVectorShuffle(instruction_descriptor_1, 200,
                                                100, 100, {0, 1, 2});
   ASSERT_TRUE(shuffle_1.IsApplicable(context.get(), transformation_context));
@@ -948,7 +954,7 @@
 
   // Replace %54 with %100[3] in '%56 = OpFOrdNotEqual %30 %54 %55'
   auto instruction_descriptor_2 =
-      MakeInstructionDescriptor(56, SpvOpFOrdNotEqual, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpFOrdNotEqual, 0);
   auto extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 201, 100, {3});
 
@@ -963,7 +969,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %15 with %101[0:1] in 'OpStore %12 %15'
-  auto instruction_descriptor_3 = MakeInstructionDescriptor(64, SpvOpStore, 0);
+  auto instruction_descriptor_3 =
+      MakeInstructionDescriptor(64, spv::Op::OpStore, 0);
   auto shuffle_3 = TransformationVectorShuffle(instruction_descriptor_3, 202,
                                                101, 101, {0, 1});
   ASSERT_TRUE(shuffle_3.IsApplicable(context.get(), transformation_context));
@@ -980,7 +987,7 @@
 
   // Replace %19 with %101[2:3] in '%81 = OpVectorShuffle %16 %19 %19 0 0 1'
   auto instruction_descriptor_4 =
-      MakeInstructionDescriptor(81, SpvOpVectorShuffle, 0);
+      MakeInstructionDescriptor(81, spv::Op::OpVectorShuffle, 0);
   auto shuffle_4 = TransformationVectorShuffle(instruction_descriptor_4, 203,
                                                101, 101, {2, 3});
   ASSERT_TRUE(shuffle_4.IsApplicable(context.get(), transformation_context));
@@ -998,7 +1005,7 @@
   // Replace %27 with %102[0] in '%82 = OpCompositeConstruct %21 %26 %27 %28
   // %25'
   auto instruction_descriptor_5 =
-      MakeInstructionDescriptor(82, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(82, spv::Op::OpCompositeConstruct, 0);
   auto extract_5 =
       TransformationCompositeExtract(instruction_descriptor_5, 204, 102, {0});
 
@@ -1014,7 +1021,7 @@
 
   // Replace %15 with %102[1:2] in '%83 = OpCopyObject %10 %15'
   auto instruction_descriptor_6 =
-      MakeInstructionDescriptor(83, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(83, spv::Op::OpCopyObject, 0);
   auto shuffle_6 = TransformationVectorShuffle(instruction_descriptor_6, 205,
                                                102, 102, {1, 2});
   ASSERT_TRUE(shuffle_6.IsApplicable(context.get(), transformation_context));
@@ -1031,7 +1038,7 @@
 
   // Replace %33 with %103[0] in '%86 = OpCopyObject %30 %33'
   auto instruction_descriptor_7 =
-      MakeInstructionDescriptor(86, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(86, spv::Op::OpCopyObject, 0);
   auto extract_7 =
       TransformationCompositeExtract(instruction_descriptor_7, 206, 103, {0});
   ASSERT_TRUE(extract_7.IsApplicable(context.get(), transformation_context));
@@ -1046,7 +1053,7 @@
 
   // Replace %47 with %103[1:3] in '%84 = OpCopyObject %39 %47'
   auto instruction_descriptor_8 =
-      MakeInstructionDescriptor(84, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(84, spv::Op::OpCopyObject, 0);
   auto shuffle_8 = TransformationVectorShuffle(instruction_descriptor_8, 207,
                                                103, 103, {1, 2, 3});
   ASSERT_TRUE(shuffle_8.IsApplicable(context.get(), transformation_context));
@@ -1063,7 +1070,7 @@
 
   // Replace %42 with %104[0] in '%85 = OpCopyObject %30 %42'
   auto instruction_descriptor_9 =
-      MakeInstructionDescriptor(85, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(85, spv::Op::OpCopyObject, 0);
   auto extract_9 =
       TransformationCompositeExtract(instruction_descriptor_9, 208, 104, {0});
   ASSERT_TRUE(extract_9.IsApplicable(context.get(), transformation_context));
@@ -1078,7 +1085,7 @@
 
   // Replace %45 with %104[1] in '%63 = OpLogicalOr %30 %45 %46'
   auto instruction_descriptor_10 =
-      MakeInstructionDescriptor(63, SpvOpLogicalOr, 0);
+      MakeInstructionDescriptor(63, spv::Op::OpLogicalOr, 0);
   auto extract_10 =
       TransformationCompositeExtract(instruction_descriptor_10, 209, 104, {1});
   ASSERT_TRUE(extract_10.IsApplicable(context.get(), transformation_context));
@@ -1092,7 +1099,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %38 with %105[0:1] in 'OpStore %36 %38'
-  auto instruction_descriptor_11 = MakeInstructionDescriptor(85, SpvOpStore, 0);
+  auto instruction_descriptor_11 =
+      MakeInstructionDescriptor(85, spv::Op::OpStore, 0);
   auto shuffle_11 = TransformationVectorShuffle(instruction_descriptor_11, 210,
                                                 105, 105, {0, 1});
   ASSERT_TRUE(shuffle_11.IsApplicable(context.get(), transformation_context));
@@ -1109,7 +1117,7 @@
 
   // Replace %46 with %105[2] in '%62 = OpLogicalAnd %30 %45 %46'
   auto instruction_descriptor_12 =
-      MakeInstructionDescriptor(62, SpvOpLogicalAnd, 0);
+      MakeInstructionDescriptor(62, spv::Op::OpLogicalAnd, 0);
   auto extract_12 =
       TransformationCompositeExtract(instruction_descriptor_12, 211, 105, {2});
   ASSERT_TRUE(extract_12.IsApplicable(context.get(), transformation_context));
diff --git a/third_party/SPIRV-Tools/test/fuzz/fact_manager/constant_uniform_facts_test.cpp b/third_party/SPIRV-Tools/test/fuzz/fact_manager/constant_uniform_facts_test.cpp
index 4d80f0a..b267e3d 100644
--- a/third_party/SPIRV-Tools/test/fuzz/fact_manager/constant_uniform_facts_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/fact_manager/constant_uniform_facts_test.cpp
@@ -366,41 +366,41 @@
   opt::Instruction::OperandList operands = {
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_int32_id, 50, operands));
+      context.get(), spv::Op::OpConstant, type_int32_id, 50, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int32_min[0]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_int32_id, 51, operands));
+      context.get(), spv::Op::OpConstant, type_int32_id, 51, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_int64_id, 52, operands));
+      context.get(), spv::Op::OpConstant, type_int64_id, 52, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_uint32_id, 53, operands));
+      context.get(), spv::Op::OpConstant, type_uint32_id, 53, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_uint64_id, 54, operands));
+      context.get(), spv::Op::OpConstant, type_uint64_id, 54, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_uint64_id, 55, operands));
+      context.get(), spv::Op::OpConstant, type_uint64_id, 55, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_float_10[0]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_float_id, 56, operands));
+      context.get(), spv::Op::OpConstant, type_float_id, 56, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_double_id, 57, operands));
+      context.get(), spv::Op::OpConstant, type_double_id, 57, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_double_id, 58, operands));
+      context.get(), spv::Op::OpConstant, type_double_id, 58, operands));
 
   // A duplicate of the constant with id 59.
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_int32_id, 59, operands));
+      context.get(), spv::Op::OpConstant, type_int32_id, 59, operands));
 
   context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
 
diff --git a/third_party/SPIRV-Tools/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp b/third_party/SPIRV-Tools/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp
index 689d2e7..c3b47a4 100644
--- a/third_party/SPIRV-Tools/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp
@@ -136,15 +136,15 @@
   FactManager fact_manager(context.get());
 
   // Add equation facts
-  fact_manager.AddFactIdEquation(24, SpvOpConvertSToF, {15});
-  fact_manager.AddFactIdEquation(25, SpvOpConvertSToF, {16});
-  fact_manager.AddFactIdEquation(26, SpvOpConvertUToF, {17});
-  fact_manager.AddFactIdEquation(27, SpvOpConvertSToF, {18});
-  fact_manager.AddFactIdEquation(28, SpvOpConvertUToF, {19});
-  fact_manager.AddFactIdEquation(29, SpvOpConvertUToF, {20});
-  fact_manager.AddFactIdEquation(30, SpvOpConvertSToF, {21});
-  fact_manager.AddFactIdEquation(31, SpvOpConvertUToF, {22});
-  fact_manager.AddFactIdEquation(32, SpvOpConvertUToF, {23});
+  fact_manager.AddFactIdEquation(24, spv::Op::OpConvertSToF, {15});
+  fact_manager.AddFactIdEquation(25, spv::Op::OpConvertSToF, {16});
+  fact_manager.AddFactIdEquation(26, spv::Op::OpConvertUToF, {17});
+  fact_manager.AddFactIdEquation(27, spv::Op::OpConvertSToF, {18});
+  fact_manager.AddFactIdEquation(28, spv::Op::OpConvertUToF, {19});
+  fact_manager.AddFactIdEquation(29, spv::Op::OpConvertUToF, {20});
+  fact_manager.AddFactIdEquation(30, spv::Op::OpConvertSToF, {21});
+  fact_manager.AddFactIdEquation(31, spv::Op::OpConvertUToF, {22});
+  fact_manager.AddFactIdEquation(32, spv::Op::OpConvertUToF, {23});
 
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(15, {}),
                                   MakeDataDescriptor(16, {}));
@@ -212,7 +212,7 @@
 
   // Add required facts.
   transformation_context.GetFactManager()->AddFactIdEquation(
-      14, SpvOpConvertSToF, {9});
+      14, spv::Op::OpConvertSToF, {9});
   transformation_context.GetFactManager()->AddFactDataSynonym(
       MakeDataDescriptor(14, {}), MakeDataDescriptor(17, {}));
 
@@ -232,7 +232,7 @@
 
   // Add another equation.
   transformation_context.GetFactManager()->AddFactIdEquation(
-      15, SpvOpConvertSToF, {9});
+      15, spv::Op::OpConvertSToF, {9});
 
   // Check that two ids are synonymous even though one of them doesn't exist in
   // the module (%17).
@@ -249,7 +249,7 @@
   ASSERT_TRUE(context->KillDef(15));
 
   transformation_context.GetFactManager()->AddFactIdEquation(
-      18, SpvOpConvertSToF, {9});
+      18, spv::Op::OpConvertSToF, {9});
 
   CheckConsistencyOfSynonymFacts(context.get(), transformation_context);
 
@@ -294,8 +294,8 @@
                                   MakeDataDescriptor(7, {}));
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(16, {}),
                                   MakeDataDescriptor(14, {}));
-  fact_manager.AddFactIdEquation(14, SpvOpLogicalNot, {7});
-  fact_manager.AddFactIdEquation(17, SpvOpLogicalNot, {16});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpLogicalNot, {7});
+  fact_manager.AddFactIdEquation(17, spv::Op::OpLogicalNot, {16});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
                                         MakeDataDescriptor(7, {})));
@@ -336,8 +336,8 @@
 
   FactManager fact_manager(context.get());
 
-  fact_manager.AddFactIdEquation(14, SpvOpSNegate, {7});
-  fact_manager.AddFactIdEquation(15, SpvOpSNegate, {14});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpSNegate, {7});
+  fact_manager.AddFactIdEquation(15, spv::Op::OpSNegate, {14});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
                                         MakeDataDescriptor(15, {})));
@@ -380,19 +380,19 @@
 
   FactManager fact_manager(context.get());
 
-  fact_manager.AddFactIdEquation(14, SpvOpIAdd, {15, 16});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpIAdd, {15, 16});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(17, {}),
                                   MakeDataDescriptor(15, {}));
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(18, {}),
                                   MakeDataDescriptor(16, {}));
-  fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 18});
-  fact_manager.AddFactIdEquation(20, SpvOpISub, {14, 17});
+  fact_manager.AddFactIdEquation(19, spv::Op::OpISub, {14, 18});
+  fact_manager.AddFactIdEquation(20, spv::Op::OpISub, {14, 17});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {}),
                                   MakeDataDescriptor(14, {}));
-  fact_manager.AddFactIdEquation(22, SpvOpISub, {16, 21});
+  fact_manager.AddFactIdEquation(22, spv::Op::OpISub, {16, 21});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(23, {}),
                                   MakeDataDescriptor(22, {}));
-  fact_manager.AddFactIdEquation(24, SpvOpSNegate, {23});
+  fact_manager.AddFactIdEquation(24, spv::Op::OpSNegate, {23});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(19, {}),
                                         MakeDataDescriptor(15, {})));
@@ -438,31 +438,31 @@
 
   FactManager fact_manager(context.get());
 
-  fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16});
-  fact_manager.AddFactIdEquation(17, SpvOpIAdd, {14, 16});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpISub, {15, 16});
+  fact_manager.AddFactIdEquation(17, spv::Op::OpIAdd, {14, 16});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
                                         MakeDataDescriptor(15, {})));
 
-  fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 14});
+  fact_manager.AddFactIdEquation(18, spv::Op::OpIAdd, {16, 14});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
                                         MakeDataDescriptor(15, {})));
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
                                         MakeDataDescriptor(18, {})));
 
-  fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15});
-  fact_manager.AddFactIdEquation(20, SpvOpSNegate, {19});
+  fact_manager.AddFactIdEquation(19, spv::Op::OpISub, {14, 15});
+  fact_manager.AddFactIdEquation(20, spv::Op::OpSNegate, {19});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
                                         MakeDataDescriptor(16, {})));
 
-  fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19});
+  fact_manager.AddFactIdEquation(21, spv::Op::OpISub, {14, 19});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
                                         MakeDataDescriptor(15, {})));
 
-  fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18});
-  fact_manager.AddFactIdEquation(23, SpvOpSNegate, {22});
+  fact_manager.AddFactIdEquation(22, spv::Op::OpISub, {14, 18});
+  fact_manager.AddFactIdEquation(23, spv::Op::OpSNegate, {22});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
                                         MakeDataDescriptor(16, {})));
 }
@@ -525,31 +525,31 @@
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
                                   MakeDataDescriptor(23, {}));
 
-  fact_manager.AddFactIdEquation(25, SpvOpConvertUToF, {16});
-  fact_manager.AddFactIdEquation(26, SpvOpConvertUToF, {17});
+  fact_manager.AddFactIdEquation(25, spv::Op::OpConvertUToF, {16});
+  fact_manager.AddFactIdEquation(26, spv::Op::OpConvertUToF, {17});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(25, {}),
                                         MakeDataDescriptor(26, {})));
 
-  fact_manager.AddFactIdEquation(27, SpvOpConvertSToF, {20});
-  fact_manager.AddFactIdEquation(28, SpvOpConvertUToF, {21});
+  fact_manager.AddFactIdEquation(27, spv::Op::OpConvertSToF, {20});
+  fact_manager.AddFactIdEquation(28, spv::Op::OpConvertUToF, {21});
   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {}),
                                          MakeDataDescriptor(28, {})));
 
-  fact_manager.AddFactIdEquation(29, SpvOpConvertSToF, {18});
-  fact_manager.AddFactIdEquation(30, SpvOpConvertUToF, {19});
+  fact_manager.AddFactIdEquation(29, spv::Op::OpConvertSToF, {18});
+  fact_manager.AddFactIdEquation(30, spv::Op::OpConvertUToF, {19});
   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(29, {}),
                                          MakeDataDescriptor(30, {})));
 
-  fact_manager.AddFactIdEquation(31, SpvOpConvertSToF, {22});
-  fact_manager.AddFactIdEquation(32, SpvOpConvertSToF, {23});
+  fact_manager.AddFactIdEquation(31, spv::Op::OpConvertSToF, {22});
+  fact_manager.AddFactIdEquation(32, spv::Op::OpConvertSToF, {23});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(31, {}),
                                         MakeDataDescriptor(32, {})));
 
-  fact_manager.AddFactIdEquation(33, SpvOpConvertUToF, {17});
+  fact_manager.AddFactIdEquation(33, spv::Op::OpConvertUToF, {17});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {}),
                                         MakeDataDescriptor(26, {})));
 
-  fact_manager.AddFactIdEquation(34, SpvOpConvertSToF, {23});
+  fact_manager.AddFactIdEquation(34, spv::Op::OpConvertSToF, {23});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
                                         MakeDataDescriptor(34, {})));
 }
@@ -605,7 +605,7 @@
 
   uint32_t lhs_id = 30;
   for (uint32_t rhs_id : {6, 6, 7, 7, 19, 19, 20, 20, 21, 21, 22, 22}) {
-    fact_manager.AddFactIdEquation(lhs_id, SpvOpBitcast, {rhs_id});
+    fact_manager.AddFactIdEquation(lhs_id, spv::Op::OpBitcast, {rhs_id});
     ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(lhs_id, {}),
                                           MakeDataDescriptor(rhs_id, {})));
     ++lhs_id;
@@ -651,37 +651,37 @@
 
   FactManager fact_manager(context.get());
 
-  fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpISub, {15, 16});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(114, {}),
                                   MakeDataDescriptor(14, {}));
-  fact_manager.AddFactIdEquation(17, SpvOpIAdd, {114, 16});
+  fact_manager.AddFactIdEquation(17, spv::Op::OpIAdd, {114, 16});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
                                         MakeDataDescriptor(15, {})));
 
-  fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 114});
+  fact_manager.AddFactIdEquation(18, spv::Op::OpIAdd, {16, 114});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
                                         MakeDataDescriptor(15, {})));
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
                                         MakeDataDescriptor(18, {})));
 
-  fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15});
+  fact_manager.AddFactIdEquation(19, spv::Op::OpISub, {14, 15});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(119, {}),
                                   MakeDataDescriptor(19, {}));
-  fact_manager.AddFactIdEquation(20, SpvOpSNegate, {119});
+  fact_manager.AddFactIdEquation(20, spv::Op::OpSNegate, {119});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
                                         MakeDataDescriptor(16, {})));
 
-  fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19});
+  fact_manager.AddFactIdEquation(21, spv::Op::OpISub, {14, 19});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
                                         MakeDataDescriptor(15, {})));
 
-  fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18});
+  fact_manager.AddFactIdEquation(22, spv::Op::OpISub, {14, 18});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
                                   MakeDataDescriptor(220, {}));
-  fact_manager.AddFactIdEquation(23, SpvOpSNegate, {220});
+  fact_manager.AddFactIdEquation(23, spv::Op::OpSNegate, {220});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
                                         MakeDataDescriptor(16, {})));
 }
diff --git a/third_party/SPIRV-Tools/test/fuzz/fuzzer_pass_donate_modules_test.cpp b/third_party/SPIRV-Tools/test/fuzz/fuzzer_pass_donate_modules_test.cpp
index fe8e671..81687ac 100644
--- a/third_party/SPIRV-Tools/test/fuzz/fuzzer_pass_donate_modules_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/fuzzer_pass_donate_modules_test.cpp
@@ -2025,9 +2025,9 @@
                                       &transformation_sequence, false, {});
 
   ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability(
-      SpvCapabilityVariablePointersStorageBuffer));
+      spv::Capability::VariablePointersStorageBuffer));
   ASSERT_FALSE(recipient_context->get_feature_mgr()->HasCapability(
-      SpvCapabilityVariablePointersStorageBuffer));
+      spv::Capability::VariablePointersStorageBuffer));
 
   fuzzer_pass.DonateSingleModule(donor_context.get(), false);
 
@@ -2040,12 +2040,12 @@
   // have different OpCapability instructions but the same capabilities. In our
   // example, VariablePointers implicitly declares
   // VariablePointersStorageBuffer. Thus, two modules must be compatible.
-  recipient_context->AddCapability(SpvCapabilityVariablePointers);
+  recipient_context->AddCapability(spv::Capability::VariablePointers);
 
   ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability(
-      SpvCapabilityVariablePointersStorageBuffer));
+      spv::Capability::VariablePointersStorageBuffer));
   ASSERT_TRUE(recipient_context->get_feature_mgr()->HasCapability(
-      SpvCapabilityVariablePointersStorageBuffer));
+      spv::Capability::VariablePointersStorageBuffer));
 
   fuzzer_pass.DonateSingleModule(donor_context.get(), false);
 
diff --git a/third_party/SPIRV-Tools/test/fuzz/fuzzerutil_test.cpp b/third_party/SPIRV-Tools/test/fuzz/fuzzerutil_test.cpp
index 1286d38..6555336 100644
--- a/third_party/SPIRV-Tools/test/fuzz/fuzzerutil_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/fuzzerutil_test.cpp
@@ -939,9 +939,9 @@
                                                kConsoleMessageConsumer));
 
   opt::IRContext* ir_context = context.get();
-  auto private_storage_class = SpvStorageClassPrivate;
-  auto function_storage_class = SpvStorageClassFunction;
-  auto input_storage_class = SpvStorageClassInput;
+  auto private_storage_class = spv::StorageClass::Private;
+  auto function_storage_class = spv::StorageClass::Function;
+  auto input_storage_class = spv::StorageClass::Input;
 
   // A valid pointer must have the correct |pointee_type_id| and |storageClass|.
   // A function type pointer with id = 9 and pointee type id 8 should be found.
@@ -1610,196 +1610,206 @@
 
   // OpAtomicLoad
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicLoad, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
-#endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicLoad, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicLoad, 2,
-                                             int_type, uint_type));
-
-  // OpAtomicExchange
-#ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
-                   context.get(), SpvOpAtomicExchange, 0, int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
-#endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicExchange,
-                                             1, int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicExchange,
-                                             2, int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicExchange, 3, int_type, uint_type));
-
-  // OpAtomicStore
-#ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore,
-                                              0, int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
-#endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore,
-                                              3, int_type, uint_type));
-
-  // OpAtomicCompareExchange
-#ifndef NDEBUG
   ASSERT_DEATH(
-      fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicCompareExchange,
-                                     0, int_type, uint_type),
-      "Signedness check should not occur on a pointer operand.");
-#endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicCompareExchange, 1, int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicCompareExchange, 2, int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicCompareExchange, 3, int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicCompareExchange, 4, int_type, uint_type));
-
-  // OpAtomicIIncrement
-#ifndef NDEBUG
-  ASSERT_DEATH(
-      fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIIncrement, 0,
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicLoad, 0,
                                      int_type, uint_type),
       "Signedness check should not occur on a pointer operand.");
 #endif
   ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicIIncrement, 1, int_type, uint_type));
+      context.get(), spv::Op::OpAtomicLoad, 1, int_type, uint_type));
   ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicIIncrement, 2, int_type, uint_type));
+      context.get(), spv::Op::OpAtomicLoad, 2, int_type, uint_type));
 
-// OpAtomicIDecrement
+  // OpAtomicExchange
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore,
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicExchange,
+                                     0, int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
+#endif
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicExchange, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicExchange, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicExchange, 3, int_type, uint_type));
+
+  // OpAtomicStore
+#ifndef NDEBUG
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicStore, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
+#endif
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 3, int_type, uint_type));
+
+  // OpAtomicCompareExchange
+#ifndef NDEBUG
+  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(),
+                                              spv::Op::OpAtomicCompareExchange,
                                               0, int_type, uint_type),
                "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore, 2,
-                                             int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicCompareExchange, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicCompareExchange, 2, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicCompareExchange, 3, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicCompareExchange, 4, int_type, uint_type));
+
+  // OpAtomicIIncrement
+#ifndef NDEBUG
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicIIncrement,
+                                     0, int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
+#endif
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIIncrement, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIIncrement, 2, int_type, uint_type));
+
+// OpAtomicIDecrement
+#ifndef NDEBUG
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicStore, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
+#endif
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 2, int_type, uint_type));
 
 // OpAtomicIAdd
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIAdd, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicIAdd, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIAdd, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIAdd, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIAdd, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIAdd, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIAdd, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIAdd, 3, int_type, uint_type));
 
 // OpAtomicISub
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicISub, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicISub, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicISub, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicISub, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicISub, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicISub, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicISub, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicISub, 3, int_type, uint_type));
 
 // OpAtomicSMin
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMin, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicSMin, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMin, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMin, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMin, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMin, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMin, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMin, 3, int_type, uint_type));
 
 // OpAtomicUMin
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMin, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicUMin, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMin, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMin, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMin, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMin, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMin, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMin, 3, int_type, uint_type));
 
 // OpAtomicSMax
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMax, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicSMax, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMax, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMax, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMax, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMax, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMax, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMax, 3, int_type, uint_type));
 
 // OpAtomicUMax
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMax, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicUMax, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMax, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMax, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMax, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMax, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMax, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMax, 3, int_type, uint_type));
 
 // OpAtomicAnd
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicAnd, 0,
-                                              int_type, uint_type),
+  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
+                   context.get(), spv::Op::OpAtomicAnd, 0, int_type, uint_type),
                "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicAnd, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicAnd, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicAnd, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicAnd, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicAnd, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicAnd, 3, int_type, uint_type));
 
 // OpAtomicOr
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicOr, 0,
-                                              int_type, uint_type),
+  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
+                   context.get(), spv::Op::OpAtomicOr, 0, int_type, uint_type),
                "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicOr, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicOr, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicOr, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicOr,
+                                             1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicOr,
+                                             2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicOr, 3, int_type, uint_type));
 
 // OpAtomicXor
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicXor, 0,
-                                              int_type, uint_type),
+  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
+                   context.get(), spv::Op::OpAtomicXor, 0, int_type, uint_type),
                "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicXor, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicXor, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicXor, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicXor, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicXor, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicXor, 3, int_type, uint_type));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/fuzz/replayer_test.cpp b/third_party/SPIRV-Tools/test/fuzz/replayer_test.cpp
index 151f263..b87d4f8 100644
--- a/third_party/SPIRV-Tools/test/fuzz/replayer_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/replayer_test.cpp
@@ -90,8 +90,8 @@
   protobufs::TransformationSequence transformations;
   for (uint32_t id = 12; id <= 22; id++) {
     *transformations.add_transformation() =
-        TransformationSplitBlock(MakeInstructionDescriptor(id, SpvOpLoad, 0),
-                                 id + 100)
+        TransformationSplitBlock(
+            MakeInstructionDescriptor(id, spv::Op::OpLoad, 0), id + 100)
             .ToMessage();
   }
 
@@ -335,7 +335,7 @@
   *transformations.add_transformation() =
       TransformationAddConstantScalar(100, 8, {42}, true).ToMessage();
   *transformations.add_transformation() =
-      TransformationAddGlobalVariable(101, 50, SpvStorageClassPrivate, 100,
+      TransformationAddGlobalVariable(101, 50, spv::StorageClass::Private, 100,
                                       true)
           .ToMessage();
   *transformations.add_transformation() =
@@ -345,7 +345,7 @@
           11,
           protobufs::TransformationAddSynonym::SynonymType::
               TransformationAddSynonym_SynonymType_COPY_OBJECT,
-          104, MakeInstructionDescriptor(12, SpvOpFunctionCall, 0))
+          104, MakeInstructionDescriptor(12, spv::Op::OpFunctionCall, 0))
           .ToMessage();
 
   // Full replay
@@ -455,7 +455,8 @@
   *transformations.add_transformation() =
       TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {}).ToMessage();
   *transformations.add_transformation() =
-      TransformationAddGlobalVariable(101, 50, SpvStorageClassPrivate, 11, true)
+      TransformationAddGlobalVariable(101, 50, spv::StorageClass::Private, 11,
+                                      true)
           .ToMessage();
 
   protobufs::FactSequence empty_facts;
diff --git a/third_party/SPIRV-Tools/test/fuzz/shrinker_test.cpp b/third_party/SPIRV-Tools/test/fuzz/shrinker_test.cpp
index 942de29..699730c 100644
--- a/third_party/SPIRV-Tools/test/fuzz/shrinker_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/shrinker_test.cpp
@@ -186,9 +186,9 @@
     for (auto& function : *temp_ir_context->module()) {
       for (auto& block : function) {
         for (auto& inst : block) {
-          if (inst.opcode() == SpvOpNot) {
+          if (inst.opcode() == spv::Op::OpNot) {
             found_op_not = true;
-          } else if (inst.opcode() == SpvOpFunctionCall) {
+          } else if (inst.opcode() == spv::Op::OpFunctionCall) {
             op_call_count++;
           }
         }
@@ -221,21 +221,21 @@
         for (auto& inst : block) {
           switch (counter) {
             case 0:
-              ASSERT_EQ(SpvOpVariable, inst.opcode());
+              ASSERT_EQ(spv::Op::OpVariable, inst.opcode());
               ASSERT_EQ(11, inst.result_id());
               break;
             case 1:
-              ASSERT_EQ(SpvOpStore, inst.opcode());
+              ASSERT_EQ(spv::Op::OpStore, inst.opcode());
               break;
             case 2:
-              ASSERT_EQ(SpvOpLoad, inst.opcode());
+              ASSERT_EQ(spv::Op::OpLoad, inst.opcode());
               ASSERT_EQ(12, inst.result_id());
               break;
             case 3:
-              ASSERT_EQ(SpvOpStore, inst.opcode());
+              ASSERT_EQ(spv::Op::OpStore, inst.opcode());
               break;
             case 4:
-              ASSERT_EQ(SpvOpReturn, inst.opcode());
+              ASSERT_EQ(spv::Op::OpReturn, inst.opcode());
               break;
             default:
               FAIL();
@@ -250,11 +250,11 @@
         first_block = false;
         for (auto& inst : block) {
           switch (inst.opcode()) {
-            case SpvOpVariable:
-            case SpvOpNot:
-            case SpvOpReturn:
-            case SpvOpReturnValue:
-            case SpvOpFunctionCall:
+            case spv::Op::OpVariable:
+            case spv::Op::OpNot:
+            case spv::Op::OpReturn:
+            case spv::Op::OpReturnValue:
+            case spv::Op::OpFunctionCall:
               // These are the only instructions we expect to see.
               break;
             default:
@@ -362,7 +362,7 @@
     uint32_t copy_object_count = 0;
     temp_ir_context->module()->ForEachInst(
         [&copy_object_count](opt::Instruction* inst) {
-          if (inst->opcode() == SpvOpCopyObject) {
+          if (inst->opcode() == spv::Op::OpCopyObject) {
             copy_object_count++;
           }
         });
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_access_chain_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_access_chain_test.cpp
index bddcf5f..fa19aa5 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_access_chain_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_access_chain_test.cpp
@@ -129,7 +129,7 @@
 
   // Check the case where the index type is not a 32-bit integer.
   TransformationAccessChain invalid_index_example1(
-      101, 28, {29}, MakeInstructionDescriptor(42, SpvOpReturn, 0));
+      101, 28, {29}, MakeInstructionDescriptor(42, spv::Op::OpReturn, 0));
 
   // Since the index  is not a 32-bit integer type but a 32-bit float type,
   // ValidIndexComposite should return false and thus the transformation is not
@@ -138,86 +138,95 @@
                                                    transformation_context));
 
   // Bad: id is not fresh
-  ASSERT_FALSE(TransformationAccessChain(
-                   43, 43, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          43, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id does not exist
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 1000, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 1000, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id is not a type
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 5, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 5, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id is not a pointer
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 23, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 23, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: index id does not exist
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 43, {1000}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 43, {1000}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: index id is not a constant and the pointer refers to a struct
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 43, {24}, MakeInstructionDescriptor(25, SpvOpIAdd, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 43, {24}, MakeInstructionDescriptor(25, spv::Op::OpIAdd, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: too many indices
-  ASSERT_FALSE(
-      TransformationAccessChain(100, 43, {80, 80, 80},
-                                MakeInstructionDescriptor(24, SpvOpLoad, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAccessChain(
+                   100, 43, {80, 80, 80},
+                   MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: index id is out of bounds when accessing a struct
   ASSERT_FALSE(
-      TransformationAccessChain(100, 43, {83, 80},
-                                MakeInstructionDescriptor(24, SpvOpLoad, 0))
+      TransformationAccessChain(
+          100, 43, {83, 80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to insert before variable
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 34, {}, MakeInstructionDescriptor(36, SpvOpVariable, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 34, {}, MakeInstructionDescriptor(36, spv::Op::OpVariable, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: OpTypeBool must be present in the module to clamp an index
   ASSERT_FALSE(
-      TransformationAccessChain(100, 36, {80, 81},
-                                MakeInstructionDescriptor(37, SpvOpStore, 0))
+      TransformationAccessChain(
+          100, 36, {80, 81}, MakeInstructionDescriptor(37, spv::Op::OpStore, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer not available
-  ASSERT_FALSE(
-      TransformationAccessChain(
-          100, 43, {80}, MakeInstructionDescriptor(21, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAccessChain(
+                   100, 43, {80},
+                   MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: instruction descriptor does not identify anything
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 43, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 100))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 100))
+          .IsApplicable(context.get(), transformation_context));
 
 #ifndef NDEBUG
   // Bad: pointer is null
   ASSERT_DEATH(
-      TransformationAccessChain(100, 46, {80},
-                                MakeInstructionDescriptor(24, SpvOpLoad, 0))
+      TransformationAccessChain(
+          100, 46, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
           .IsApplicable(context.get(), transformation_context),
       "Access chains should not be created from null/undefined pointers");
 #endif
 
   // Bad: pointer to result type does not exist
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 52, {0}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 52, {0}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationAccessChain transformation(
-        100, 43, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
+        100, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -230,7 +239,7 @@
 
   {
     TransformationAccessChain transformation(
-        101, 28, {81}, MakeInstructionDescriptor(42, SpvOpReturn, 0));
+        101, 28, {81}, MakeInstructionDescriptor(42, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -243,7 +252,7 @@
 
   {
     TransformationAccessChain transformation(
-        102, 44, {}, MakeInstructionDescriptor(44, SpvOpStore, 0));
+        102, 44, {}, MakeInstructionDescriptor(44, spv::Op::OpStore, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -256,7 +265,8 @@
 
   {
     TransformationAccessChain transformation(
-        103, 13, {80}, MakeInstructionDescriptor(21, SpvOpAccessChain, 0));
+        103, 13, {80},
+        MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -269,7 +279,7 @@
 
   {
     TransformationAccessChain transformation(
-        104, 34, {}, MakeInstructionDescriptor(44, SpvOpStore, 1));
+        104, 34, {}, MakeInstructionDescriptor(44, spv::Op::OpStore, 1));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -282,7 +292,7 @@
 
   {
     TransformationAccessChain transformation(
-        105, 38, {}, MakeInstructionDescriptor(40, SpvOpFunctionCall, 0));
+        105, 38, {}, MakeInstructionDescriptor(40, spv::Op::OpFunctionCall, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -295,7 +305,7 @@
 
   {
     TransformationAccessChain transformation(
-        106, 14, {}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
+        106, 14, {}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -309,7 +319,7 @@
     // Check the case where the access chain's base pointer has the irrelevant
     // pointee fact; the resulting access chain should inherit this fact.
     TransformationAccessChain transformation(
-        107, 54, {}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
+        107, 54, {}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -440,9 +450,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Bad: %9 is a pointer to a struct, but %20 is not a constant.
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 9, {20}, MakeInstructionDescriptor(9, SpvOpReturn, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 9, {20}, MakeInstructionDescriptor(9, spv::Op::OpReturn, 0))
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAccessChainTest, IsomorphicStructs) {
@@ -478,7 +489,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   {
     TransformationAccessChain transformation(
-        100, 11, {}, MakeInstructionDescriptor(5, SpvOpReturn, 0));
+        100, 11, {}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -488,7 +499,7 @@
   }
   {
     TransformationAccessChain transformation(
-        101, 12, {}, MakeInstructionDescriptor(5, SpvOpReturn, 0));
+        101, 12, {}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -587,51 +598,56 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Bad: no ids given for clamping
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 29, {17}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: an id given for clamping is not fresh
   ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+                   100, 29, {17},
+                   MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
                    {{46, 201}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: an id given for clamping is not fresh
   ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+                   100, 29, {17},
+                   MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
                    {{200, 46}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: an id given for clamping is the same as the id for the access chain
   ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+                   100, 29, {17},
+                   MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
                    {{100, 201}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: the fresh ids given are not distinct
   ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+                   100, 29, {17},
+                   MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
                    {{200, 200}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: not enough ids given for clamping (2 pairs needed)
-  ASSERT_FALSE(
-      TransformationAccessChain(104, 34, {45, 10, 46},
-                                MakeInstructionDescriptor(46, SpvOpReturn, 0),
-                                {{208, 209}, {209, 211}})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAccessChain(
+                   104, 34, {45, 10, 46},
+                   MakeInstructionDescriptor(46, spv::Op::OpReturn, 0),
+                   {{208, 209}, {209, 211}})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: the fresh ids given are not distinct
-  ASSERT_FALSE(
-      TransformationAccessChain(104, 34, {45, 10, 46},
-                                MakeInstructionDescriptor(46, SpvOpReturn, 0),
-                                {{208, 209}, {209, 211}})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAccessChain(
+                   104, 34, {45, 10, 46},
+                   MakeInstructionDescriptor(46, spv::Op::OpReturn, 0),
+                   {{208, 209}, {209, 211}})
+                   .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationAccessChain transformation(
-        100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+        100, 29, {17}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
         {{200, 201}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
@@ -643,7 +659,7 @@
 
   {
     TransformationAccessChain transformation(
-        101, 29, {36}, MakeInstructionDescriptor(38, SpvOpLoad, 0),
+        101, 29, {36}, MakeInstructionDescriptor(38, spv::Op::OpLoad, 0),
         {{202, 203}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
@@ -655,7 +671,7 @@
 
   {
     TransformationAccessChain transformation(
-        102, 32, {10, 40}, MakeInstructionDescriptor(42, SpvOpLoad, 0),
+        102, 32, {10, 40}, MakeInstructionDescriptor(42, spv::Op::OpLoad, 0),
         {{204, 205}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
@@ -667,7 +683,7 @@
 
   {
     TransformationAccessChain transformation(
-        103, 34, {11}, MakeInstructionDescriptor(45, SpvOpLoad, 0),
+        103, 34, {11}, MakeInstructionDescriptor(45, spv::Op::OpLoad, 0),
         {{206, 207}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
@@ -679,7 +695,8 @@
 
   {
     TransformationAccessChain transformation(
-        104, 34, {45, 10, 46}, MakeInstructionDescriptor(46, SpvOpReturn, 0),
+        104, 34, {45, 10, 46},
+        MakeInstructionDescriptor(46, spv::Op::OpReturn, 0),
         {{208, 209}, {210, 211}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_boolean_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_boolean_test.cpp
index bd8d91c..bb8817e 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_boolean_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_boolean_test.cpp
@@ -72,7 +72,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(7));
   ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(7));
   ApplyAndCheckFreshIds(add_true, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpConstantTrue, context->get_def_use_mgr()->GetDef(7)->opcode());
+  ASSERT_EQ(spv::Op::OpConstantTrue,
+            context->get_def_use_mgr()->GetDef(7)->opcode());
   ASSERT_TRUE(context->get_constant_mgr()
                   ->FindDeclaredConstant(7)
                   ->AsBoolConstant()
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_composite_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_composite_test.cpp
index e5cbeec..193aa0a 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_composite_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_composite_test.cpp
@@ -91,7 +91,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpConstantComposite,
+    ASSERT_EQ(spv::Op::OpConstantComposite,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_EQ(0.0F, context->get_constant_mgr()
                         ->FindDeclaredConstant(100)
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_null_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_null_test.cpp
index 1553e9f..44e92f8 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_null_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_null_test.cpp
@@ -87,7 +87,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpConstantNull,
+    ASSERT_EQ(spv::Op::OpConstantNull,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_EQ(
         0.0F,
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_scalar_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_scalar_test.cpp
index 00c0541..8c742a4 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_scalar_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_constant_scalar_test.cpp
@@ -179,7 +179,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(19));
   ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(19));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpConstant, context->get_def_use_mgr()->GetDef(19)->opcode());
+  ASSERT_EQ(spv::Op::OpConstant,
+            context->get_def_use_mgr()->GetDef(19)->opcode());
   ASSERT_EQ(4, context->get_constant_mgr()->FindDeclaredConstant(19)->GetU32());
   auto* constant_instruction = context->get_def_use_mgr()->GetDef(19);
   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_copy_memory_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_copy_memory_test.cpp
index ff8ac72..29a936c 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_copy_memory_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_copy_memory_test.cpp
@@ -148,89 +148,89 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Target id is not fresh (59).
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 59, 19,
-                   SpvStorageClassPrivate, 20)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   59, 19, spv::StorageClass::Private, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Instruction descriptor is invalid (id 90 is undefined).
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(90, SpvOpVariable, 0), 90, 19,
-                   SpvStorageClassPrivate, 20)
+                   MakeInstructionDescriptor(90, spv::Op::OpVariable, 0), 90,
+                   19, spv::StorageClass::Private, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert OpCopyMemory before OpPhi.
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(75, SpvOpPhi, 0),
-                                  90, 19, SpvStorageClassPrivate, 20)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(75, spv::Op::OpPhi, 0), 90, 19,
+                   spv::StorageClass::Private, 20)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Source instruction is invalid.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 76,
-                   SpvStorageClassPrivate, 0)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 76, spv::StorageClass::Private, 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Source instruction's type doesn't exist.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 5,
-                   SpvStorageClassPrivate, 0)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 5, spv::StorageClass::Private, 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Source instruction's type is invalid.
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
-                                  90, 40, SpvStorageClassPrivate, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(41, spv::Op::OpLoad, 0), 90, 40,
+                   spv::StorageClass::Private, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Source instruction is OpConstantNull.
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
-                                  90, 88, SpvStorageClassPrivate, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(41, spv::Op::OpLoad, 0), 90, 88,
+                   spv::StorageClass::Private, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Storage class is invalid.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
-                   SpvStorageClassWorkgroup, 20)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 19, spv::StorageClass::Workgroup, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Initializer is 0.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
-                   SpvStorageClassPrivate, 0)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 19, spv::StorageClass::Private, 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Initializer has wrong type.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
-                   SpvStorageClassPrivate, 25)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 19, spv::StorageClass::Private, 25)
                    .IsApplicable(context.get(), transformation_context));
 
   // Source and target instructions are in different functions.
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(13, SpvOpLoad, 0),
-                                  90, 19, SpvStorageClassPrivate, 20)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(13, spv::Op::OpLoad, 0), 90, 19,
+                   spv::StorageClass::Private, 20)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Source instruction doesn't dominate the target instruction.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(77, SpvOpLogicalEqual, 0), 90, 89,
-                   SpvStorageClassPrivate, 20)
+                   MakeInstructionDescriptor(77, spv::Op::OpLogicalEqual, 0),
+                   90, 89, spv::StorageClass::Private, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Source and target instructions are the same.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(19, SpvOpVariable, 0), 90, 19,
-                   SpvStorageClassPrivate, 20)
+                   MakeInstructionDescriptor(19, spv::Op::OpVariable, 0), 90,
+                   19, spv::StorageClass::Private, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Correct transformations.
   uint32_t fresh_id = 90;
-  auto descriptor = MakeInstructionDescriptor(27, SpvOpFunctionCall, 0);
+  auto descriptor = MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0);
   std::vector<uint32_t> source_ids = {19, 23, 26, 30, 35, 39, 68, 86};
   std::vector<uint32_t> initializers = {20, 24, 25, 25, 36, 84, 85, 20};
-  std::vector<SpvStorageClass> storage_classes = {SpvStorageClassPrivate,
-                                                  SpvStorageClassFunction};
+  std::vector<spv::StorageClass> storage_classes = {
+      spv::StorageClass::Private, spv::StorageClass::Function};
   for (size_t i = 0, n = source_ids.size(); i < n; ++i) {
     TransformationAddCopyMemory transformation(
         descriptor, fresh_id, source_ids[i],
@@ -420,10 +420,10 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(5, SpvOpReturn, 0),
-                                  100, 9, SpvStorageClassPrivate, 50)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100, 9,
+                   spv::StorageClass::Private, 50)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddCopyMemoryTest, DisallowBlockDecoration) {
@@ -466,12 +466,12 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(5, SpvOpReturn, 0),
-                                  100, 9, SpvStorageClassPrivate, 50)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100, 9,
+                   spv::StorageClass::Private, 50)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
 }  // namespace fuzz
-}  // namespace spvtools
\ No newline at end of file
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_early_terminator_wrapper_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_early_terminator_wrapper_test.cpp
index 8239e21..8cb04a9 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_early_terminator_wrapper_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_early_terminator_wrapper_test.cpp
@@ -40,8 +40,9 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
 
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpKill)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddEarlyTerminatorWrapper(100, 101, spv::Op::OpKill)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddEarlyTerminatorWrapperTest, NoVoidFunctionType) {
@@ -63,8 +64,9 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
 
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpKill)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddEarlyTerminatorWrapper(100, 101, spv::Op::OpKill)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddEarlyTerminatorWrapperTest, BasicTest) {
@@ -93,25 +95,27 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
 
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(2, 101, SpvOpKill)
+  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(2, 101, spv::Op::OpKill)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 4, SpvOpKill)
+  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 4, spv::Op::OpKill)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 100, SpvOpKill)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddEarlyTerminatorWrapper(100, 100, spv::Op::OpKill)
+          .IsApplicable(context.get(), transformation_context));
 
 #ifndef NDEBUG
-  ASSERT_DEATH(TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpReturn)
-                   .IsApplicable(context.get(), transformation_context),
-               "Invalid opcode.");
+  ASSERT_DEATH(
+      TransformationAddEarlyTerminatorWrapper(100, 101, spv::Op::OpReturn)
+          .IsApplicable(context.get(), transformation_context),
+      "Invalid opcode.");
 #endif
 
   auto transformation1 =
-      TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpKill);
+      TransformationAddEarlyTerminatorWrapper(100, 101, spv::Op::OpKill);
   auto transformation2 =
-      TransformationAddEarlyTerminatorWrapper(102, 103, SpvOpUnreachable);
+      TransformationAddEarlyTerminatorWrapper(102, 103, spv::Op::OpUnreachable);
   auto transformation3 = TransformationAddEarlyTerminatorWrapper(
-      104, 105, SpvOpTerminateInvocation);
+      104, 105, spv::Op::OpTerminateInvocation);
 
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_function_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_function_test.cpp
index d55fb93..65ae2f2 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_function_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_function_test.cpp
@@ -84,7 +84,7 @@
                            &found_non_irrelevant_parameter](
                               opt::Instruction* inst) {
       if (context->get_def_use_mgr()->GetDef(inst->type_id())->opcode() ==
-              SpvOpTypePointer &&
+              spv::Op::OpTypePointer &&
           !transformation_context.GetFactManager()->PointeeValueIsIrrelevant(
               inst->result_id())) {
         found_non_irrelevant_parameter = true;
@@ -96,7 +96,7 @@
     }
     // Look through the instructions in the function's first block.
     for (auto& inst : *function.begin()) {
-      if (inst.opcode() != SpvOpVariable) {
+      if (inst.opcode() != spv::Op::OpVariable) {
         // We have found a non-variable instruction; this means we have gotten
         // past all variables, so we are done.
         return true;
@@ -154,73 +154,84 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationAddFunction transformation1(std::vector<protobufs::Instruction>(
-      {MakeInstructionMessage(
-           SpvOpFunction, 8, 13,
-           {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-            {SPV_OPERAND_TYPE_ID, {10}}}),
-       MakeInstructionMessage(SpvOpFunctionParameter, 7, 11, {}),
-       MakeInstructionMessage(SpvOpFunctionParameter, 9, 12, {}),
-       MakeInstructionMessage(SpvOpLabel, 0, 14, {}),
+      {MakeInstructionMessage(spv::Op::OpFunction, 8, 13,
+                              {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                                {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                               {SPV_OPERAND_TYPE_ID, {10}}}),
+       MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 11, {}),
+       MakeInstructionMessage(spv::Op::OpFunctionParameter, 9, 12, {}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 14, {}),
+       MakeInstructionMessage(spv::Op::OpVariable, 9, 17,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
+       MakeInstructionMessage(spv::Op::OpVariable, 7, 19,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
        MakeInstructionMessage(
-           SpvOpVariable, 9, 17,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpVariable, 7, 19,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {17}}, {SPV_OPERAND_TYPE_ID, {18}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {19}}, {SPV_OPERAND_TYPE_ID, {20}}}),
-       MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {21}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 21, {}),
+       MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {21}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 21, {}),
+       MakeInstructionMessage(spv::Op::OpLoopMerge, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {23}},
+                               {SPV_OPERAND_TYPE_ID, {24}},
+                               {SPV_OPERAND_TYPE_LOOP_CONTROL,
+                                {uint32_t(spv::LoopControlMask::MaskNone)}}}),
+       MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {25}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 25, {}),
+       MakeInstructionMessage(spv::Op::OpLoad, 6, 26,
+                              {{SPV_OPERAND_TYPE_ID, {19}}}),
+       MakeInstructionMessage(spv::Op::OpLoad, 6, 27,
+                              {{SPV_OPERAND_TYPE_ID, {11}}}),
        MakeInstructionMessage(
-           SpvOpLoopMerge, 0, 0,
-           {{SPV_OPERAND_TYPE_ID, {23}},
-            {SPV_OPERAND_TYPE_ID, {24}},
-            {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}),
-       MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {25}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 25, {}),
-       MakeInstructionMessage(SpvOpLoad, 6, 26, {{SPV_OPERAND_TYPE_ID, {19}}}),
-       MakeInstructionMessage(SpvOpLoad, 6, 27, {{SPV_OPERAND_TYPE_ID, {11}}}),
-       MakeInstructionMessage(
-           SpvOpSLessThan, 28, 29,
+           spv::Op::OpSLessThan, 28, 29,
            {{SPV_OPERAND_TYPE_ID, {26}}, {SPV_OPERAND_TYPE_ID, {27}}}),
-       MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+       MakeInstructionMessage(spv::Op::OpBranchConditional, 0, 0,
                               {{SPV_OPERAND_TYPE_ID, {29}},
                                {SPV_OPERAND_TYPE_ID, {22}},
                                {SPV_OPERAND_TYPE_ID, {23}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 22, {}),
-       MakeInstructionMessage(SpvOpLoad, 8, 30, {{SPV_OPERAND_TYPE_ID, {12}}}),
-       MakeInstructionMessage(SpvOpLoad, 6, 31, {{SPV_OPERAND_TYPE_ID, {19}}}),
-       MakeInstructionMessage(SpvOpConvertSToF, 8, 32,
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 22, {}),
+       MakeInstructionMessage(spv::Op::OpLoad, 8, 30,
+                              {{SPV_OPERAND_TYPE_ID, {12}}}),
+       MakeInstructionMessage(spv::Op::OpLoad, 6, 31,
+                              {{SPV_OPERAND_TYPE_ID, {19}}}),
+       MakeInstructionMessage(spv::Op::OpConvertSToF, 8, 32,
                               {{SPV_OPERAND_TYPE_ID, {31}}}),
        MakeInstructionMessage(
-           SpvOpFMul, 8, 33,
+           spv::Op::OpFMul, 8, 33,
            {{SPV_OPERAND_TYPE_ID, {30}}, {SPV_OPERAND_TYPE_ID, {32}}}),
-       MakeInstructionMessage(SpvOpLoad, 8, 34, {{SPV_OPERAND_TYPE_ID, {17}}}),
+       MakeInstructionMessage(spv::Op::OpLoad, 8, 34,
+                              {{SPV_OPERAND_TYPE_ID, {17}}}),
        MakeInstructionMessage(
-           SpvOpFAdd, 8, 35,
+           spv::Op::OpFAdd, 8, 35,
            {{SPV_OPERAND_TYPE_ID, {34}}, {SPV_OPERAND_TYPE_ID, {33}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {17}}, {SPV_OPERAND_TYPE_ID, {35}}}),
-       MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {24}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 24, {}),
-       MakeInstructionMessage(SpvOpLoad, 6, 36, {{SPV_OPERAND_TYPE_ID, {19}}}),
+       MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {24}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 24, {}),
+       MakeInstructionMessage(spv::Op::OpLoad, 6, 36,
+                              {{SPV_OPERAND_TYPE_ID, {19}}}),
        MakeInstructionMessage(
-           SpvOpIAdd, 6, 38,
+           spv::Op::OpIAdd, 6, 38,
            {{SPV_OPERAND_TYPE_ID, {36}}, {SPV_OPERAND_TYPE_ID, {37}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {19}}, {SPV_OPERAND_TYPE_ID, {38}}}),
-       MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {21}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 23, {}),
-       MakeInstructionMessage(SpvOpLoad, 8, 39, {{SPV_OPERAND_TYPE_ID, {17}}}),
-       MakeInstructionMessage(SpvOpReturnValue, 0, 0,
+       MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {21}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 23, {}),
+       MakeInstructionMessage(spv::Op::OpLoad, 8, 39,
+                              {{SPV_OPERAND_TYPE_ID, {17}}}),
+       MakeInstructionMessage(spv::Op::OpReturnValue, 0, 0,
                               {{SPV_OPERAND_TYPE_ID, {39}}}),
-       MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {})}));
+       MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {})}));
 
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
@@ -299,51 +310,51 @@
   ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(25));
 
   TransformationAddFunction transformation2(std::vector<protobufs::Instruction>(
-      {MakeInstructionMessage(
-           SpvOpFunction, 2, 15,
-           {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-            {SPV_OPERAND_TYPE_ID, {3}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 16, {}),
+      {MakeInstructionMessage(spv::Op::OpFunction, 2, 15,
+                              {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                                {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                               {SPV_OPERAND_TYPE_ID, {3}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 16, {}),
+       MakeInstructionMessage(spv::Op::OpVariable, 7, 44,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
+       MakeInstructionMessage(spv::Op::OpVariable, 9, 45,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
+       MakeInstructionMessage(spv::Op::OpVariable, 7, 48,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
+       MakeInstructionMessage(spv::Op::OpVariable, 9, 49,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
        MakeInstructionMessage(
-           SpvOpVariable, 7, 44,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpVariable, 9, 45,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpVariable, 7, 48,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpVariable, 9, 49,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {44}}, {SPV_OPERAND_TYPE_ID, {20}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {45}}, {SPV_OPERAND_TYPE_ID, {18}}}),
-       MakeInstructionMessage(SpvOpFunctionCall, 8, 46,
+       MakeInstructionMessage(spv::Op::OpFunctionCall, 8, 46,
                               {{SPV_OPERAND_TYPE_ID, {13}},
                                {SPV_OPERAND_TYPE_ID, {44}},
                                {SPV_OPERAND_TYPE_ID, {45}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {48}}, {SPV_OPERAND_TYPE_ID, {37}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {49}}, {SPV_OPERAND_TYPE_ID, {47}}}),
-       MakeInstructionMessage(SpvOpFunctionCall, 8, 50,
+       MakeInstructionMessage(spv::Op::OpFunctionCall, 8, 50,
                               {{SPV_OPERAND_TYPE_ID, {13}},
                                {SPV_OPERAND_TYPE_ID, {48}},
                                {SPV_OPERAND_TYPE_ID, {49}}}),
        MakeInstructionMessage(
-           SpvOpFAdd, 8, 51,
+           spv::Op::OpFAdd, 8, 51,
            {{SPV_OPERAND_TYPE_ID, {46}}, {SPV_OPERAND_TYPE_ID, {50}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {43}}, {SPV_OPERAND_TYPE_ID, {51}}}),
-       MakeInstructionMessage(SpvOpReturn, 0, 0, {}),
-       MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {})}));
+       MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}),
+       MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {})}));
 
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
@@ -513,45 +524,46 @@
   ASSERT_FALSE(
       TransformationAddFunction(
           std::vector<protobufs::Instruction>(
-              {MakeInstructionMessage(SpvOpFunctionParameter, 7, 11, {}),
-               MakeInstructionMessage(SpvOpFunctionParameter, 9, 12, {}),
-               MakeInstructionMessage(SpvOpLabel, 0, 14, {})}))
+              {MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 11, {}),
+               MakeInstructionMessage(spv::Op::OpFunctionParameter, 9, 12, {}),
+               MakeInstructionMessage(spv::Op::OpLabel, 0, 14, {})}))
           .IsApplicable(context.get(), transformation_context));
 
   // No OpLabel
   ASSERT_FALSE(
       TransformationAddFunction(
           std::vector<protobufs::Instruction>(
-              {MakeInstructionMessage(SpvOpFunction, 8, 13,
-                                      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
-                                        {SpvFunctionControlMaskNone}},
-                                       {SPV_OPERAND_TYPE_ID, {10}}}),
-               MakeInstructionMessage(SpvOpReturnValue, 0, 0,
+              {MakeInstructionMessage(
+                   spv::Op::OpFunction, 8, 13,
+                   {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                     {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                    {SPV_OPERAND_TYPE_ID, {10}}}),
+               MakeInstructionMessage(spv::Op::OpReturnValue, 0, 0,
                                       {{SPV_OPERAND_TYPE_ID, {39}}}),
-               MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {})}))
+               MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {})}))
           .IsApplicable(context.get(), transformation_context));
 
   // Abrupt end of instructions
   ASSERT_FALSE(TransformationAddFunction(
                    std::vector<protobufs::Instruction>({MakeInstructionMessage(
-                       SpvOpFunction, 8, 13,
+                       spv::Op::OpFunction, 8, 13,
                        {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
-                         {SpvFunctionControlMaskNone}},
+                         {uint32_t(spv::FunctionControlMask::MaskNone)}},
                         {SPV_OPERAND_TYPE_ID, {10}}})}))
                    .IsApplicable(context.get(), transformation_context));
 
   // No function end
-  ASSERT_FALSE(
-      TransformationAddFunction(
-          std::vector<protobufs::Instruction>(
-              {MakeInstructionMessage(SpvOpFunction, 8, 13,
-                                      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
-                                        {SpvFunctionControlMaskNone}},
-                                       {SPV_OPERAND_TYPE_ID, {10}}}),
-               MakeInstructionMessage(SpvOpLabel, 0, 14, {}),
-               MakeInstructionMessage(SpvOpReturnValue, 0, 0,
-                                      {{SPV_OPERAND_TYPE_ID, {39}}})}))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddFunction(
+                   std::vector<protobufs::Instruction>(
+                       {MakeInstructionMessage(
+                            spv::Op::OpFunction, 8, 13,
+                            {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                              {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                             {SPV_OPERAND_TYPE_ID, {10}}}),
+                        MakeInstructionMessage(spv::Op::OpLabel, 0, 14, {}),
+                        MakeInstructionMessage(spv::Op::OpReturnValue, 0, 0,
+                                               {{SPV_OPERAND_TYPE_ID, {39}}})}))
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddFunctionTest, LoopLimiters) {
@@ -581,61 +593,69 @@
   const auto consumer = nullptr;
 
   std::vector<protobufs::Instruction> instructions;
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 30,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 31, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {20}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 20, {}));
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpLoopMerge, 0, 0,
-      {{SPV_OPERAND_TYPE_ID, {21}},
-       {SPV_OPERAND_TYPE_ID, {22}},
-       {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 30,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 31, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {20}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 20, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpLoopMerge, 0, 0,
+                             {{SPV_OPERAND_TYPE_ID, {21}},
+                              {SPV_OPERAND_TYPE_ID, {22}},
+                              {SPV_OPERAND_TYPE_LOOP_CONTROL,
+                               {uint32_t(spv::LoopControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {12}},
                                                  {SPV_OPERAND_TYPE_ID, {23}},
                                                  {SPV_OPERAND_TYPE_ID, {21}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 23, {}));
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpLoopMerge, 0, 0,
-      {{SPV_OPERAND_TYPE_ID, {25}},
-       {SPV_OPERAND_TYPE_ID, {26}},
-       {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 23, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {28}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 28, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+      MakeInstructionMessage(spv::Op::OpLoopMerge, 0, 0,
+                             {{SPV_OPERAND_TYPE_ID, {25}},
+                              {SPV_OPERAND_TYPE_ID, {26}},
+                              {SPV_OPERAND_TYPE_LOOP_CONTROL,
+                               {uint32_t(spv::LoopControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {28}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 28, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {12}},
                                                  {SPV_OPERAND_TYPE_ID, {26}},
                                                  {SPV_OPERAND_TYPE_ID, {25}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 26, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 26, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {23}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 25, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {23}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 25, {}));
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpLoopMerge, 0, 0,
-      {{SPV_OPERAND_TYPE_ID, {24}},
-       {SPV_OPERAND_TYPE_ID, {27}},
-       {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+      MakeInstructionMessage(spv::Op::OpLoopMerge, 0, 0,
+                             {{SPV_OPERAND_TYPE_ID, {24}},
+                              {SPV_OPERAND_TYPE_ID, {27}},
+                              {SPV_OPERAND_TYPE_LOOP_CONTROL,
+                               {uint32_t(spv::LoopControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {12}},
                                                  {SPV_OPERAND_TYPE_ID, {24}},
                                                  {SPV_OPERAND_TYPE_ID, {27}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 27, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 27, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {25}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 24, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {22}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 22, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {20}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 21, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {25}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 24, {}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {22}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 22, {}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {20}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 21, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpReturn, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -837,31 +857,36 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 10,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {8}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 7, 9, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 11, {}));
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 10,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {8}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 12, {{SPV_OPERAND_TYPE_ID, {9}}}));
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 9, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 11, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 12,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpIEqual, 14, 15,
+      spv::Op::OpIEqual, 14, 15,
       {{SPV_OPERAND_TYPE_ID, {12}}, {SPV_OPERAND_TYPE_ID, {13}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpSelectionMerge, 0, 0,
+      spv::Op::OpSelectionMerge, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {17}},
-       {SPV_OPERAND_TYPE_SELECTION_CONTROL, {SpvSelectionControlMaskNone}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+       {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+        {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {15}},
                                                  {SPV_OPERAND_TYPE_ID, {16}},
                                                  {SPV_OPERAND_TYPE_ID, {17}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 16, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpUnreachable, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 17, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpKill, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 16, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpUnreachable, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 17, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpKill, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -996,31 +1021,36 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 6, 10,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {50}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 7, 9, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 11, {}));
+      MakeInstructionMessage(spv::Op::OpFunction, 6, 10,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {50}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 12, {{SPV_OPERAND_TYPE_ID, {9}}}));
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 9, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 11, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 12,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpIEqual, 14, 15,
+      spv::Op::OpIEqual, 14, 15,
       {{SPV_OPERAND_TYPE_ID, {12}}, {SPV_OPERAND_TYPE_ID, {13}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpSelectionMerge, 0, 0,
+      spv::Op::OpSelectionMerge, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {17}},
-       {SPV_OPERAND_TYPE_SELECTION_CONTROL, {SpvSelectionControlMaskNone}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+       {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+        {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {15}},
                                                  {SPV_OPERAND_TYPE_ID, {16}},
                                                  {SPV_OPERAND_TYPE_ID, {17}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 16, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpUnreachable, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 17, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpKill, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 16, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpUnreachable, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 17, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpKill, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -1189,129 +1219,133 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 12,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {8}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 7, 9, {}));
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 12,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {8}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 102, 10, {}));
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 9, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 7, 11, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 13, {}));
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 102, 10, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 11, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 13, {}));
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpVariable, 7, 14,
-      {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpVariable, 26, 27,
-      {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 22, {{SPV_OPERAND_TYPE_ID, {11}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpAccessChain, 23, 24,
+      MakeInstructionMessage(spv::Op::OpVariable, 7, 14,
+                             {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                               {uint32_t(spv::StorageClass::Function)}}}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpVariable, 26, 27,
+                             {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                               {uint32_t(spv::StorageClass::Function)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 22,
+                                                {{SPV_OPERAND_TYPE_ID, {11}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpAccessChain, 23, 24,
                                                 {{SPV_OPERAND_TYPE_ID, {20}},
                                                  {SPV_OPERAND_TYPE_ID, {21}},
                                                  {SPV_OPERAND_TYPE_ID, {22}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 25, {{SPV_OPERAND_TYPE_ID, {24}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 25,
+                                                {{SPV_OPERAND_TYPE_ID, {24}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {14}}, {SPV_OPERAND_TYPE_ID, {25}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 15, 28, {{SPV_OPERAND_TYPE_ID, {10}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 15, 28,
+                                                {{SPV_OPERAND_TYPE_ID, {10}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpAccessChain, 29, 30,
+      spv::Op::OpAccessChain, 29, 30,
       {{SPV_OPERAND_TYPE_ID, {20}}, {SPV_OPERAND_TYPE_ID, {28}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 17, 31, {{SPV_OPERAND_TYPE_ID, {30}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 17, 31,
+                                                {{SPV_OPERAND_TYPE_ID, {30}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {27}}, {SPV_OPERAND_TYPE_ID, {31}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 32, {{SPV_OPERAND_TYPE_ID, {9}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 32,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpInBoundsAccessChain, 7, 34,
+      spv::Op::OpInBoundsAccessChain, 7, 34,
       {{SPV_OPERAND_TYPE_ID, {27}}, {SPV_OPERAND_TYPE_ID, {32}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {34}}, {SPV_OPERAND_TYPE_ID, {33}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 39, {{SPV_OPERAND_TYPE_ID, {9}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 39,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpAccessChain, 23, 40,
+      spv::Op::OpAccessChain, 23, 40,
       {{SPV_OPERAND_TYPE_ID, {38}}, {SPV_OPERAND_TYPE_ID, {33}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 41, {{SPV_OPERAND_TYPE_ID, {40}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 41,
+                                                {{SPV_OPERAND_TYPE_ID, {40}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpInBoundsAccessChain, 23, 42,
+      spv::Op::OpInBoundsAccessChain, 23, 42,
       {{SPV_OPERAND_TYPE_ID, {38}}, {SPV_OPERAND_TYPE_ID, {39}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {42}}, {SPV_OPERAND_TYPE_ID, {41}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 15, 43, {{SPV_OPERAND_TYPE_ID, {10}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 44, {{SPV_OPERAND_TYPE_ID, {11}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 45, {{SPV_OPERAND_TYPE_ID, {9}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 15, 46, {{SPV_OPERAND_TYPE_ID, {10}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 15, 43,
+                                                {{SPV_OPERAND_TYPE_ID, {10}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 44,
+                                                {{SPV_OPERAND_TYPE_ID, {11}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 45,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 15, 46,
+                                                {{SPV_OPERAND_TYPE_ID, {10}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpIAdd, 6, 47,
+      spv::Op::OpIAdd, 6, 47,
       {{SPV_OPERAND_TYPE_ID, {45}}, {SPV_OPERAND_TYPE_ID, {46}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpAccessChain, 23, 48,
+      spv::Op::OpAccessChain, 23, 48,
       {{SPV_OPERAND_TYPE_ID, {38}}, {SPV_OPERAND_TYPE_ID, {47}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 49, {{SPV_OPERAND_TYPE_ID, {48}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpInBoundsAccessChain, 23,
-                                                50,
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 49,
+                                                {{SPV_OPERAND_TYPE_ID, {48}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpInBoundsAccessChain,
+                                                23, 50,
                                                 {{SPV_OPERAND_TYPE_ID, {20}},
                                                  {SPV_OPERAND_TYPE_ID, {43}},
                                                  {SPV_OPERAND_TYPE_ID, {44}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 51, {{SPV_OPERAND_TYPE_ID, {50}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 51,
+                                                {{SPV_OPERAND_TYPE_ID, {50}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpIAdd, 6, 52,
+      spv::Op::OpIAdd, 6, 52,
       {{SPV_OPERAND_TYPE_ID, {51}}, {SPV_OPERAND_TYPE_ID, {49}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpAccessChain, 23, 53,
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpAccessChain, 23, 53,
                                                 {{SPV_OPERAND_TYPE_ID, {20}},
                                                  {SPV_OPERAND_TYPE_ID, {43}},
                                                  {SPV_OPERAND_TYPE_ID, {44}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {53}}, {SPV_OPERAND_TYPE_ID, {52}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 15, 58, {{SPV_OPERAND_TYPE_ID, {10}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 63, {{SPV_OPERAND_TYPE_ID, {11}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpAccessChain, 64, 65,
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 15, 58,
+                                                {{SPV_OPERAND_TYPE_ID, {10}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 63,
+                                                {{SPV_OPERAND_TYPE_ID, {11}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpAccessChain, 64, 65,
                                                 {{SPV_OPERAND_TYPE_ID, {62}},
                                                  {SPV_OPERAND_TYPE_ID, {21}},
                                                  {SPV_OPERAND_TYPE_ID, {63}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpAccessChain, 64, 101,
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpAccessChain, 64, 101,
                                                 {{SPV_OPERAND_TYPE_ID, {62}},
                                                  {SPV_OPERAND_TYPE_ID, {45}},
                                                  {SPV_OPERAND_TYPE_ID, {46}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 54, 66, {{SPV_OPERAND_TYPE_ID, {65}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 54, 66,
+                                                {{SPV_OPERAND_TYPE_ID, {65}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpAccessChain, 64, 67,
+      spv::Op::OpAccessChain, 64, 67,
       {{SPV_OPERAND_TYPE_ID, {57}}, {SPV_OPERAND_TYPE_ID, {58}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {67}}, {SPV_OPERAND_TYPE_ID, {66}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 68, {{SPV_OPERAND_TYPE_ID, {9}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 68,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpInBoundsAccessChain, 64, 70,
+      spv::Op::OpInBoundsAccessChain, 64, 70,
       {{SPV_OPERAND_TYPE_ID, {57}}, {SPV_OPERAND_TYPE_ID, {68}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {70}}, {SPV_OPERAND_TYPE_ID, {69}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpReturn, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -1634,15 +1668,17 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 8,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 9, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionCall, 2, 11,
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 8,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 9, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpFunctionCall, 2, 11,
                                                 {{SPV_OPERAND_TYPE_ID, {6}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpReturn, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -1738,15 +1774,17 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 8,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 9, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionCall, 2, 11,
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 8,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 9, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpFunctionCall, 2, 11,
                                                 {{SPV_OPERAND_TYPE_ID, {6}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpReturn, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_global_undef_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_global_undef_test.cpp
index 03b9157..b87970f 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_global_undef_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_global_undef_test.cpp
@@ -71,7 +71,8 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpUndef, context->get_def_use_mgr()->GetDef(100)->opcode());
+    ASSERT_EQ(spv::Op::OpUndef,
+              context->get_def_use_mgr()->GetDef(100)->opcode());
   }
 
   TransformationAddGlobalUndef transformations[] = {
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_global_variable_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_global_variable_test.cpp
index 9531ade..fc452df 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_global_variable_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_global_variable_test.cpp
@@ -66,94 +66,95 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Id already in use
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(4, 10, SpvStorageClassPrivate, 0, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   4, 10, spv::StorageClass::Private, 0, true)
+                   .IsApplicable(context.get(), transformation_context));
   // %1 is not a type
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 1, SpvStorageClassPrivate, 0, false)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 1, spv::StorageClass::Private, 0, false)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %7 is not a pointer type
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 7, SpvStorageClassPrivate, 0, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 7, spv::StorageClass::Private, 0, true)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %9 does not have Private storage class
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 9, SpvStorageClassPrivate, 0, false)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 9, spv::StorageClass::Private, 0, false)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %15 does not have Private storage class
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 15, SpvStorageClassPrivate, 0, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 15, spv::StorageClass::Private, 0, true)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %10 is a pointer to float, while %16 is an int constant
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 10, SpvStorageClassPrivate,
-                                               16, false)
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 10, spv::StorageClass::Private, 16, false)
                    .IsApplicable(context.get(), transformation_context));
 
   // %10 is a Private pointer to float, while %15 is a variable with type
   // Uniform float pointer
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 10, SpvStorageClassPrivate, 15, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 10, spv::StorageClass::Private, 15, true)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %12 is a Private pointer to int, while %10 is a variable with type
   // Private float pointer
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate,
-                                               10, false)
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 12, spv::StorageClass::Private, 10, false)
                    .IsApplicable(context.get(), transformation_context));
 
   // %10 is pointer-to-float, and %14 has type pointer-to-float; that's not OK
   // since the initializer's type should be the *pointee* type.
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(104, 10, SpvStorageClassPrivate, 14, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   104, 10, spv::StorageClass::Private, 14, true)
+                   .IsApplicable(context.get(), transformation_context));
 
   // This would work in principle, but logical addressing does not allow
   // a pointer to a pointer.
-  ASSERT_FALSE(TransformationAddGlobalVariable(104, 17, SpvStorageClassPrivate,
-                                               14, false)
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   104, 17, spv::StorageClass::Private, 14, false)
                    .IsApplicable(context.get(), transformation_context));
 
   {
     // %100 = OpVariable %12 Private
     ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
     TransformationAddGlobalVariable transformation(
-        100, 12, SpvStorageClassPrivate, 16, true);
+        100, 12, spv::StorageClass::Private, 16, true);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpVariable, context->get_def_use_mgr()->GetDef(100)->opcode());
+    ASSERT_EQ(spv::Op::OpVariable,
+              context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_EQ(
-        SpvStorageClassPrivate,
-        static_cast<SpvStorageClass>(
+        spv::StorageClass::Private,
+        static_cast<spv::StorageClass>(
             context->get_def_use_mgr()->GetDef(100)->GetSingleWordInOperand(
                 0)));
   }
 
   TransformationAddGlobalVariable transformations[] = {
       // %101 = OpVariable %10 Private
-      TransformationAddGlobalVariable(101, 10, SpvStorageClassPrivate, 40,
+      TransformationAddGlobalVariable(101, 10, spv::StorageClass::Private, 40,
                                       false),
 
       // %102 = OpVariable %13 Private
-      TransformationAddGlobalVariable(102, 13, SpvStorageClassPrivate, 41,
+      TransformationAddGlobalVariable(102, 13, spv::StorageClass::Private, 41,
                                       true),
 
       // %103 = OpVariable %12 Private %16
-      TransformationAddGlobalVariable(103, 12, SpvStorageClassPrivate, 16,
+      TransformationAddGlobalVariable(103, 12, spv::StorageClass::Private, 16,
                                       false),
 
       // %104 = OpVariable %19 Private %21
-      TransformationAddGlobalVariable(104, 19, SpvStorageClassPrivate, 21,
+      TransformationAddGlobalVariable(104, 19, spv::StorageClass::Private, 21,
                                       true),
 
       // %105 = OpVariable %19 Private %22
-      TransformationAddGlobalVariable(105, 19, SpvStorageClassPrivate, 22,
+      TransformationAddGlobalVariable(105, 19, spv::StorageClass::Private, 22,
                                       false)};
 
   for (auto& transformation : transformations) {
@@ -269,15 +270,15 @@
         MakeUnique<FactManager>(context.get()), validator_options);
     TransformationAddGlobalVariable transformations[] = {
         // %100 = OpVariable %12 Private
-        TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+        TransformationAddGlobalVariable(100, 12, spv::StorageClass::Private, 16,
                                         true),
 
         // %101 = OpVariable %12 Private %16
-        TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
+        TransformationAddGlobalVariable(101, 12, spv::StorageClass::Private, 16,
                                         false),
 
         // %102 = OpVariable %19 Private %21
-        TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
+        TransformationAddGlobalVariable(102, 19, spv::StorageClass::Private, 21,
                                         true)};
 
     for (auto& transformation : transformations) {
@@ -388,15 +389,15 @@
         MakeUnique<FactManager>(context.get()), validator_options);
     TransformationAddGlobalVariable transformations[] = {
         // %100 = OpVariable %12 Private
-        TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+        TransformationAddGlobalVariable(100, 12, spv::StorageClass::Private, 16,
                                         true),
 
         // %101 = OpVariable %12 Private %16
-        TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
+        TransformationAddGlobalVariable(101, 12, spv::StorageClass::Private, 16,
                                         false),
 
         // %102 = OpVariable %19 Private %21
-        TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
+        TransformationAddGlobalVariable(102, 19, spv::StorageClass::Private, 21,
                                         true)};
 
     for (auto& transformation : transformations) {
@@ -486,7 +487,8 @@
       MakeUnique<FactManager>(context.get()), validator_options);
 #ifndef NDEBUG
   ASSERT_DEATH(
-      TransformationAddGlobalVariable(8, 7, SpvStorageClassWorkgroup, 50, true)
+      TransformationAddGlobalVariable(8, 7, spv::StorageClass::Workgroup, 50,
+                                      true)
           .IsApplicable(context.get(), transformation_context),
       "By construction this transformation should not have an.*initializer "
       "when Workgroup storage class is used");
@@ -494,10 +496,11 @@
 
   TransformationAddGlobalVariable transformations[] = {
       // %8 = OpVariable %7 Workgroup
-      TransformationAddGlobalVariable(8, 7, SpvStorageClassWorkgroup, 0, true),
+      TransformationAddGlobalVariable(8, 7, spv::StorageClass::Workgroup, 0,
+                                      true),
 
       // %10 = OpVariable %7 Workgroup
-      TransformationAddGlobalVariable(10, 7, SpvStorageClassWorkgroup, 0,
+      TransformationAddGlobalVariable(10, 7, spv::StorageClass::Workgroup, 0,
                                       false)};
 
   for (auto& transformation : transformations) {
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_image_sample_unused_components_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_image_sample_unused_components_test.cpp
index 072378c..7047544 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_image_sample_unused_components_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_image_sample_unused_components_test.cpp
@@ -73,14 +73,14 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests applicable image instruction.
   auto instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   auto transformation =
       TransformationAddImageSampleUnusedComponents(23, instruction_descriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(26, SpvOpImageSampleExplicitLod, 0);
+      MakeInstructionDescriptor(26, spv::Op::OpImageSampleExplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(24, instruction_descriptor);
   ASSERT_TRUE(
@@ -88,27 +88,27 @@
 
   // Tests undefined image instructions.
   instruction_descriptor =
-      MakeInstructionDescriptor(27, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(27, spv::Op::OpImageSampleImplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(23, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(28, SpvOpImageSampleExplicitLod, 0);
+      MakeInstructionDescriptor(28, spv::Op::OpImageSampleExplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(23, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests non-image instructions.
-  instruction_descriptor = MakeInstructionDescriptor(19, SpvOpLabel, 0);
+  instruction_descriptor = MakeInstructionDescriptor(19, spv::Op::OpLabel, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(24, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(20, SpvOpLoad, 0);
+  instruction_descriptor = MakeInstructionDescriptor(20, spv::Op::OpLoad, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(24, instruction_descriptor);
   ASSERT_FALSE(
@@ -116,7 +116,7 @@
 
   // Tests coordinate operand being a vec4.
   instruction_descriptor =
-      MakeInstructionDescriptor(27, SpvOpImageSampleExplicitLod, 0);
+      MakeInstructionDescriptor(27, spv::Op::OpImageSampleExplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(22, instruction_descriptor);
   ASSERT_FALSE(
@@ -124,7 +124,7 @@
 
   // Tests undefined coordinate with unused operands.
   instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(27, instruction_descriptor);
   ASSERT_FALSE(
@@ -133,7 +133,7 @@
   // Tests coordinate with unused operands being a non-OpCompositeConstruct
   // instruction.
   instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(21, instruction_descriptor);
   ASSERT_FALSE(
@@ -142,7 +142,7 @@
   // Tests the first OpCompositeConstruct constituent not being the original
   // coordinate.
   instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(22, instruction_descriptor);
   ASSERT_FALSE(
@@ -198,13 +198,13 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   auto transformation =
       TransformationAddImageSampleUnusedComponents(23, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(26, SpvOpImageSampleExplicitLod, 0);
+      MakeInstructionDescriptor(26, spv::Op::OpImageSampleExplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(24, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_local_variable_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_local_variable_test.cpp
index de88573..2af8597 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_local_variable_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_local_variable_test.cpp
@@ -104,7 +104,8 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpVariable, context->get_def_use_mgr()->GetDef(105)->opcode());
+    ASSERT_EQ(spv::Op::OpVariable,
+              context->get_def_use_mgr()->GetDef(105)->opcode());
     ASSERT_EQ(5, context->get_instr_block(105)->id());
   }
 
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_opphi_synonym_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_opphi_synonym_test.cpp
index 3501f8e..4aca30c 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_opphi_synonym_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_opphi_synonym_test.cpp
@@ -366,7 +366,7 @@
 
   // Remove the VariablePointers capability.
   context.get()->get_feature_mgr()->RemoveCapability(
-      SpvCapabilityVariablePointers);
+      spv::Capability::VariablePointers);
 
   // The VariablePointers capability is required to add an OpPhi instruction of
   // pointer type.
@@ -375,7 +375,7 @@
 
   // Add the VariablePointers capability back.
   context.get()->get_feature_mgr()->AddCapability(
-      SpvCapabilityVariablePointers);
+      spv::Capability::VariablePointers);
 
   // If the ids have pointer type, the storage class must be Workgroup or
   // StorageBuffer, but it is Function in this case.
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_synonym_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_synonym_test.cpp
index ffcf1c9..385590e 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_synonym_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_synonym_test.cpp
@@ -77,7 +77,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(24);
 
-  auto insert_before = MakeInstructionDescriptor(22, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(22, spv::Op::OpReturn, 0);
 
 #ifndef NDEBUG
   ASSERT_DEATH(
@@ -126,34 +126,34 @@
                      .IsApplicable(context.get(), transformation_context));
 
     // |insert_before| is invalid.
-    ASSERT_FALSE(
-        TransformationAddSynonym(9, synonym_type, 40,
-                                 MakeInstructionDescriptor(25, SpvOpStore, 0))
-            .IsApplicable(context.get(), transformation_context));
-
-    // Can't insert before |insert_before|.
-    ASSERT_FALSE(
-        TransformationAddSynonym(9, synonym_type, 40,
-                                 MakeInstructionDescriptor(5, SpvOpLabel, 0))
-            .IsApplicable(context.get(), transformation_context));
     ASSERT_FALSE(TransformationAddSynonym(
                      9, synonym_type, 40,
-                     MakeInstructionDescriptor(22, SpvOpVariable, 0))
+                     MakeInstructionDescriptor(25, spv::Op::OpStore, 0))
+                     .IsApplicable(context.get(), transformation_context));
+
+    // Can't insert before |insert_before|.
+    ASSERT_FALSE(TransformationAddSynonym(
+                     9, synonym_type, 40,
+                     MakeInstructionDescriptor(5, spv::Op::OpLabel, 0))
                      .IsApplicable(context.get(), transformation_context));
     ASSERT_FALSE(TransformationAddSynonym(
                      9, synonym_type, 40,
-                     MakeInstructionDescriptor(25, SpvOpFunctionEnd, 0))
+                     MakeInstructionDescriptor(22, spv::Op::OpVariable, 0))
+                     .IsApplicable(context.get(), transformation_context));
+    ASSERT_FALSE(TransformationAddSynonym(
+                     9, synonym_type, 40,
+                     MakeInstructionDescriptor(25, spv::Op::OpFunctionEnd, 0))
                      .IsApplicable(context.get(), transformation_context));
 
     // Domination rules are not satisfied.
-    ASSERT_FALSE(
-        TransformationAddSynonym(27, synonym_type, 40,
-                                 MakeInstructionDescriptor(27, SpvOpLoad, 0))
-            .IsApplicable(context.get(), transformation_context));
-    ASSERT_FALSE(
-        TransformationAddSynonym(27, synonym_type, 40,
-                                 MakeInstructionDescriptor(22, SpvOpStore, 1))
-            .IsApplicable(context.get(), transformation_context));
+    ASSERT_FALSE(TransformationAddSynonym(
+                     27, synonym_type, 40,
+                     MakeInstructionDescriptor(27, spv::Op::OpLoad, 0))
+                     .IsApplicable(context.get(), transformation_context));
+    ASSERT_FALSE(TransformationAddSynonym(
+                     27, synonym_type, 40,
+                     MakeInstructionDescriptor(22, spv::Op::OpStore, 1))
+                     .IsApplicable(context.get(), transformation_context));
   }
 }
 
@@ -212,7 +212,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
 
   uint32_t fresh_id = 50;
   for (auto synonym_type : {protobufs::TransformationAddSynonym::ADD_ZERO,
@@ -374,7 +374,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
 
   uint32_t fresh_id = 50;
   for (auto synonym_type : {protobufs::TransformationAddSynonym::LOGICAL_AND,
@@ -467,7 +467,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
   const auto synonym_type = protobufs::TransformationAddSynonym::LOGICAL_AND;
 
   // Required constant is not present in the module.
@@ -505,7 +505,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
   const auto synonym_type = protobufs::TransformationAddSynonym::LOGICAL_OR;
 
   // Required constant is not present in the module.
@@ -563,7 +563,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
   const auto synonym_type = protobufs::TransformationAddSynonym::COPY_OBJECT;
 
   ASSERT_FALSE(
@@ -666,7 +666,7 @@
   {
     TransformationAddSynonym copy_true(
         7, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
-        MakeInstructionDescriptor(5, SpvOpReturn, 0));
+        MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
     ASSERT_TRUE(copy_true.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(copy_true, context.get(), &transformation_context);
 
@@ -687,7 +687,7 @@
   {
     TransformationAddSynonym copy_false(
         8, protobufs::TransformationAddSynonym::COPY_OBJECT, 101,
-        MakeInstructionDescriptor(100, SpvOpReturn, 0));
+        MakeInstructionDescriptor(100, spv::Op::OpReturn, 0));
     ASSERT_TRUE(copy_false.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(copy_false, context.get(), &transformation_context);
     std::vector<uint32_t> ids_for_which_synonyms_are_known =
@@ -707,7 +707,7 @@
   {
     TransformationAddSynonym copy_false_again(
         101, protobufs::TransformationAddSynonym::COPY_OBJECT, 102,
-        MakeInstructionDescriptor(5, SpvOpReturn, 0));
+        MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         copy_false_again.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(copy_false_again, context.get(),
@@ -730,7 +730,7 @@
   {
     TransformationAddSynonym copy_true_again(
         7, protobufs::TransformationAddSynonym::COPY_OBJECT, 103,
-        MakeInstructionDescriptor(102, SpvOpReturn, 0));
+        MakeInstructionDescriptor(102, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         copy_true_again.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(copy_true_again, context.get(),
@@ -970,128 +970,133 @@
   // Inapplicable because %18 is decorated.
   ASSERT_FALSE(TransformationAddSynonym(
                    18, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(21, SpvOpAccessChain, 0))
+                   MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %77 is decorated.
   ASSERT_FALSE(TransformationAddSynonym(
                    77, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(77, SpvOpBranch, 0))
+                   MakeInstructionDescriptor(77, spv::Op::OpBranch, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %80 is decorated.
   ASSERT_FALSE(TransformationAddSynonym(
                    80, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(77, SpvOpIAdd, 0))
+                   MakeInstructionDescriptor(77, spv::Op::OpIAdd, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %84 is not available at the requested point
-  ASSERT_FALSE(TransformationAddSynonym(
-                   84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(32, SpvOpCompositeExtract, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddSynonym(
+          84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+          MakeInstructionDescriptor(32, spv::Op::OpCompositeExtract, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Fine because %84 is available at the requested point
-  ASSERT_TRUE(TransformationAddSynonym(
-                  84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0))
-                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(
+      TransformationAddSynonym(
+          84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+          MakeInstructionDescriptor(32, spv::Op::OpCompositeConstruct, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because id %9 is already in use
-  ASSERT_FALSE(TransformationAddSynonym(
-                   84, protobufs::TransformationAddSynonym::COPY_OBJECT, 9,
-                   MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddSynonym(
+          84, protobufs::TransformationAddSynonym::COPY_OBJECT, 9,
+          MakeInstructionDescriptor(32, spv::Op::OpCompositeConstruct, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the requested point does not exist
   ASSERT_FALSE(TransformationAddSynonym(
                    84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(86, SpvOpReturn, 2))
+                   MakeInstructionDescriptor(86, spv::Op::OpReturn, 2))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %9 is not in a function
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(9, SpvOpTypeInt, 0))
+                   MakeInstructionDescriptor(9, spv::Op::OpTypeInt, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right before, or inside, a chunk
   // of OpPhis
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(30, SpvOpPhi, 0))
+                   MakeInstructionDescriptor(30, spv::Op::OpPhi, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(99, SpvOpPhi, 1))
+                   MakeInstructionDescriptor(99, spv::Op::OpPhi, 1))
                    .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is just after a chunk of OpPhis.
   ASSERT_TRUE(TransformationAddSynonym(
                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(96, SpvOpAccessChain, 0))
+                  MakeInstructionDescriptor(96, spv::Op::OpAccessChain, 0))
+                  .IsApplicable(context.get(), transformation_context));
+
+  // Inapplicable because the insert point is right after an OpSelectionMerge
+  ASSERT_FALSE(
+      TransformationAddSynonym(
+          9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+          MakeInstructionDescriptor(58, spv::Op::OpBranchConditional, 0))
+          .IsApplicable(context.get(), transformation_context));
+
+  // OK, because the insert point is right before the OpSelectionMerge
+  ASSERT_TRUE(TransformationAddSynonym(
+                  9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+                  MakeInstructionDescriptor(58, spv::Op::OpSelectionMerge, 0))
                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right after an OpSelectionMerge
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(58, SpvOpBranchConditional, 0))
+                   MakeInstructionDescriptor(43, spv::Op::OpSwitch, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is right before the OpSelectionMerge
   ASSERT_TRUE(TransformationAddSynonym(
                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(58, SpvOpSelectionMerge, 0))
-                  .IsApplicable(context.get(), transformation_context));
-
-  // Inapplicable because the insert point is right after an OpSelectionMerge
-  ASSERT_FALSE(TransformationAddSynonym(
-                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(43, SpvOpSwitch, 0))
-                   .IsApplicable(context.get(), transformation_context));
-
-  // OK, because the insert point is right before the OpSelectionMerge
-  ASSERT_TRUE(TransformationAddSynonym(
-                  9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(43, SpvOpSelectionMerge, 0))
+                  MakeInstructionDescriptor(43, spv::Op::OpSelectionMerge, 0))
                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right after an OpLoopMerge
-  ASSERT_FALSE(TransformationAddSynonym(
-                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(40, SpvOpBranchConditional, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddSynonym(
+          9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+          MakeInstructionDescriptor(40, spv::Op::OpBranchConditional, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is right before the OpLoopMerge
   ASSERT_TRUE(TransformationAddSynonym(
                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(40, SpvOpLoopMerge, 0))
+                  MakeInstructionDescriptor(40, spv::Op::OpLoopMerge, 0))
                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because id %300 does not exist
   ASSERT_FALSE(TransformationAddSynonym(
                    300, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(40, SpvOpLoopMerge, 0))
+                   MakeInstructionDescriptor(40, spv::Op::OpLoopMerge, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the following instruction is OpVariable
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(180, SpvOpVariable, 0))
+                   MakeInstructionDescriptor(180, spv::Op::OpVariable, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(181, SpvOpVariable, 0))
+                   MakeInstructionDescriptor(181, spv::Op::OpVariable, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(182, SpvOpVariable, 0))
+                   MakeInstructionDescriptor(182, spv::Op::OpVariable, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // OK, because this is just past the group of OpVariable instructions.
   ASSERT_TRUE(TransformationAddSynonym(
                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(182, SpvOpAccessChain, 0))
+                  MakeInstructionDescriptor(182, spv::Op::OpAccessChain, 0))
                   .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1163,25 +1168,25 @@
   std::vector<TransformationAddSynonym> transformations = {
       TransformationAddSynonym(
           19, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
-          MakeInstructionDescriptor(22, SpvOpStore, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpStore, 0)),
       TransformationAddSynonym(
           22, protobufs::TransformationAddSynonym::COPY_OBJECT, 101,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           12, protobufs::TransformationAddSynonym::COPY_OBJECT, 102,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           11, protobufs::TransformationAddSynonym::COPY_OBJECT, 103,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           16, protobufs::TransformationAddSynonym::COPY_OBJECT, 104,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           8, protobufs::TransformationAddSynonym::COPY_OBJECT, 105,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           17, protobufs::TransformationAddSynonym::COPY_OBJECT, 106,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0))};
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0))};
 
   for (auto& transformation : transformations) {
     ASSERT_TRUE(
@@ -1273,7 +1278,7 @@
   // Illegal to copy null.
   ASSERT_FALSE(TransformationAddSynonym(
                    8, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
-                   MakeInstructionDescriptor(5, SpvOpReturn, 0))
+                   MakeInstructionDescriptor(5, spv::Op::OpReturn, 0))
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1312,13 +1317,13 @@
 
   TransformationAddSynonym transformation1(
       8, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
-      MakeInstructionDescriptor(9, SpvOpReturn, 0));
+      MakeInstructionDescriptor(9, spv::Op::OpReturn, 0));
   TransformationAddSynonym transformation2(
       9, protobufs::TransformationAddSynonym::COPY_OBJECT, 101,
-      MakeInstructionDescriptor(9, SpvOpReturn, 0));
+      MakeInstructionDescriptor(9, spv::Op::OpReturn, 0));
   TransformationAddSynonym transformation3(
       100, protobufs::TransformationAddSynonym::COPY_OBJECT, 102,
-      MakeInstructionDescriptor(9, SpvOpReturn, 0));
+      MakeInstructionDescriptor(9, spv::Op::OpReturn, 0));
 
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
@@ -1397,7 +1402,7 @@
   ASSERT_FALSE(
       TransformationAddSynonym(
           216, protobufs::TransformationAddSynonym::COPY_OBJECT, 500,
-          MakeInstructionDescriptor(217, SpvOpImageSampleImplicitLod, 0))
+          MakeInstructionDescriptor(217, spv::Op::OpImageSampleImplicitLod, 0))
           .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1434,7 +1439,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   ASSERT_FALSE(TransformationAddSynonym(
                    8, protobufs::TransformationAddSynonym::COPY_OBJECT, 500,
-                   MakeInstructionDescriptor(8, SpvOpReturn, 0))
+                   MakeInstructionDescriptor(8, spv::Op::OpReturn, 0))
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1475,7 +1480,7 @@
 
   transformation_context.GetFactManager()->AddFactBlockIsDead(9);
 
-  auto insert_before = MakeInstructionDescriptor(9, SpvOpBranch, 0);
+  auto insert_before = MakeInstructionDescriptor(9, spv::Op::OpBranch, 0);
 
   ASSERT_FALSE(TransformationAddSynonym(
                    7, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_array_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_array_test.cpp
index 2ef8200..ab480fb 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_array_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_array_test.cpp
@@ -99,7 +99,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeArray,
+    ASSERT_EQ(spv::Op::OpTypeArray,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsArray());
   }
@@ -113,7 +113,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeArray,
+    ASSERT_EQ(spv::Op::OpTypeArray,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsArray());
   }
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_boolean_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_boolean_test.cpp
index a8e657b..388d4f6 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_boolean_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_boolean_test.cpp
@@ -57,7 +57,8 @@
   ASSERT_TRUE(
       add_type_bool.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(add_type_bool, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeBool, context->get_def_use_mgr()->GetDef(100)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeBool,
+            context->get_def_use_mgr()->GetDef(100)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsBool());
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_float_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_float_test.cpp
index 9275bec..75f3788 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_float_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_float_test.cpp
@@ -74,7 +74,7 @@
 
   // By default, SPIR-V does not support 64-bit float types.
   // Below we add such capability, so the test should now pass.
-  context.get()->get_feature_mgr()->AddCapability(SpvCapabilityFloat64);
+  context.get()->get_feature_mgr()->AddCapability(spv::Capability::Float64);
   ASSERT_TRUE(TransformationAddTypeFloat(7, 64).IsApplicable(
       context.get(), transformation_context));
 
@@ -120,7 +120,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(6));
   ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(6));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(6)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeFloat,
+            context->get_def_use_mgr()->GetDef(6)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(6)->AsFloat());
 
   // Adds 32-bit float type.
@@ -128,7 +129,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(7));
   ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(7));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(7)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeFloat,
+            context->get_def_use_mgr()->GetDef(7)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(7)->AsFloat());
 
   // Adds 64-bit float type.
@@ -136,7 +138,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(8));
   ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(8));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(8)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeFloat,
+            context->get_def_use_mgr()->GetDef(8)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(8)->AsFloat());
 
   std::string variant_shader = R"(
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_int_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_int_test.cpp
index 4cbfed0..b41d420 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_int_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_int_test.cpp
@@ -88,13 +88,13 @@
 
   // By default SPIR-V does not support 16-bit integers.
   // Below we add such capability, so the test should now be successful.
-  context.get()->get_feature_mgr()->AddCapability(SpvCapabilityInt16);
+  context.get()->get_feature_mgr()->AddCapability(spv::Capability::Int16);
   ASSERT_TRUE(TransformationAddTypeInt(7, 16, true)
                   .IsApplicable(context.get(), transformation_context));
 
   // By default SPIR-V does not support 64-bit integers.
   // Below we add such capability, so the test should now pass.
-  context.get()->get_feature_mgr()->AddCapability(SpvCapabilityInt64);
+  context.get()->get_feature_mgr()->AddCapability(spv::Capability::Int64);
   ASSERT_TRUE(TransformationAddTypeInt(7, 64, true)
                   .IsApplicable(context.get(), transformation_context));
 
@@ -147,7 +147,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(6));
   ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(6));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeInt, context->get_def_use_mgr()->GetDef(6)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeInt,
+            context->get_def_use_mgr()->GetDef(6)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(6)->AsInteger());
 
   // Adds signed 16-bit integer type.
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_matrix_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_matrix_test.cpp
index df0111e..9b10dbd 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_matrix_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_matrix_test.cpp
@@ -72,7 +72,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeMatrix,
+    ASSERT_EQ(spv::Op::OpTypeMatrix,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsMatrix());
   }
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_pointer_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_pointer_test.cpp
index b9072e3..5e25f0e 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_pointer_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_pointer_test.cpp
@@ -103,28 +103,28 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto bad_type_id_does_not_exist =
-      TransformationAddTypePointer(100, SpvStorageClassFunction, 101);
+      TransformationAddTypePointer(100, spv::StorageClass::Function, 101);
   auto bad_type_id_is_not_type =
-      TransformationAddTypePointer(100, SpvStorageClassFunction, 23);
+      TransformationAddTypePointer(100, spv::StorageClass::Function, 23);
   auto bad_result_id_is_not_fresh =
-      TransformationAddTypePointer(17, SpvStorageClassFunction, 21);
+      TransformationAddTypePointer(17, spv::StorageClass::Function, 21);
 
   auto good_new_private_pointer_to_t =
-      TransformationAddTypePointer(101, SpvStorageClassPrivate, 7);
+      TransformationAddTypePointer(101, spv::StorageClass::Private, 7);
   auto good_new_uniform_pointer_to_t =
-      TransformationAddTypePointer(102, SpvStorageClassUniform, 7);
+      TransformationAddTypePointer(102, spv::StorageClass::Uniform, 7);
   auto good_another_function_pointer_to_s =
-      TransformationAddTypePointer(103, SpvStorageClassFunction, 8);
+      TransformationAddTypePointer(103, spv::StorageClass::Function, 8);
   auto good_new_uniform_pointer_to_s =
-      TransformationAddTypePointer(104, SpvStorageClassUniform, 8);
+      TransformationAddTypePointer(104, spv::StorageClass::Uniform, 8);
   auto good_another_private_pointer_to_float =
-      TransformationAddTypePointer(105, SpvStorageClassPrivate, 21);
+      TransformationAddTypePointer(105, spv::StorageClass::Private, 21);
   auto good_new_private_pointer_to_private_pointer_to_float =
-      TransformationAddTypePointer(106, SpvStorageClassPrivate, 105);
+      TransformationAddTypePointer(106, spv::StorageClass::Private, 105);
   auto good_new_uniform_pointer_to_vec2 =
-      TransformationAddTypePointer(107, SpvStorageClassUniform, 24);
+      TransformationAddTypePointer(107, spv::StorageClass::Uniform, 24);
   auto good_new_private_pointer_to_uniform_pointer_to_vec2 =
-      TransformationAddTypePointer(108, SpvStorageClassPrivate, 107);
+      TransformationAddTypePointer(108, spv::StorageClass::Private, 107);
 
   ASSERT_FALSE(bad_type_id_does_not_exist.IsApplicable(context.get(),
                                                        transformation_context));
@@ -143,7 +143,7 @@
                           &transformation_context);
     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
         context.get(), validator_options, kConsoleMessageConsumer));
-    ASSERT_EQ(SpvOpTypePointer,
+    ASSERT_EQ(spv::Op::OpTypePointer,
               context->get_def_use_mgr()->GetDef(101)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(101)->AsPointer());
   }
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_struct_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_struct_test.cpp
index 7fb91ab..1440b4a 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_struct_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_struct_test.cpp
@@ -72,7 +72,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeStruct,
+    ASSERT_EQ(spv::Op::OpTypeStruct,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsStruct());
   }
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_vector_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_vector_test.cpp
index 755bc4a..b39c1c9 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_vector_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_add_type_vector_test.cpp
@@ -66,7 +66,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeVector,
+    ASSERT_EQ(spv::Op::OpTypeVector,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsVector());
   }
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_adjust_branch_weights_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_adjust_branch_weights_test.cpp
index 5984a3e..2b532bf 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_adjust_branch_weights_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_adjust_branch_weights_test.cpp
@@ -108,7 +108,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests OpBranchConditional instruction with weights.
   auto instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   auto transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {0, 1});
   ASSERT_TRUE(
@@ -116,7 +116,7 @@
 
   // Tests the two branch weights equal to 0.
   instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {0, 0});
 #ifndef NDEBUG
@@ -127,14 +127,14 @@
 
   // Tests 32-bit unsigned integer overflow.
   instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   transformation = TransformationAdjustBranchWeights(instruction_descriptor,
                                                      {UINT32_MAX, 0});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   transformation = TransformationAdjustBranchWeights(instruction_descriptor,
                                                      {1, UINT32_MAX});
 #ifndef NDEBUG
@@ -145,26 +145,26 @@
 
   // Tests OpBranchConditional instruction with no weights.
   instruction_descriptor =
-      MakeInstructionDescriptor(21, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {0, 1});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests non-OpBranchConditional instructions.
-  instruction_descriptor = MakeInstructionDescriptor(2, SpvOpTypeVoid, 0);
+  instruction_descriptor = MakeInstructionDescriptor(2, spv::Op::OpTypeVoid, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {5, 6});
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(20, SpvOpLabel, 0);
+  instruction_descriptor = MakeInstructionDescriptor(20, spv::Op::OpLabel, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {1, 2});
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(49, SpvOpIAdd, 0);
+  instruction_descriptor = MakeInstructionDescriptor(49, spv::Op::OpIAdd, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {1, 2});
   ASSERT_FALSE(
@@ -255,13 +255,13 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   auto transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {5, 6});
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(21, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {7, 8});
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_composite_construct_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_composite_construct_test.cpp
index 3c5f731..c4eef87 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_composite_construct_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_composite_construct_test.cpp
@@ -136,16 +136,17 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Make a vec2[3]
   TransformationCompositeConstruct make_vec2_array_length_3(
-      37, {41, 45, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0),
-      200);
+      37, {41, 45, 27},
+      MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 200);
   // Bad: there are too many components
   TransformationCompositeConstruct make_vec2_array_length_3_bad(
-      37, {41, 45, 27, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0),
-      200);
+      37, {41, 45, 27, 27},
+      MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 200);
   // The first component does not correspond to an instruction with a result
   // type so this check should return false.
   TransformationCompositeConstruct make_vec2_array_length_3_nores(
-      37, {2, 45, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 200);
+      37, {2, 45, 27}, MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0),
+      200);
   ASSERT_TRUE(make_vec2_array_length_3.IsApplicable(context.get(),
                                                     transformation_context));
   ASSERT_FALSE(make_vec2_array_length_3_bad.IsApplicable(
@@ -159,7 +160,7 @@
   uint32_t num_uses_of_27_before = context->get_def_use_mgr()->NumUses(27);
   ApplyAndCheckFreshIds(make_vec2_array_length_3, context.get(),
                         &transformation_context);
-  ASSERT_EQ(SpvOpCompositeConstruct,
+  ASSERT_EQ(spv::Op::OpCompositeConstruct,
             context->get_def_use_mgr()->GetDef(200)->opcode());
   ASSERT_EQ(34, context->get_instr_block(200)->id());
   ASSERT_EQ(num_uses_of_41_before + 1, context->get_def_use_mgr()->NumUses(41));
@@ -176,10 +177,10 @@
 
   // Make a float[2]
   TransformationCompositeConstruct make_float_array_length_2(
-      9, {24, 40}, MakeInstructionDescriptor(71, SpvOpStore, 0), 201);
+      9, {24, 40}, MakeInstructionDescriptor(71, spv::Op::OpStore, 0), 201);
   // Bad: %41 does not have type float
   TransformationCompositeConstruct make_float_array_length_2_bad(
-      9, {41, 40}, MakeInstructionDescriptor(71, SpvOpStore, 0), 201);
+      9, {41, 40}, MakeInstructionDescriptor(71, spv::Op::OpStore, 0), 201);
   ASSERT_TRUE(make_float_array_length_2.IsApplicable(context.get(),
                                                      transformation_context));
   ASSERT_FALSE(make_float_array_length_2_bad.IsApplicable(
@@ -195,12 +196,12 @@
 
   // Make a bool[3]
   TransformationCompositeConstruct make_bool_array_length_3(
-      47, {33, 50, 50}, MakeInstructionDescriptor(33, SpvOpSelectionMerge, 0),
-      202);
+      47, {33, 50, 50},
+      MakeInstructionDescriptor(33, spv::Op::OpSelectionMerge, 0), 202);
   // Bad: %54 is not available at the desired program point.
   TransformationCompositeConstruct make_bool_array_length_3_bad(
-      47, {33, 54, 50}, MakeInstructionDescriptor(33, SpvOpSelectionMerge, 0),
-      202);
+      47, {33, 54, 50},
+      MakeInstructionDescriptor(33, spv::Op::OpSelectionMerge, 0), 202);
   ASSERT_TRUE(make_bool_array_length_3.IsApplicable(context.get(),
                                                     transformation_context));
   ASSERT_FALSE(make_bool_array_length_3_bad.IsApplicable(
@@ -218,10 +219,10 @@
 
   // make a uvec3[2][2]
   TransformationCompositeConstruct make_uvec3_array_length_2_2(
-      58, {69, 100}, MakeInstructionDescriptor(64, SpvOpStore, 0), 203);
+      58, {69, 100}, MakeInstructionDescriptor(64, spv::Op::OpStore, 0), 203);
   // Bad: Skip count 100 is too large.
   TransformationCompositeConstruct make_uvec3_array_length_2_2_bad(
-      58, {33, 54}, MakeInstructionDescriptor(64, SpvOpStore, 100), 203);
+      58, {33, 54}, MakeInstructionDescriptor(64, spv::Op::OpStore, 100), 203);
   ASSERT_TRUE(make_uvec3_array_length_2_2.IsApplicable(context.get(),
                                                        transformation_context));
   ASSERT_FALSE(make_uvec3_array_length_2_2_bad.IsApplicable(
@@ -425,14 +426,17 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // make a mat3x4
   TransformationCompositeConstruct make_mat34(
-      32, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      32, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   // Bad: %35 is mat4x3, not mat3x4.
   TransformationCompositeConstruct make_mat34_bad(
-      35, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      35, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   // The first component does not correspond to an instruction with a result
   // type so this check should return false.
   TransformationCompositeConstruct make_mat34_nores(
-      32, {2, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      32, {2, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   ASSERT_TRUE(make_mat34.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_mat34_bad.IsApplicable(context.get(), transformation_context));
@@ -450,10 +454,12 @@
 
   // make a mat4x3
   TransformationCompositeConstruct make_mat43(
-      35, {11, 13, 16, 100}, MakeInstructionDescriptor(31, SpvOpStore, 0), 201);
+      35, {11, 13, 16, 100}, MakeInstructionDescriptor(31, spv::Op::OpStore, 0),
+      201);
   // Bad: %25 does not match the matrix's column type.
   TransformationCompositeConstruct make_mat43_bad(
-      35, {25, 13, 16, 100}, MakeInstructionDescriptor(31, SpvOpStore, 0), 201);
+      35, {25, 13, 16, 100}, MakeInstructionDescriptor(31, spv::Op::OpStore, 0),
+      201);
   ASSERT_TRUE(make_mat43.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_mat43_bad.IsApplicable(context.get(), transformation_context));
@@ -644,14 +650,16 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // make an Inner
   TransformationCompositeConstruct make_inner(
-      9, {25, 19}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200);
+      9, {25, 19}, MakeInstructionDescriptor(57, spv::Op::OpAccessChain, 0),
+      200);
   // Bad: Too few fields to make the struct.
   TransformationCompositeConstruct make_inner_bad(
-      9, {25}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200);
+      9, {25}, MakeInstructionDescriptor(57, spv::Op::OpAccessChain, 0), 200);
   // The first component does not correspond to an instruction with a result
   // type so this check should return false.
   TransformationCompositeConstruct make_inner_nores(
-      9, {2, 19}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200);
+      9, {2, 19}, MakeInstructionDescriptor(57, spv::Op::OpAccessChain, 0),
+      200);
   ASSERT_TRUE(make_inner.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_inner_bad.IsApplicable(context.get(), transformation_context));
@@ -667,12 +675,12 @@
 
   // make an Outer
   TransformationCompositeConstruct make_outer(
-      33, {46, 200, 56}, MakeInstructionDescriptor(200, SpvOpAccessChain, 0),
-      201);
+      33, {46, 200, 56},
+      MakeInstructionDescriptor(200, spv::Op::OpAccessChain, 0), 201);
   // Bad: %200 is not available at the desired program point.
   TransformationCompositeConstruct make_outer_bad(
       33, {46, 200, 56},
-      MakeInstructionDescriptor(200, SpvOpCompositeConstruct, 0), 201);
+      MakeInstructionDescriptor(200, spv::Op::OpCompositeConstruct, 0), 201);
   ASSERT_TRUE(make_outer.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_outer_bad.IsApplicable(context.get(), transformation_context));
@@ -973,10 +981,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationCompositeConstruct make_vec2(
-      7, {17, 11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200);
+      7, {17, 11}, MakeInstructionDescriptor(100, spv::Op::OpStore, 0), 200);
   // Bad: not enough data for a vec2
   TransformationCompositeConstruct make_vec2_bad(
-      7, {11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200);
+      7, {11}, MakeInstructionDescriptor(100, spv::Op::OpStore, 0), 200);
   ASSERT_TRUE(make_vec2.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_vec2_bad.IsApplicable(context.get(), transformation_context));
@@ -989,12 +997,12 @@
       MakeDataDescriptor(11, {}), MakeDataDescriptor(200, {1})));
 
   TransformationCompositeConstruct make_vec3(
-      25, {12, 32}, MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0),
-      201);
+      25, {12, 32},
+      MakeInstructionDescriptor(35, spv::Op::OpCompositeConstruct, 0), 201);
   // Bad: too much data for a vec3
   TransformationCompositeConstruct make_vec3_bad(
       25, {12, 32, 32},
-      MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0), 201);
+      MakeInstructionDescriptor(35, spv::Op::OpCompositeConstruct, 0), 201);
   ASSERT_TRUE(make_vec3.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_vec3_bad.IsApplicable(context.get(), transformation_context));
@@ -1009,12 +1017,12 @@
       MakeDataDescriptor(32, {}), MakeDataDescriptor(201, {2})));
 
   TransformationCompositeConstruct make_vec4(
-      44, {32, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0),
-      202);
+      44, {32, 32, 10, 11},
+      MakeInstructionDescriptor(75, spv::Op::OpAccessChain, 0), 202);
   // Bad: id 48 is not available at the insertion points
   TransformationCompositeConstruct make_vec4_bad(
-      44, {48, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0),
-      202);
+      44, {48, 32, 10, 11},
+      MakeInstructionDescriptor(75, spv::Op::OpAccessChain, 0), 202);
   ASSERT_TRUE(make_vec4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_vec4_bad.IsApplicable(context.get(), transformation_context));
@@ -1031,10 +1039,10 @@
       MakeDataDescriptor(11, {}), MakeDataDescriptor(202, {3})));
 
   TransformationCompositeConstruct make_ivec2(
-      51, {126, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203);
+      51, {126, 120}, MakeInstructionDescriptor(128, spv::Op::OpLoad, 0), 203);
   // Bad: if 128 is not available at the instruction that defines 128
   TransformationCompositeConstruct make_ivec2_bad(
-      51, {128, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203);
+      51, {128, 120}, MakeInstructionDescriptor(128, spv::Op::OpLoad, 0), 203);
   ASSERT_TRUE(make_ivec2.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_ivec2_bad.IsApplicable(context.get(), transformation_context));
@@ -1047,12 +1055,12 @@
       MakeDataDescriptor(120, {}), MakeDataDescriptor(203, {1})));
 
   TransformationCompositeConstruct make_ivec3(
-      114, {56, 117, 56}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0),
-      204);
+      114, {56, 117, 56},
+      MakeInstructionDescriptor(66, spv::Op::OpAccessChain, 0), 204);
   // Bad because 1300 is not an id
   TransformationCompositeConstruct make_ivec3_bad(
-      114, {56, 117, 1300}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0),
-      204);
+      114, {56, 117, 1300},
+      MakeInstructionDescriptor(66, spv::Op::OpAccessChain, 0), 204);
   ASSERT_TRUE(make_ivec3.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_ivec3_bad.IsApplicable(context.get(), transformation_context));
@@ -1067,12 +1075,12 @@
       MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {2})));
 
   TransformationCompositeConstruct make_ivec4(
-      122, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0),
-      205);
+      122, {56, 117, 117, 117},
+      MakeInstructionDescriptor(66, spv::Op::OpIAdd, 0), 205);
   // Bad because 86 is the wrong type.
   TransformationCompositeConstruct make_ivec4_bad(
-      86, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0),
-      205);
+      86, {56, 117, 117, 117},
+      MakeInstructionDescriptor(66, spv::Op::OpIAdd, 0), 205);
   ASSERT_TRUE(make_ivec4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_ivec4_bad.IsApplicable(context.get(), transformation_context));
@@ -1089,9 +1097,11 @@
       MakeDataDescriptor(117, {}), MakeDataDescriptor(205, {3})));
 
   TransformationCompositeConstruct make_uvec2(
-      86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 0), 206);
+      86, {18, 38}, MakeInstructionDescriptor(133, spv::Op::OpAccessChain, 0),
+      206);
   TransformationCompositeConstruct make_uvec2_bad(
-      86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 200), 206);
+      86, {18, 38}, MakeInstructionDescriptor(133, spv::Op::OpAccessChain, 200),
+      206);
   ASSERT_TRUE(make_uvec2.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_uvec2_bad.IsApplicable(context.get(), transformation_context));
@@ -1104,10 +1114,12 @@
       MakeDataDescriptor(38, {}), MakeDataDescriptor(206, {1})));
 
   TransformationCompositeConstruct make_uvec3(
-      59, {14, 18, 136}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207);
+      59, {14, 18, 136}, MakeInstructionDescriptor(137, spv::Op::OpReturn, 0),
+      207);
   // Bad because 1300 is not an id
   TransformationCompositeConstruct make_uvec3_bad(
-      59, {14, 18, 1300}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207);
+      59, {14, 18, 1300}, MakeInstructionDescriptor(137, spv::Op::OpReturn, 0),
+      207);
   ASSERT_TRUE(make_uvec3.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_uvec3_bad.IsApplicable(context.get(), transformation_context));
@@ -1123,11 +1135,11 @@
 
   TransformationCompositeConstruct make_uvec4(
       131, {14, 18, 136, 136},
-      MakeInstructionDescriptor(137, SpvOpAccessChain, 0), 208);
+      MakeInstructionDescriptor(137, spv::Op::OpAccessChain, 0), 208);
   // Bad because 86 is the wrong type.
   TransformationCompositeConstruct make_uvec4_bad(
       86, {14, 18, 136, 136},
-      MakeInstructionDescriptor(137, SpvOpAccessChain, 0), 208);
+      MakeInstructionDescriptor(137, spv::Op::OpAccessChain, 0), 208);
   ASSERT_TRUE(make_uvec4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_uvec4_bad.IsApplicable(context.get(), transformation_context));
@@ -1149,7 +1161,7 @@
           111,
           41,
       },
-      MakeInstructionDescriptor(75, SpvOpAccessChain, 0), 209);
+      MakeInstructionDescriptor(75, spv::Op::OpAccessChain, 0), 209);
   // Bad because 0 is not a valid base instruction id
   TransformationCompositeConstruct make_bvec2_bad(
       102,
@@ -1157,7 +1169,7 @@
           111,
           41,
       },
-      MakeInstructionDescriptor(0, SpvOpExtInstImport, 0), 209);
+      MakeInstructionDescriptor(0, spv::Op::OpExtInstImport, 0), 209);
   ASSERT_TRUE(make_bvec2.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_bvec2_bad.IsApplicable(context.get(), transformation_context));
@@ -1170,10 +1182,10 @@
       MakeDataDescriptor(41, {}), MakeDataDescriptor(209, {1})));
 
   TransformationCompositeConstruct make_bvec3(
-      93, {108, 73}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210);
+      93, {108, 73}, MakeInstructionDescriptor(108, spv::Op::OpStore, 0), 210);
   // Bad because there are too many components for a bvec3
   TransformationCompositeConstruct make_bvec3_bad(
-      93, {108, 108}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210);
+      93, {108, 108}, MakeInstructionDescriptor(108, spv::Op::OpStore, 0), 210);
   ASSERT_TRUE(make_bvec3.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_bvec3_bad.IsApplicable(context.get(), transformation_context));
@@ -1188,10 +1200,11 @@
       MakeDataDescriptor(73, {}), MakeDataDescriptor(210, {2})));
 
   TransformationCompositeConstruct make_bvec4(
-      70, {108, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211);
+      70, {108, 108}, MakeInstructionDescriptor(108, spv::Op::OpBranch, 0),
+      211);
   // Bad because 21 is a type, not a result id
   TransformationCompositeConstruct make_bvec4_bad(
-      70, {21, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211);
+      70, {21, 108}, MakeInstructionDescriptor(108, spv::Op::OpBranch, 0), 211);
   ASSERT_TRUE(make_bvec4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_bvec4_bad.IsApplicable(context.get(), transformation_context));
@@ -1477,7 +1490,8 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationCompositeConstruct transformation(
-      32, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      32, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1562,7 +1576,8 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(25);
 
   TransformationCompositeConstruct transformation(
-      32, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      32, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1618,7 +1633,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
 
   TransformationCompositeConstruct transformation(
-      7, {10, 11}, MakeInstructionDescriptor(15, SpvOpBranch, 0), 100);
+      7, {10, 11}, MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 100);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1660,7 +1675,7 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(8);
 
   TransformationCompositeConstruct transformation(
-      7, {8, 9, 10}, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100);
+      7, {8, 9, 10}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1707,7 +1722,7 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(10);
 
   TransformationCompositeConstruct transformation(
-      8, {10, 9}, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100);
+      8, {10, 9}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_composite_extract_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_composite_extract_test.cpp
index 1df5591..d468e41 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_composite_extract_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_composite_extract_test.cpp
@@ -102,47 +102,49 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Instruction does not exist.
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(36, SpvOpIAdd, 0), 200, 101, {0})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(36, spv::Op::OpIAdd, 0), 200, 101, {0})
+          .IsApplicable(context.get(), transformation_context));
 
   // Id for composite is not a composite.
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 200, 32, {})
+          MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 200, 32, {})
           .IsApplicable(context.get(), transformation_context));
 
   // Composite does not dominate instruction being inserted before.
-  ASSERT_FALSE(
-      TransformationCompositeExtract(
-          MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 200, 101, {0})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationCompositeExtract(
+                   MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0),
+                   200, 101, {0})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Too many indices for extraction from struct composite.
-  ASSERT_FALSE(
-      TransformationCompositeExtract(
-          MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 200, 101, {0, 0})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationCompositeExtract(
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0),
+                   200, 101, {0, 0})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Too many indices for extraction from struct composite.
-  ASSERT_FALSE(
-      TransformationCompositeExtract(
-          MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 0, 0})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationCompositeExtract(
+                   MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200,
+                   104, {0, 0, 0})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Out of bounds index for extraction from struct composite.
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 3})
+          MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200, 104, {0, 3})
           .IsApplicable(context.get(), transformation_context));
 
   // Result id already used.
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(35, SpvOpFAdd, 0), 80, 103, {0})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(35, spv::Op::OpFAdd, 0), 80, 103, {0})
+          .IsApplicable(context.get(), transformation_context));
 
   TransformationCompositeExtract transformation_1(
-      MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
+      MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(201));
   ASSERT_EQ(nullptr, context->get_instr_block(201));
   uint32_t num_uses_of_100_before = context->get_def_use_mgr()->NumUses(100);
@@ -150,7 +152,7 @@
       transformation_1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_1, context.get(),
                         &transformation_context);
-  ASSERT_EQ(SpvOpCompositeExtract,
+  ASSERT_EQ(spv::Op::OpCompositeExtract,
             context->get_def_use_mgr()->GetDef(201)->opcode());
   ASSERT_EQ(15, context->get_instr_block(201)->id());
   ASSERT_EQ(num_uses_of_100_before + 1,
@@ -159,7 +161,8 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_2(
-      MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 202, 104, {0, 2});
+      MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 202, 104,
+      {0, 2});
   ASSERT_TRUE(
       transformation_2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_2, context.get(),
@@ -168,7 +171,7 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_3(
-      MakeInstructionDescriptor(29, SpvOpAccessChain, 0), 203, 104, {0});
+      MakeInstructionDescriptor(29, spv::Op::OpAccessChain, 0), 203, 104, {0});
   ASSERT_TRUE(
       transformation_3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_3, context.get(),
@@ -177,7 +180,7 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_4(
-      MakeInstructionDescriptor(24, SpvOpStore, 0), 204, 101, {0});
+      MakeInstructionDescriptor(24, spv::Op::OpStore, 0), 204, 101, {0});
   ASSERT_TRUE(
       transformation_4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_4, context.get(),
@@ -186,7 +189,7 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_5(
-      MakeInstructionDescriptor(29, SpvOpBranch, 0), 205, 102, {2});
+      MakeInstructionDescriptor(29, spv::Op::OpBranch, 0), 205, 102, {2});
   ASSERT_TRUE(
       transformation_5.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_5, context.get(),
@@ -195,7 +198,7 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_6(
-      MakeInstructionDescriptor(37, SpvOpReturn, 0), 206, 103, {1});
+      MakeInstructionDescriptor(37, spv::Op::OpReturn, 0), 206, 103, {1});
   ASSERT_TRUE(
       transformation_6.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_6, context.get(),
@@ -378,45 +381,50 @@
   // Cannot insert before the OpVariables of a function.
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, {0})
+          MakeInstructionDescriptor(101, spv::Op::OpVariable, 0), 200, 14, {0})
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, {1})
+          MakeInstructionDescriptor(101, spv::Op::OpVariable, 1), 200, 14, {1})
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, {1})
+          MakeInstructionDescriptor(102, spv::Op::OpVariable, 0), 200, 14, {1})
           .IsApplicable(context.get(), transformation_context));
   // OK to insert right after the OpVariables.
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, {1})
-                   .IsApplicable(context.get(), transformation_context));
-
-  // Cannot insert before the OpPhis of a block.
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(60, SpvOpPhi, 0), 200, 14, {2})
-                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(59, SpvOpPhi, 0), 200, 14, {3})
-                   .IsApplicable(context.get(), transformation_context));
-  // OK to insert after the OpPhis.
-  ASSERT_TRUE(
+  ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14, {3})
+          MakeInstructionDescriptor(102, spv::Op::OpBranch, 1), 200, 14, {1})
           .IsApplicable(context.get(), transformation_context));
 
+  // Cannot insert before the OpPhis of a block.
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(60, spv::Op::OpPhi, 0), 200, 14, {2})
+          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(59, spv::Op::OpPhi, 0), 200, 14, {3})
+          .IsApplicable(context.get(), transformation_context));
+  // OK to insert after the OpPhis.
+  ASSERT_TRUE(TransformationCompositeExtract(
+                  MakeInstructionDescriptor(59, spv::Op::OpAccessChain, 0), 200,
+                  14, {3})
+                  .IsApplicable(context.get(), transformation_context));
+
   // Cannot insert before OpLoopMerge
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
-                   200, 14, {3})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0), 200,
+          14, {3})
+          .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpSelectionMerge
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
-                   200, 14, {2})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0), 200,
+          14, {2})
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationCompositeExtractTest, AddSynonymsForRelevantIds) {
@@ -498,7 +506,7 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationCompositeExtract transformation(
-      MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
+      MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -586,7 +594,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(100);
   TransformationCompositeExtract transformation(
-      MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
+      MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -635,7 +643,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
   TransformationCompositeExtract transformation(
-      MakeInstructionDescriptor(15, SpvOpBranch, 0), 100, 12, {0});
+      MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 100, 12, {0});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_composite_insert_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_composite_insert_test.cpp
index 3b6f34d..e61c0fa 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_composite_insert_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_composite_insert_test.cpp
@@ -103,65 +103,69 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Bad: |fresh_id| is not fresh.
   auto transformation_bad_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 20, 29, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 20, 29, 11,
+      {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_1.IsApplicable(context.get(), transformation_context));
 
   // Bad: |composite_id| does not refer to a existing instruction.
   auto transformation_bad_2 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 40, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 40, 11,
+      {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_2.IsApplicable(context.get(), transformation_context));
 
   // Bad: |composite_id| does not refer to a composite value.
   auto transformation_bad_3 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 9, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 9, 11, {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_3.IsApplicable(context.get(), transformation_context));
 
   // Bad: |object_id| does not refer to a defined instruction.
   auto transformation_bad_4 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 29, 40, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 40,
+      {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_4.IsApplicable(context.get(), transformation_context));
 
   // Bad: |object_id| cannot refer to a pointer.
   auto transformation_bad_5 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 29, 8, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 8, {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_5.IsApplicable(context.get(), transformation_context));
 
   // Bad: |index| is not a correct index.
   auto transformation_bad_6 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 29, 11, {2, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 11,
+      {2, 0, 0});
   ASSERT_FALSE(
       transformation_bad_6.IsApplicable(context.get(), transformation_context));
 
   // Bad: Type id of the object to be inserted and the type id of the
   // component at |index| are not the same.
   auto transformation_bad_7 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 29, 11, {1, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 11, {1, 0});
   ASSERT_FALSE(
       transformation_bad_7.IsApplicable(context.get(), transformation_context));
 
   // Bad: |instruction_to_insert_before| does not refer to a defined
   // instruction.
   auto transformation_bad_8 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpIMul, 0), 50, 29, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpIMul, 0), 50, 29, 11, {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_8.IsApplicable(context.get(), transformation_context));
 
   // Bad: OpCompositeInsert cannot be inserted before OpBranchConditional with
   // OpSelectionMerge above it.
   auto transformation_bad_9 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpBranchConditional, 0), 50, 29, 11,
-      {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpBranchConditional, 0), 50, 29,
+      11, {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_9.IsApplicable(context.get(), transformation_context));
 
   // Bad: |composite_id| does not have a type_id.
   auto transformation_bad_10 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 1, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 1, 11, {1, 0, 0});
   ASSERT_FALSE(transformation_bad_10.IsApplicable(context.get(),
                                                   transformation_context));
 }
@@ -222,14 +226,14 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Bad: The composite with |composite_id| cannot be empty.
   auto transformation_bad_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(64, SpvOpStore, 0), 50, 61, 62, {1});
+      MakeInstructionDescriptor(64, spv::Op::OpStore, 0), 50, 61, 62, {1});
   ASSERT_FALSE(
       transformation_bad_1.IsApplicable(context.get(), transformation_context));
 
   // Good: It is possible to insert into a composite an element which is an
   // empty composite.
   auto transformation_good_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(64, SpvOpStore, 0), 50, 64, 62, {1});
+      MakeInstructionDescriptor(64, spv::Op::OpStore, 0), 50, 64, 62, {1});
   ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_1, context.get(),
@@ -368,7 +372,8 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(30);
 
   auto transformation_good_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(30, SpvOpStore, 0), 50, 30, 11, {1, 0, 0});
+      MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 50, 30, 11,
+      {1, 0, 0});
   ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_1, context.get(),
@@ -473,7 +478,8 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(11);
 
   auto transformation_good_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(30, SpvOpStore, 0), 50, 30, 11, {1, 0, 0});
+      MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 50, 30, 11,
+      {1, 0, 0});
   ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_1, context.get(),
@@ -580,7 +586,8 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto transformation_good_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(30, SpvOpStore, 0), 50, 30, 11, {1, 0, 0});
+      MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 50, 30, 11,
+      {1, 0, 0});
   ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_1, context.get(),
@@ -609,7 +616,8 @@
       MakeDataDescriptor(30, {1, 0, 0}), MakeDataDescriptor(50, {1, 0, 0})));
 
   auto transformation_good_2 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(50, SpvOpStore, 0), 51, 50, 11, {0, 1, 1});
+      MakeInstructionDescriptor(50, spv::Op::OpStore, 0), 51, 50, 11,
+      {0, 1, 1});
   ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_2, context.get(),
@@ -787,30 +795,30 @@
   // Bad: The object with |object_id| is not available at
   // |instruction_to_insert_before|.
   auto transformation_bad_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(31, SpvOpIMul, 0), 50, 27, 60, {1});
+      MakeInstructionDescriptor(31, spv::Op::OpIMul, 0), 50, 27, 60, {1});
   ASSERT_FALSE(
       transformation_bad_1.IsApplicable(context.get(), transformation_context));
 
   // Bad: The composite with |composite_id| is not available at
   // |instruction_to_insert_before|.
   auto transformation_bad_2 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(31, SpvOpIMul, 0), 50, 61, 21, {1});
+      MakeInstructionDescriptor(31, spv::Op::OpIMul, 0), 50, 61, 21, {1});
   ASSERT_FALSE(
       transformation_bad_2.IsApplicable(context.get(), transformation_context));
 
   // Bad: The |instruction_to_insert_before| is the composite itself and is
   // available.
   auto transformation_bad_3 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(61, SpvOpCompositeConstruct, 0), 50, 61, 21,
-      {1});
+      MakeInstructionDescriptor(61, spv::Op::OpCompositeConstruct, 0), 50, 61,
+      21, {1});
   ASSERT_FALSE(
       transformation_bad_3.IsApplicable(context.get(), transformation_context));
 
   // Bad: The |instruction_to_insert_before| is the object itself and is not
   // available.
   auto transformation_bad_4 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(60, SpvOpCompositeConstruct, 0), 50, 27, 60,
-      {1});
+      MakeInstructionDescriptor(60, spv::Op::OpCompositeConstruct, 0), 50, 27,
+      60, {1});
   ASSERT_FALSE(
       transformation_bad_4.IsApplicable(context.get(), transformation_context));
 }
@@ -863,7 +871,8 @@
 
   // Leads to synonyms - nothing is irrelevant.
   auto transformation1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0), 100, 9, 17, {0});
+      MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0), 100, 9, 17,
+      {0});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -876,7 +885,8 @@
   // Because %16 is irrelevant, we don't get a synonym with the component to
   // which it has been inserted (but we do for the other component).
   auto transformation2 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0), 101, 9, 16, {0});
+      MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0), 101, 9, 16,
+      {0});
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -889,7 +899,8 @@
   // Because %18 is irrelevant we only get a synonym for the component into
   // which insertion has taken place.
   auto transformation3 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0), 102, 18, 17, {0});
+      MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0), 102, 18, 17,
+      {0});
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -901,7 +912,7 @@
 
   // Does not lead to synonyms as block %14 is dead.
   auto transformation4 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(14, SpvOpBranch, 0), 103, 9, 17, {0});
+      MakeInstructionDescriptor(14, spv::Op::OpBranch, 0), 103, 9, 17, {0});
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_equation_instruction_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_equation_instruction_test.cpp
index 5b5033d..3653fca 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_equation_instruction_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_equation_instruction_test.cpp
@@ -54,65 +54,66 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Bad: id already in use.
-  ASSERT_FALSE(TransformationEquationInstruction(7, SpvOpSNegate, {7},
+  ASSERT_FALSE(TransformationEquationInstruction(7, spv::Op::OpSNegate, {7},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: identified instruction does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(
-          14, SpvOpSNegate, {7}, MakeInstructionDescriptor(13, SpvOpLoad, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(
+                   14, spv::Op::OpSNegate, {7},
+                   MakeInstructionDescriptor(13, spv::Op::OpLoad, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 100 does not exist
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {100},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {100},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 20 is an OpUndef
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {20},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {20},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 30 is not available right before its definition
   ASSERT_FALSE(TransformationEquationInstruction(
-                   14, SpvOpSNegate, {30},
-                   MakeInstructionDescriptor(30, SpvOpCopyObject, 0))
+                   14, spv::Op::OpSNegate, {30},
+                   MakeInstructionDescriptor(30, spv::Op::OpCopyObject, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: too many arguments to OpSNegate.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {7, 7},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {7, 7},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: 40 is a type id.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {40},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {40},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: wrong type of argument to OpSNegate.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {41},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {41},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationEquationInstruction(
-      14, SpvOpSNegate, {7}, return_instruction);
+      14, spv::Op::OpSNegate, {7}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(14));
   ASSERT_EQ(nullptr, context->get_instr_block(14));
   ApplyAndCheckFreshIds(transformation1, context.get(),
                         &transformation_context);
-  ASSERT_EQ(SpvOpSNegate, context->get_def_use_mgr()->GetDef(14)->opcode());
+  ASSERT_EQ(spv::Op::OpSNegate,
+            context->get_def_use_mgr()->GetDef(14)->opcode());
   ASSERT_EQ(13, context->get_instr_block(14)->id());
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      15, SpvOpSNegate, {14}, return_instruction);
+      15, spv::Op::OpSNegate, {14}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -178,25 +179,25 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Bad: too few arguments to OpLogicalNot.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpLogicalNot, {},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: 6 is a type id.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {6},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpLogicalNot, {6},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: wrong type of argument to OpLogicalNot.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {21},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpLogicalNot,
+                                                 {21}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationEquationInstruction(
-      14, SpvOpLogicalNot, {7}, return_instruction);
+      14, spv::Op::OpLogicalNot, {7}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -205,7 +206,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      15, SpvOpLogicalNot, {14}, return_instruction);
+      15, spv::Op::OpLogicalNot, {14}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -272,31 +273,31 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Bad: too many arguments to OpIAdd.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 16, 16},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(
+                   14, spv::Op::OpIAdd, {15, 16, 16}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
   // Bad: boolean argument to OpIAdd.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 32},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {15, 32},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
   // Bad: type as argument to OpIAdd.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {33, 16},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {33, 16},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
   // Bad: arguments of mismatched widths
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 31},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {15, 31},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
   // Bad: arguments of mismatched widths
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {31, 15},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {31, 15},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationEquationInstruction(
-      14, SpvOpIAdd, {15, 16}, return_instruction);
+      14, spv::Op::OpIAdd, {15, 16}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -305,7 +306,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      19, SpvOpISub, {14, 16}, return_instruction);
+      19, spv::Op::OpISub, {14, 16}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -316,7 +317,7 @@
       MakeDataDescriptor(15, {}), MakeDataDescriptor(19, {})));
 
   auto transformation3 = TransformationEquationInstruction(
-      20, SpvOpISub, {14, 15}, return_instruction);
+      20, spv::Op::OpISub, {14, 15}, return_instruction);
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -327,7 +328,7 @@
       MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
 
   auto transformation4 = TransformationEquationInstruction(
-      22, SpvOpISub, {16, 14}, return_instruction);
+      22, spv::Op::OpISub, {16, 14}, return_instruction);
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
@@ -336,7 +337,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation5 = TransformationEquationInstruction(
-      24, SpvOpSNegate, {22}, return_instruction);
+      24, spv::Op::OpSNegate, {22}, return_instruction);
   ASSERT_TRUE(
       transformation5.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation5, context.get(),
@@ -404,10 +405,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   auto transformation1 = TransformationEquationInstruction(
-      14, SpvOpISub, {15, 16}, return_instruction);
+      14, spv::Op::OpISub, {15, 16}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -416,7 +417,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      17, SpvOpIAdd, {14, 16}, return_instruction);
+      17, spv::Op::OpIAdd, {14, 16}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -427,7 +428,7 @@
       MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {})));
 
   auto transformation3 = TransformationEquationInstruction(
-      18, SpvOpIAdd, {16, 14}, return_instruction);
+      18, spv::Op::OpIAdd, {16, 14}, return_instruction);
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -440,7 +441,7 @@
       MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {})));
 
   auto transformation4 = TransformationEquationInstruction(
-      19, SpvOpISub, {14, 15}, return_instruction);
+      19, spv::Op::OpISub, {14, 15}, return_instruction);
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
@@ -449,7 +450,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation5 = TransformationEquationInstruction(
-      20, SpvOpSNegate, {19}, return_instruction);
+      20, spv::Op::OpSNegate, {19}, return_instruction);
   ASSERT_TRUE(
       transformation5.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation5, context.get(),
@@ -460,7 +461,7 @@
       MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
 
   auto transformation6 = TransformationEquationInstruction(
-      21, SpvOpISub, {14, 19}, return_instruction);
+      21, spv::Op::OpISub, {14, 19}, return_instruction);
   ASSERT_TRUE(
       transformation6.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation6, context.get(),
@@ -471,7 +472,7 @@
       MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {})));
 
   auto transformation7 = TransformationEquationInstruction(
-      22, SpvOpISub, {14, 18}, return_instruction);
+      22, spv::Op::OpISub, {14, 18}, return_instruction);
   ASSERT_TRUE(
       transformation7.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation7, context.get(),
@@ -480,7 +481,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation8 = TransformationEquationInstruction(
-      23, SpvOpSNegate, {22}, return_instruction);
+      23, spv::Op::OpSNegate, {22}, return_instruction);
   ASSERT_TRUE(
       transformation8.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation8, context.get(),
@@ -559,51 +560,51 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Too many operands.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpBitcast, {15, 16},
-                                                 insert_before)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast,
+                                                 {15, 16}, insert_before)
                    .IsApplicable(context.get(), transformation_context));
 
   // Too few operands.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Operand's id is invalid.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {50}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {50},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Operand's type is invalid
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {13}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {13},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Operand must be a scalar or a vector of numerical type.
 #ifndef NDEBUG
-  ASSERT_DEATH(
-      TransformationEquationInstruction(50, SpvOpBitcast, {23}, insert_before)
-          .IsApplicable(context.get(), transformation_context),
-      "Operand is not a scalar or a vector of numerical type");
-  ASSERT_DEATH(
-      TransformationEquationInstruction(50, SpvOpBitcast, {24}, insert_before)
-          .IsApplicable(context.get(), transformation_context),
-      "Only vectors of numerical components are supported");
+  ASSERT_DEATH(TransformationEquationInstruction(50, spv::Op::OpBitcast, {23},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context),
+               "Operand is not a scalar or a vector of numerical type");
+  ASSERT_DEATH(TransformationEquationInstruction(50, spv::Op::OpBitcast, {24},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context),
+               "Only vectors of numerical components are supported");
 #else
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {23}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {24}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {23},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {24},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 #endif
 
   for (uint32_t operand_id = 15, fresh_id = 50; operand_id <= 20;
        ++operand_id, ++fresh_id) {
     TransformationEquationInstruction transformation(
-        fresh_id, SpvOpBitcast, {operand_id}, insert_before);
+        fresh_id, spv::Op::OpBitcast, {operand_id}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -683,23 +684,23 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Scalar floating-point type does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {15}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {16}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {15},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {16},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Vector of floating-point components does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {18}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {19}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {18},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {19},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist1) {
@@ -730,17 +731,17 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Scalar integral type does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {17}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {17},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Vector of integral components does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {20}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {20},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist2) {
@@ -773,19 +774,19 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
+                                                     {20}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -848,19 +849,19 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
+                                                     {20}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -922,20 +923,20 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
 
-  ASSERT_FALSE(
-      TransformationEquationInstruction(51, SpvOpBitcast, {20}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(51, spv::Op::OpBitcast, {20},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
@@ -993,20 +994,20 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
 
-  ASSERT_FALSE(
-      TransformationEquationInstruction(51, SpvOpBitcast, {20}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(51, spv::Op::OpBitcast, {20},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
@@ -1066,19 +1067,19 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
+                                                     {20}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -1146,19 +1147,19 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
+                                                     {20}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -1222,10 +1223,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   auto transformation1 = TransformationEquationInstruction(
-      522, SpvOpISub, {113, 113}, return_instruction);
+      522, spv::Op::OpISub, {113, 113}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -1234,7 +1235,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      570, SpvOpIAdd, {522, 113}, return_instruction);
+      570, spv::Op::OpIAdd, {522, 113}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -1294,10 +1295,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   auto transformation1 = TransformationEquationInstruction(
-      522, SpvOpISub, {113, 113}, return_instruction);
+      522, spv::Op::OpISub, {113, 113}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -1306,7 +1307,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      570, SpvOpIAdd, {522, 113}, return_instruction);
+      570, spv::Op::OpIAdd, {522, 113}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -1380,97 +1381,97 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Too few instruction operands.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {},
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF, {},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Too many instruction operands.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {15, 16},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
+                                                 {15, 16}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Operand has no type id.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {7},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
+                                                 {7}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // OpConvertSToF and OpConvertUToF require an operand to have scalar or vector
   // of integral components type.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {17},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
+                                                 {17}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {14},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
+                                                 {14}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertUToF, {17},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertUToF,
+                                                 {17}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertUToF, {14},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertUToF,
+                                                 {14}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpConvertSToF, {15},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(50, spv::Op::OpConvertSToF,
+                                                     {15}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpConvertSToF, {10},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(51, spv::Op::OpConvertSToF,
+                                                     {10}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(52, SpvOpConvertUToF, {16},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(52, spv::Op::OpConvertUToF,
+                                                     {16}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(53, SpvOpConvertUToF, {11},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(53, spv::Op::OpConvertUToF,
+                                                     {11}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(58, SpvOpConvertSToF, {18},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(58, spv::Op::OpConvertSToF,
+                                                     {18}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(59, SpvOpConvertUToF, {19},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(59, spv::Op::OpConvertUToF,
+                                                     {19}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(60, SpvOpConvertSToF, {20},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(60, spv::Op::OpConvertSToF,
+                                                     {20}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(61, SpvOpConvertUToF, {21},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(61, spv::Op::OpConvertUToF,
+                                                     {21}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -1555,22 +1556,22 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Scalar float type doesn't exist.
-  ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertUToF, {10},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertUToF,
+                                                 {10}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertSToF, {11},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertSToF,
+                                                 {11}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Vector float type doesn't exist.
-  ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertUToF, {14},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertUToF,
+                                                 {14}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertSToF, {15},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertSToF,
+                                                 {15}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1605,11 +1606,11 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto return_instruction = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto return_instruction = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Applicable.
-  TransformationEquationInstruction transformation(14, SpvOpIAdd, {15, 16},
-                                                   return_instruction);
+  TransformationEquationInstruction transformation(
+      14, spv::Op::OpIAdd, {15, 16}, return_instruction);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
@@ -1662,11 +1663,12 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(41);
 
   TransformationEquationInstruction transformation1(
-      14, SpvOpIAdd, {15, 16},
-      MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0));
+      14, spv::Op::OpIAdd, {15, 16},
+      MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0));
   // No synonym is created since block is dead.
   TransformationEquationInstruction transformation2(
-      100, SpvOpISub, {14, 16}, MakeInstructionDescriptor(41, SpvOpBranch, 0));
+      100, spv::Op::OpISub, {14, 16},
+      MakeInstructionDescriptor(41, spv::Op::OpBranch, 0));
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_flatten_conditional_branch_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_flatten_conditional_branch_test.cpp
index 800af0e..0631899 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_flatten_conditional_branch_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_flatten_conditional_branch_test.cpp
@@ -441,8 +441,8 @@
   ASSERT_DEATH(TransformationFlattenConditionalBranch(
                    31, true, 0, 0, 0,
                    {{MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(6, SpvOpLoad, 0), 100, 101,
-                       102, 103, 104, 14)}})
+                       MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 100,
+                       101, 102, 103, 104, 14)}})
                    .IsApplicable(context.get(), transformation_context),
                "Bad attempt to query whether overflow ids are available.");
 #endif
@@ -451,52 +451,55 @@
   ASSERT_FALSE(TransformationFlattenConditionalBranch(
                    31, true, 0, 0, 0,
                    {{MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(6, SpvOpLoad, 0), 100, 101,
-                       102, 103, 0, 0)}})
+                       MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 100,
+                       101, 102, 103, 0, 0)}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Not all fresh ids given are distinct.
   ASSERT_FALSE(TransformationFlattenConditionalBranch(
                    31, true, 0, 0, 0,
                    {{MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(6, SpvOpLoad, 0), 100, 100,
-                       102, 103, 104, 0)}})
+                       MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 100,
+                       100, 102, 103, 104, 0)}})
                    .IsApplicable(context.get(), transformation_context));
 
   // %48 heads a construct containing an OpSampledImage instruction.
   ASSERT_FALSE(TransformationFlattenConditionalBranch(
                    48, true, 0, 0, 0,
                    {{MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(53, SpvOpLoad, 0), 100, 101,
-                       102, 103, 104, 0)}})
+                       MakeInstructionDescriptor(53, spv::Op::OpLoad, 0), 100,
+                       101, 102, 103, 104, 0)}})
                    .IsApplicable(context.get(), transformation_context));
 
   // %0 is not a valid id.
   ASSERT_FALSE(
       TransformationFlattenConditionalBranch(
           31, true, 0, 0, 0,
-          {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(6, SpvOpLoad, 0),
-                                     104, 100, 101, 102, 103, 0),
+          {MakeSideEffectWrapperInfo(
+               MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 104, 100, 101,
+               102, 103, 0),
            MakeSideEffectWrapperInfo(
-               MakeInstructionDescriptor(6, SpvOpStore, 0), 106, 105)})
+               MakeInstructionDescriptor(6, spv::Op::OpStore, 0), 106, 105)})
           .IsApplicable(context.get(), transformation_context));
 
   // %17 is a float constant, while %6 has int type.
   ASSERT_FALSE(
       TransformationFlattenConditionalBranch(
           31, true, 0, 0, 0,
-          {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(6, SpvOpLoad, 0),
-                                     104, 100, 101, 102, 103, 17),
+          {MakeSideEffectWrapperInfo(
+               MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 104, 100, 101,
+               102, 103, 17),
            MakeSideEffectWrapperInfo(
-               MakeInstructionDescriptor(6, SpvOpStore, 0), 106, 105)})
+               MakeInstructionDescriptor(6, spv::Op::OpStore, 0), 106, 105)})
           .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationFlattenConditionalBranch(
       31, true, 0, 0, 0,
-      {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(6, SpvOpLoad, 0),
-                                 104, 100, 101, 102, 103, 70),
-       MakeSideEffectWrapperInfo(MakeInstructionDescriptor(6, SpvOpStore, 0),
-                                 106, 105)});
+      {MakeSideEffectWrapperInfo(
+           MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 104, 100, 101, 102,
+           103, 70),
+       MakeSideEffectWrapperInfo(
+           MakeInstructionDescriptor(6, spv::Op::OpStore, 0), 106, 105)});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -514,8 +517,8 @@
 
   auto transformation2 = TransformationFlattenConditionalBranch(
       36, false, 0, 0, 0,
-      {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(8, SpvOpStore, 0),
-                                 114, 113)});
+      {MakeSideEffectWrapperInfo(
+          MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 114, 113)});
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), new_transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -717,7 +720,8 @@
   auto transformation1 = TransformationFlattenConditionalBranch(
       7, true, 0, 0, 0,
       {{MakeSideEffectWrapperInfo(
-          MakeInstructionDescriptor(10, SpvOpFunctionCall, 0), 100, 101)}});
+          MakeInstructionDescriptor(10, spv::Op::OpFunctionCall, 0), 100,
+          101)}});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -729,7 +733,8 @@
       TransformationFlattenConditionalBranch(
           7, true, 0, 0, 0,
           {{MakeSideEffectWrapperInfo(
-              MakeInstructionDescriptor(14, SpvOpFunctionCall, 0), 102, 103)}})
+              MakeInstructionDescriptor(14, spv::Op::OpFunctionCall, 0), 102,
+              103)}})
           .IsApplicable(context.get(), transformation_context));
 
   // Block %16 is unreachable.
@@ -1126,10 +1131,12 @@
 
   auto transformation = TransformationFlattenConditionalBranch(
       7, true, 0, 0, 0,
-      {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(522, SpvOpLoad, 0),
-                                 200, 201, 202, 203, 204, 5),
-       MakeSideEffectWrapperInfo(MakeInstructionDescriptor(466, SpvOpLoad, 0),
-                                 300, 301, 302, 303, 304, 5)});
+      {MakeSideEffectWrapperInfo(
+           MakeInstructionDescriptor(522, spv::Op::OpLoad, 0), 200, 201, 202,
+           203, 204, 5),
+       MakeSideEffectWrapperInfo(
+           MakeInstructionDescriptor(466, spv::Op::OpLoad, 0), 300, 301, 302,
+           303, 304, 5)});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1231,8 +1238,9 @@
 
   auto transformation = TransformationFlattenConditionalBranch(
       5, true, 0, 0, 0,
-      {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(20, SpvOpLoad, 0),
-                                 100, 101, 102, 103, 104, 21)});
+      {MakeSideEffectWrapperInfo(
+          MakeInstructionDescriptor(20, spv::Op::OpLoad, 0), 100, 101, 102, 103,
+          104, 21)});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1299,8 +1307,8 @@
   ASSERT_FALSE(TransformationFlattenConditionalBranch(
                    28, true, 0, 0, 0,
                    {MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(40, SpvOpLoad, 0), 100, 101,
-                       102, 103, 104, 200)})
+                       MakeInstructionDescriptor(40, spv::Op::OpLoad, 0), 100,
+                       101, 102, 103, 104, 200)})
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1730,7 +1738,7 @@
   // Check that the in operands of any OpSelect instructions all have the
   // appropriate operand type.
   context->module()->ForEachInst([](opt::Instruction* inst) {
-    if (inst->opcode() == SpvOpSelect) {
+    if (inst->opcode() == spv::Op::OpSelect) {
       ASSERT_EQ(SPV_OPERAND_TYPE_ID, inst->GetInOperand(0).type);
       ASSERT_EQ(SPV_OPERAND_TYPE_ID, inst->GetInOperand(1).type);
       ASSERT_EQ(SPV_OPERAND_TYPE_ID, inst->GetInOperand(2).type);
@@ -2183,14 +2191,15 @@
 
   transformation_context.GetFactManager()->AddFactDataSynonym(
       MakeDataDescriptor(10, {}), MakeDataDescriptor(21, {}));
-  ASSERT_FALSE(TransformationFlattenConditionalBranch(
-                   12, true, 0, 0, 0,
-                   {MakeSideEffectWrapperInfo(
-                        MakeInstructionDescriptor(30, SpvOpStore, 0), 100, 101),
-                    MakeSideEffectWrapperInfo(
-                        MakeInstructionDescriptor(21, SpvOpLoad, 0), 102, 103,
-                        104, 105, 106, 80)})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationFlattenConditionalBranch(
+          12, true, 0, 0, 0,
+          {MakeSideEffectWrapperInfo(
+               MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 100, 101),
+           MakeSideEffectWrapperInfo(
+               MakeInstructionDescriptor(21, spv::Op::OpLoad, 0), 102, 103, 104,
+               105, 106, 80)})
+          .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_function_call_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_function_call_test.cpp
index b27b3ca..c963e33 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_function_call_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_function_call_test.cpp
@@ -174,88 +174,91 @@
 
   // Bad transformations
   // Too many arguments
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {71, 72, 71},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
-  // Too few arguments
   ASSERT_FALSE(TransformationFunctionCall(
-                   100, 21, {71}, MakeInstructionDescriptor(59, SpvOpBranch, 0))
+                   100, 21, {71, 72, 71},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
                    .IsApplicable(context.get(), transformation_context));
+  // Too few arguments
+  ASSERT_FALSE(
+      TransformationFunctionCall(
+          100, 21, {71}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+          .IsApplicable(context.get(), transformation_context));
   // Arguments are the wrong way around (types do not match)
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {72, 71},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {72, 71},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // 21 is not an appropriate argument
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {21, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {21, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // 300 does not exist
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {300, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {300, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // 71 is not a function
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 71, {71, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 71, {71, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // 500 does not exist
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 500, {71, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 500, {71, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Id is not fresh
   ASSERT_FALSE(
-      TransformationFunctionCall(21, 21, {71, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
+      TransformationFunctionCall(
+          21, 21, {71, 72}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
           .IsApplicable(context.get(), transformation_context));
   // Access chain as pointer parameter
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {98, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {98, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Copied object as pointer parameter
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {99, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {99, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Non-livesafe called from original live block
-  ASSERT_FALSE(
-      TransformationFunctionCall(
-          100, 10, {71}, MakeInstructionDescriptor(99, SpvOpSelectionMerge, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 10, {71},
+                   MakeInstructionDescriptor(99, spv::Op::OpSelectionMerge, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Non-livesafe called from livesafe function
-  ASSERT_FALSE(
-      TransformationFunctionCall(
-          100, 10, {19}, MakeInstructionDescriptor(38, SpvOpConvertFToS, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 10, {19},
+                   MakeInstructionDescriptor(38, spv::Op::OpConvertFToS, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Livesafe function called with pointer to non-arbitrary local variable
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {61, 72},
+                   MakeInstructionDescriptor(38, spv::Op::OpConvertFToS, 0))
+                   .IsApplicable(context.get(), transformation_context));
+  // Direct recursion
   ASSERT_FALSE(
       TransformationFunctionCall(
-          100, 21, {61, 72}, MakeInstructionDescriptor(38, SpvOpConvertFToS, 0))
+          100, 4, {}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
           .IsApplicable(context.get(), transformation_context));
-  // Direct recursion
-  ASSERT_FALSE(TransformationFunctionCall(
-                   100, 4, {}, MakeInstructionDescriptor(59, SpvOpBranch, 0))
-                   .IsApplicable(context.get(), transformation_context));
   // Indirect recursion
-  ASSERT_FALSE(TransformationFunctionCall(
-                   100, 24, {9}, MakeInstructionDescriptor(96, SpvOpBranch, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationFunctionCall(
+          100, 24, {9}, MakeInstructionDescriptor(96, spv::Op::OpBranch, 0))
+          .IsApplicable(context.get(), transformation_context));
   // Parameter 23 is not available at the call site
   ASSERT_FALSE(
-      TransformationFunctionCall(104, 10, {23},
-                                 MakeInstructionDescriptor(205, SpvOpBranch, 0))
+      TransformationFunctionCall(
+          104, 10, {23}, MakeInstructionDescriptor(205, spv::Op::OpBranch, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Good transformations
   {
     // Livesafe called from dead block: fine
     TransformationFunctionCall transformation(
-        100, 21, {71, 72}, MakeInstructionDescriptor(59, SpvOpBranch, 0));
+        100, 21, {71, 72}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -266,7 +269,8 @@
   {
     // Livesafe called from original live block: fine
     TransformationFunctionCall transformation(
-        101, 21, {71, 72}, MakeInstructionDescriptor(98, SpvOpAccessChain, 0));
+        101, 21, {71, 72},
+        MakeInstructionDescriptor(98, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -277,7 +281,7 @@
   {
     // Livesafe called from livesafe function: fine
     TransformationFunctionCall transformation(
-        102, 200, {19, 20}, MakeInstructionDescriptor(36, SpvOpLoad, 0));
+        102, 200, {19, 20}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -288,7 +292,7 @@
   {
     // Dead called from dead block in injected function: fine
     TransformationFunctionCall transformation(
-        103, 10, {23}, MakeInstructionDescriptor(45, SpvOpLoad, 0));
+        103, 10, {23}, MakeInstructionDescriptor(45, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -299,7 +303,7 @@
   {
     // Non-livesafe called from dead block in livesafe function: OK
     TransformationFunctionCall transformation(
-        104, 10, {201}, MakeInstructionDescriptor(205, SpvOpBranch, 0));
+        104, 10, {201}, MakeInstructionDescriptor(205, spv::Op::OpBranch, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -310,7 +314,7 @@
   {
     // Livesafe called from dead block with non-arbitrary parameter
     TransformationFunctionCall transformation(
-        105, 21, {62, 65}, MakeInstructionDescriptor(59, SpvOpBranch, 0));
+        105, 21, {62, 65}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -465,9 +469,10 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(11);
 
   // 4 is an entry point, so it is not legal for it to be the target of a call.
-  ASSERT_FALSE(TransformationFunctionCall(
-                   100, 4, {}, MakeInstructionDescriptor(11, SpvOpReturn, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationFunctionCall(
+          100, 4, {}, MakeInstructionDescriptor(11, spv::Op::OpReturn, 0))
+          .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_load_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_load_test.cpp
index 370826e..6fde49a 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_load_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_load_test.cpp
@@ -131,67 +131,68 @@
   //  60 - null
 
   // Bad: id is not fresh
-  ASSERT_FALSE(
-      TransformationLoad(33, 33, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   33, 33, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: attempt to load from 11 from outside its function
-  ASSERT_FALSE(
-      TransformationLoad(100, 11, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 11, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer is not available
-  ASSERT_FALSE(
-      TransformationLoad(100, 33, false, 0, 0,
-                         MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 33, false, 0, 0,
+                   MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to insert before OpVariable
   ASSERT_FALSE(
       TransformationLoad(100, 27, false, 0, 0,
-                         MakeInstructionDescriptor(27, SpvOpVariable, 0))
+                         MakeInstructionDescriptor(27, spv::Op::OpVariable, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id does not exist
-  ASSERT_FALSE(
-      TransformationLoad(100, 1000, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 1000, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists but does not have a type
-  ASSERT_FALSE(
-      TransformationLoad(100, 5, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 5, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists and has a type, but is not a pointer
-  ASSERT_FALSE(
-      TransformationLoad(100, 24, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 24, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to load from null pointer
-  ASSERT_FALSE(
-      TransformationLoad(100, 60, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 60, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: %40 is not available at the program point
-  ASSERT_FALSE(TransformationLoad(100, 40, false, 0, 0,
-                                  MakeInstructionDescriptor(37, SpvOpReturn, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationLoad(100, 40, false, 0, 0,
+                         MakeInstructionDescriptor(37, spv::Op::OpReturn, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: The described instruction does not exist
   ASSERT_FALSE(
       TransformationLoad(100, 33, false, 0, 0,
-                         MakeInstructionDescriptor(1000, SpvOpReturn, 0))
+                         MakeInstructionDescriptor(1000, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationLoad transformation(
         100, 33, false, 0, 0,
-        MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -203,7 +204,7 @@
   {
     TransformationLoad transformation(
         101, 46, false, 0, 0,
-        MakeInstructionDescriptor(16, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(16, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -215,7 +216,7 @@
   {
     TransformationLoad transformation(
         102, 16, false, 0, 0,
-        MakeInstructionDescriptor(16, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(16, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -227,7 +228,7 @@
   {
     TransformationLoad transformation(
         103, 40, false, 0, 0,
-        MakeInstructionDescriptor(43, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(43, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -344,80 +345,80 @@
       MakeUnique<FactManager>(context.get()), validator_options);
 
   // Bad: id is not fresh.
-  ASSERT_FALSE(
-      TransformationLoad(14, 14, true, 15, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   14, 14, true, 15, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 100 of memory scope instruction does not exist.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 100, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 100, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: id 100 of memory semantics instruction does not exist.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 100,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 100,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: memory scope should be |OpConstant| opcode.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 5, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 5, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: memory semantics should be |OpConstant| opcode.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 5,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 5,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: The memory scope instruction must have an Integer operand.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 19,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 19,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: The memory memory semantics instruction must have an Integer operand.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 19, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 19, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Integer size of the memory scope must be equal to 32 bits.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 17, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 17, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Integer size of memory semantics must be equal to 32 bits.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 17,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 17,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
-  // Bad: memory scope value must be 4 (SpvScopeInvocation).
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 16, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  // Bad: memory scope value must be 4 (spv::Scope::Invocation).
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 16, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: memory semantics value must be either:
   // 64 (SpvMemorySemanticsUniformMemoryMask)
   // 256 (SpvMemorySemanticsWorkgroupMemoryMask)
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 16,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 16,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: The described instruction does not exist
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, false, 15, 20,
-                         MakeInstructionDescriptor(150, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, false, 15, 20,
+                   MakeInstructionDescriptor(150, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Successful transformations.
   {
     TransformationLoad transformation(
         21, 14, true, 15, 20,
-        MakeInstructionDescriptor(24, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -518,22 +519,22 @@
       MakeUnique<FactManager>(context.get()), validator_options);
 
   // Bad: Can't insert OpAccessChain before the id 23 of memory scope.
-  ASSERT_FALSE(
-      TransformationLoad(60, 38, true, 21, 23,
-                         MakeInstructionDescriptor(23, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   60, 38, true, 21, 23,
+                   MakeInstructionDescriptor(23, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Can't insert OpAccessChain before the id 23 of memory semantics.
-  ASSERT_FALSE(
-      TransformationLoad(60, 38, true, 21, 23,
-                         MakeInstructionDescriptor(21, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   60, 38, true, 21, 23,
+                   MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Successful transformations.
   {
     TransformationLoad transformation(
         60, 38, true, 21, 23,
-        MakeInstructionDescriptor(40, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_merge_function_returns_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_merge_function_returns_test.cpp
index 400d49a..dd1869f 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_merge_function_returns_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_merge_function_returns_test.cpp
@@ -1884,7 +1884,7 @@
   // Ensure that all input operands of OpBranchConditional instructions have
   // the right operand type.
   context->module()->ForEachInst([](opt::Instruction* inst) {
-    if (inst->opcode() == SpvOpBranchConditional) {
+    if (inst->opcode() == spv::Op::OpBranchConditional) {
       ASSERT_EQ(inst->GetInOperand(0).type, SPV_OPERAND_TYPE_ID);
       ASSERT_EQ(inst->GetInOperand(1).type, SPV_OPERAND_TYPE_ID);
       ASSERT_EQ(inst->GetInOperand(2).type, SPV_OPERAND_TYPE_ID);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_move_instruction_down_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_move_instruction_down_test.cpp
index 45dde7d..5ab1619 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_move_instruction_down_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_move_instruction_down_test.cpp
@@ -73,44 +73,45 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Instruction descriptor is invalid.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(30, SpvOpNop, 0))
+                   MakeInstructionDescriptor(30, spv::Op::OpNop, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Opcode is not supported.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(5, SpvOpLabel, 0))
+                   MakeInstructionDescriptor(5, spv::Op::OpLabel, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(12, SpvOpVariable, 0))
+                   MakeInstructionDescriptor(12, spv::Op::OpVariable, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(42, SpvOpFunctionCall, 0))
+                   MakeInstructionDescriptor(42, spv::Op::OpFunctionCall, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Can't move the last instruction in the block.
-  ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(15, SpvOpBranchConditional, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationMoveInstructionDown(
+          MakeInstructionDescriptor(15, spv::Op::OpBranchConditional, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Can't move the instruction if the next instruction is the last one in the
   // block.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(21, SpvOpIAdd, 0))
+                   MakeInstructionDescriptor(21, spv::Op::OpIAdd, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Can't insert instruction's opcode after its successor.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(15, SpvOpIMul, 0))
+                   MakeInstructionDescriptor(15, spv::Op::OpIMul, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Instruction's successor depends on the instruction.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(10, SpvOpIAdd, 0))
+                   MakeInstructionDescriptor(10, spv::Op::OpIAdd, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(11, SpvOpISub, 0));
+        MakeInstructionDescriptor(11, spv::Op::OpISub, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -120,7 +121,7 @@
   }
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(22, SpvOpIAdd, 0));
+        MakeInstructionDescriptor(22, spv::Op::OpIAdd, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -218,17 +219,17 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Swap memory instruction with an unsupported one.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(22, SpvOpLoad, 0))
+                   MakeInstructionDescriptor(22, spv::Op::OpLoad, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Swap memory barrier with an unsupported one.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(23, SpvOpMemoryBarrier, 0))
+                   MakeInstructionDescriptor(23, spv::Op::OpMemoryBarrier, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Swap simple instruction with an unsupported one.
   TransformationMoveInstructionDown transformation(
-      MakeInstructionDescriptor(8, SpvOpCopyObject, 0));
+      MakeInstructionDescriptor(8, spv::Op::OpCopyObject, 0));
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -322,21 +323,21 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Swap two barrier instructions.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(21, SpvOpMemoryBarrier, 0))
+                   MakeInstructionDescriptor(21, spv::Op::OpMemoryBarrier, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Swap barrier and memory instructions.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(21, SpvOpMemoryBarrier, 2))
+                   MakeInstructionDescriptor(21, spv::Op::OpMemoryBarrier, 2))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(22, SpvOpLoad, 0))
+                   MakeInstructionDescriptor(22, spv::Op::OpLoad, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Swap barrier and simple instructions.
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(23, SpvOpCopyObject, 0));
+        MakeInstructionDescriptor(23, spv::Op::OpCopyObject, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -346,7 +347,7 @@
   }
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(22, SpvOpMemoryBarrier, 1));
+        MakeInstructionDescriptor(22, spv::Op::OpMemoryBarrier, 1));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -406,7 +407,7 @@
   // Swap simple and barrier instructions.
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(40, SpvOpCopyObject, 0));
+        MakeInstructionDescriptor(40, spv::Op::OpCopyObject, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -416,7 +417,7 @@
   }
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(21, SpvOpMemoryBarrier, 0));
+        MakeInstructionDescriptor(21, spv::Op::OpMemoryBarrier, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -428,7 +429,7 @@
   // Swap simple and memory instructions.
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(41, SpvOpCopyObject, 0));
+        MakeInstructionDescriptor(41, spv::Op::OpCopyObject, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -438,7 +439,7 @@
   }
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(22, SpvOpLoad, 0));
+        MakeInstructionDescriptor(22, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -450,7 +451,7 @@
   // Swap two simple instructions.
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(23, SpvOpCopyObject, 0));
+        MakeInstructionDescriptor(23, spv::Op::OpCopyObject, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -625,22 +626,22 @@
 
   protobufs::InstructionDescriptor invalid_swaps[] = {
       // R and RW
-      MakeInstructionDescriptor(25, SpvOpLoad, 0),
+      MakeInstructionDescriptor(25, spv::Op::OpLoad, 0),
 
       // R and W
-      MakeInstructionDescriptor(29, SpvOpLoad, 0),
+      MakeInstructionDescriptor(29, spv::Op::OpLoad, 0),
 
       // RW and RW
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 0),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 2),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 4),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 0),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 2),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 4),
 
       // RW and W
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 12),
-      MakeInstructionDescriptor(32, SpvOpStore, 1),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 12),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 1),
 
       // W and W
-      MakeInstructionDescriptor(32, SpvOpStore, 6),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 6),
   };
 
   for (const auto& descriptor : invalid_swaps) {
@@ -651,55 +652,55 @@
   // Valid swaps.
   protobufs::InstructionDescriptor valid_swaps[] = {
       // R and R
-      MakeInstructionDescriptor(23, SpvOpLoad, 0),
-      MakeInstructionDescriptor(24, SpvOpLoad, 0),
+      MakeInstructionDescriptor(23, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(24, spv::Op::OpLoad, 0),
 
       // R and RW
-      MakeInstructionDescriptor(26, SpvOpLoad, 0),
-      MakeInstructionDescriptor(25, SpvOpCopyMemory, 1),
+      MakeInstructionDescriptor(26, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(25, spv::Op::OpCopyMemory, 1),
 
-      MakeInstructionDescriptor(27, SpvOpLoad, 0),
-      MakeInstructionDescriptor(26, SpvOpCopyMemory, 1),
+      MakeInstructionDescriptor(27, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(26, spv::Op::OpCopyMemory, 1),
 
-      MakeInstructionDescriptor(28, SpvOpLoad, 0),
-      MakeInstructionDescriptor(27, SpvOpCopyMemory, 1),
+      MakeInstructionDescriptor(28, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(27, spv::Op::OpCopyMemory, 1),
 
       // R and W
-      MakeInstructionDescriptor(30, SpvOpLoad, 0),
-      MakeInstructionDescriptor(29, SpvOpStore, 1),
+      MakeInstructionDescriptor(30, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 1),
 
-      MakeInstructionDescriptor(31, SpvOpLoad, 0),
-      MakeInstructionDescriptor(30, SpvOpStore, 1),
+      MakeInstructionDescriptor(31, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(30, spv::Op::OpStore, 1),
 
-      MakeInstructionDescriptor(32, SpvOpLoad, 0),
-      MakeInstructionDescriptor(31, SpvOpStore, 1),
+      MakeInstructionDescriptor(32, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(31, spv::Op::OpStore, 1),
 
       // RW and RW
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 6),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 6),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 6),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 6),
 
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 8),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 8),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 8),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 8),
 
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 10),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 10),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 10),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 10),
 
       // RW and W
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 14),
-      MakeInstructionDescriptor(32, SpvOpStore, 3),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 14),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 3),
 
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 15),
-      MakeInstructionDescriptor(32, SpvOpStore, 4),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 15),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 4),
 
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 16),
-      MakeInstructionDescriptor(32, SpvOpStore, 5),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 16),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 5),
 
       // W and W
-      MakeInstructionDescriptor(32, SpvOpStore, 8),
-      MakeInstructionDescriptor(32, SpvOpStore, 8),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 8),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 8),
 
-      MakeInstructionDescriptor(32, SpvOpStore, 10),
-      MakeInstructionDescriptor(32, SpvOpStore, 10),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 10),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 10),
   };
 
   for (const auto& descriptor : valid_swaps) {
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_mutate_pointer_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_mutate_pointer_test.cpp
index e869efa..e0cb615 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_mutate_pointer_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_mutate_pointer_test.cpp
@@ -86,7 +86,8 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(35);
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(39);
 
-  const auto insert_before = MakeInstructionDescriptor(26, SpvOpReturn, 0);
+  const auto insert_before =
+      MakeInstructionDescriptor(26, spv::Op::OpReturn, 0);
 
   // 20 is not a fresh id.
   ASSERT_FALSE(TransformationMutatePointer(20, 20, insert_before)
@@ -94,13 +95,14 @@
 
   // |insert_before| instruction descriptor is invalid.
   ASSERT_FALSE(TransformationMutatePointer(
-                   20, 70, MakeInstructionDescriptor(26, SpvOpStore, 0))
+                   20, 70, MakeInstructionDescriptor(26, spv::Op::OpStore, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Can't insert OpLoad before OpVariable.
-  ASSERT_FALSE(TransformationMutatePointer(
-                   20, 70, MakeInstructionDescriptor(26, SpvOpVariable, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationMutatePointer(
+          20, 70, MakeInstructionDescriptor(26, spv::Op::OpVariable, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // |pointer_id| doesn't exist in the module.
   ASSERT_FALSE(TransformationMutatePointer(70, 70, insert_before)
@@ -131,9 +133,10 @@
                    .IsApplicable(context.get(), transformation_context));
 
   // |pointer_id| is not available before |insert_before|.
-  ASSERT_FALSE(TransformationMutatePointer(
-                   26, 70, MakeInstructionDescriptor(26, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationMutatePointer(
+          26, 70, MakeInstructionDescriptor(26, spv::Op::OpAccessChain, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(40);
 
@@ -274,7 +277,8 @@
   ASSERT_FALSE(
       context->GetDominatorAnalysis(context->GetFunction(4))->IsReachable(10));
 
-  const auto insert_before = MakeInstructionDescriptor(10, SpvOpReturn, 0);
+  const auto insert_before =
+      MakeInstructionDescriptor(10, spv::Op::OpReturn, 0);
 
   // Can mutate a global variable in an unreachable block.
   TransformationMutatePointer transformation(12, 50, insert_before);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_permute_phi_operands_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_permute_phi_operands_test.cpp
index 0774dcf..320dd1d 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_permute_phi_operands_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_permute_phi_operands_test.cpp
@@ -128,11 +128,11 @@
   context->get_def_use_mgr()->ForEachUse(
       25, [&found_use_in_store, &found_use_in_add_lhs, &found_use_in_add_rhs](
               opt::Instruction* inst, uint32_t operand_index) {
-        if (inst->opcode() == SpvOpStore) {
+        if (inst->opcode() == spv::Op::OpStore) {
           ASSERT_FALSE(found_use_in_store);
           found_use_in_store = true;
         } else {
-          ASSERT_EQ(SpvOpIAdd, inst->opcode());
+          ASSERT_EQ(spv::Op::OpIAdd, inst->opcode());
           if (operand_index == 2) {
             ASSERT_FALSE(found_use_in_add_lhs);
             found_use_in_add_lhs = true;
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_propagate_instruction_down_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_propagate_instruction_down_test.cpp
index 52974ca..8bedef2 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_propagate_instruction_down_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_propagate_instruction_down_test.cpp
@@ -499,13 +499,13 @@
     TransformationPropagateInstructionDown transformation(
         5, 200, {{{15, 203}, {16, 204}}});
     ASSERT_FALSE(context->get_feature_mgr()->HasCapability(
-        SpvCapabilityVariablePointersStorageBuffer));
+        spv::Capability::VariablePointersStorageBuffer));
     ASSERT_FALSE(
         transformation.IsApplicable(context.get(), transformation_context));
 
-    context->AddCapability(SpvCapabilityVariablePointers);
+    context->AddCapability(spv::Capability::VariablePointers);
     ASSERT_TRUE(context->get_feature_mgr()->HasCapability(
-        SpvCapabilityVariablePointersStorageBuffer));
+        spv::Capability::VariablePointersStorageBuffer));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_propagate_instruction_up_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_propagate_instruction_up_test.cpp
index 8a04270..20cf4b3 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_propagate_instruction_up_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_propagate_instruction_up_test.cpp
@@ -699,7 +699,7 @@
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  context->AddCapability(SpvCapabilityVariablePointers);
+  context->AddCapability(spv::Capability::VariablePointers);
 
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
@@ -779,7 +779,7 @@
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  context->AddCapability(SpvCapabilityVariablePointersStorageBuffer);
+  context->AddCapability(spv::Capability::VariablePointersStorageBuffer);
 
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_push_id_through_variable_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_push_id_through_variable_test.cpp
index b0fff58..0d4850d 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_push_id_through_variable_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_push_id_through_variable_test.cpp
@@ -110,9 +110,9 @@
   uint32_t value_synonym_id = 62;
   uint32_t variable_id = 63;
   uint32_t initializer_id = 23;
-  uint32_t variable_storage_class = SpvStorageClassPrivate;
+  uint32_t variable_storage_class = (uint32_t)spv::StorageClass::Private;
   auto instruction_descriptor =
-      MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   auto transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -124,8 +124,9 @@
   value_synonym_id = 60;
   variable_id = 61;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -137,8 +138,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(64, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(64, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -151,8 +153,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 24;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(27, SpvOpVariable, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(27, spv::Op::OpVariable, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -164,8 +167,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(100, SpvOpUnreachable, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(100, spv::Op::OpUnreachable, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -177,8 +181,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 23;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -190,8 +195,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassPrivate;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Private;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -203,8 +209,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 93;
-  variable_storage_class = SpvStorageClassInput;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Input;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -219,8 +226,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(40, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -232,8 +240,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 95;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(40, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -245,8 +254,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 93;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(40, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -335,9 +345,9 @@
   uint32_t value_synonym_id = 100;
   uint32_t variable_id = 101;
   uint32_t initializer_id = 80;
-  uint32_t variable_storage_class = SpvStorageClassFunction;
+  uint32_t variable_storage_class = (uint32_t)spv::StorageClass::Function;
   auto instruction_descriptor =
-      MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0);
   auto transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -346,18 +356,18 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(variable_id));
   ASSERT_EQ(nullptr, context->get_instr_block(variable_id));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpLoad,
+  ASSERT_EQ(spv::Op::OpLoad,
             context->get_def_use_mgr()->GetDef(value_synonym_id)->opcode());
   ASSERT_EQ(36, context->get_instr_block(value_synonym_id)->id());
-  ASSERT_EQ(SpvOpVariable,
+  ASSERT_EQ(spv::Op::OpVariable,
             context->get_def_use_mgr()->GetDef(variable_id)->opcode());
   ASSERT_EQ(5, context->get_instr_block(variable_id)->id());
   uint32_t variable_use_count = 0;
   context->get_def_use_mgr()->ForEachUse(
       variable_id,
       [&variable_use_count](opt::Instruction* inst, uint32_t /*unused*/) {
-        ASSERT_TRUE(inst->opcode() == SpvOpLoad ||
-                    inst->opcode() == SpvOpStore);
+        ASSERT_TRUE(inst->opcode() == spv::Op::OpLoad ||
+                    inst->opcode() == spv::Op::OpStore);
         variable_use_count++;
       });
   ASSERT_EQ(2, variable_use_count);
@@ -366,8 +376,9 @@
   value_synonym_id = 102;
   variable_id = 103;
   initializer_id = 21;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -377,8 +388,9 @@
   value_synonym_id = 104;
   variable_id = 105;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -388,8 +400,9 @@
   value_synonym_id = 106;
   variable_id = 107;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -399,8 +412,9 @@
   value_synonym_id = 108;
   variable_id = 109;
   initializer_id = 21;
-  variable_storage_class = SpvStorageClassPrivate;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Private;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -410,8 +424,8 @@
   value_synonym_id = 110;
   variable_id = 111;
   initializer_id = 21;
-  variable_storage_class = SpvStorageClassPrivate;
-  instruction_descriptor = MakeInstructionDescriptor(27, SpvOpStore, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Private;
+  instruction_descriptor = MakeInstructionDescriptor(27, spv::Op::OpStore, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -602,9 +616,9 @@
   uint32_t value_synonym_id = 62;
   uint32_t variable_id = 63;
   uint32_t initializer_id = 23;
-  uint32_t variable_storage_class = SpvStorageClassPrivate;
+  uint32_t variable_storage_class = (uint32_t)spv::StorageClass::Private;
   auto instruction_descriptor =
-      MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   auto transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -705,9 +719,9 @@
   uint32_t value_synonym_id = 62;
   uint32_t variable_id = 63;
   uint32_t initializer_id = 23;
-  uint32_t variable_storage_class = SpvStorageClassPrivate;
+  uint32_t variable_storage_class = (uint32_t)spv::StorageClass::Private;
   auto instruction_descriptor =
-      MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   auto transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -766,8 +780,8 @@
 
   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
   auto transformation = TransformationPushIdThroughVariable(
-      14, 100, 101, SpvStorageClassFunction, 14,
-      MakeInstructionDescriptor(15, SpvOpBranch, 0));
+      14, 100, 101, uint32_t(spv::StorageClass::Function), 14,
+      MakeInstructionDescriptor(15, spv::Op::OpBranch, 0));
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp
index b8c2a8a..65cf3d4 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp
@@ -167,34 +167,38 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   std::vector<protobufs::IdUseDescriptor> uses_of_true = {
-      MakeIdUseDescriptor(41, MakeInstructionDescriptor(44, SpvOpStore, 12), 1),
-      MakeIdUseDescriptor(41, MakeInstructionDescriptor(46, SpvOpLogicalOr, 0),
-                          0)};
+      MakeIdUseDescriptor(
+          41, MakeInstructionDescriptor(44, spv::Op::OpStore, 12), 1),
+      MakeIdUseDescriptor(
+          41, MakeInstructionDescriptor(46, spv::Op::OpLogicalOr, 0), 0)};
 
   std::vector<protobufs::IdUseDescriptor> uses_of_false = {
-      MakeIdUseDescriptor(43, MakeInstructionDescriptor(44, SpvOpStore, 13), 1),
-      MakeIdUseDescriptor(43, MakeInstructionDescriptor(48, SpvOpLogicalAnd, 0),
-                          1)};
+      MakeIdUseDescriptor(
+          43, MakeInstructionDescriptor(44, spv::Op::OpStore, 13), 1),
+      MakeIdUseDescriptor(
+          43, MakeInstructionDescriptor(48, spv::Op::OpLogicalAnd, 0), 1)};
 
   const uint32_t fresh_id = 100;
 
-  std::vector<SpvOp> fp_gt_opcodes = {
-      SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan,
-      SpvOpFUnordGreaterThanEqual};
+  std::vector<spv::Op> fp_gt_opcodes = {
+      spv::Op::OpFOrdGreaterThan, spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThan, spv::Op::OpFUnordGreaterThanEqual};
 
-  std::vector<SpvOp> fp_lt_opcodes = {SpvOpFOrdLessThan, SpvOpFOrdLessThanEqual,
-                                      SpvOpFUnordLessThan,
-                                      SpvOpFUnordLessThanEqual};
+  std::vector<spv::Op> fp_lt_opcodes = {
+      spv::Op::OpFOrdLessThan, spv::Op::OpFOrdLessThanEqual,
+      spv::Op::OpFUnordLessThan, spv::Op::OpFUnordLessThanEqual};
 
-  std::vector<SpvOp> int_gt_opcodes = {SpvOpSGreaterThan,
-                                       SpvOpSGreaterThanEqual};
+  std::vector<spv::Op> int_gt_opcodes = {spv::Op::OpSGreaterThan,
+                                         spv::Op::OpSGreaterThanEqual};
 
-  std::vector<SpvOp> int_lt_opcodes = {SpvOpSLessThan, SpvOpSLessThanEqual};
+  std::vector<spv::Op> int_lt_opcodes = {spv::Op::OpSLessThan,
+                                         spv::Op::OpSLessThanEqual};
 
-  std::vector<SpvOp> uint_gt_opcodes = {SpvOpUGreaterThan,
-                                        SpvOpUGreaterThanEqual};
+  std::vector<spv::Op> uint_gt_opcodes = {spv::Op::OpUGreaterThan,
+                                          spv::Op::OpUGreaterThanEqual};
 
-  std::vector<SpvOp> uint_lt_opcodes = {SpvOpULessThan, SpvOpULessThanEqual};
+  std::vector<spv::Op> uint_lt_opcodes = {spv::Op::OpULessThan,
+                                          spv::Op::OpULessThanEqual};
 
 #define CHECK_OPERATOR(USE_DESCRIPTOR, LHS_ID, RHS_ID, OPCODE, FRESH_ID) \
   ASSERT_TRUE(TransformationReplaceBooleanConstantWithConstantBinary(    \
@@ -253,41 +257,41 @@
 
   // Target id is not fresh
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 15, 17, SpvOpFOrdLessThan, 15)
+                   uses_of_true[0], 15, 17, spv::Op::OpFOrdLessThan, 15)
                    .IsApplicable(context.get(), transformation_context));
 
   // LHS id does not exist
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 300, 17, SpvOpFOrdLessThan, 200)
+                   uses_of_true[0], 300, 17, spv::Op::OpFOrdLessThan, 200)
                    .IsApplicable(context.get(), transformation_context));
 
   // RHS id does not exist
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 15, 300, SpvOpFOrdLessThan, 200)
+                   uses_of_true[0], 15, 300, spv::Op::OpFOrdLessThan, 200)
                    .IsApplicable(context.get(), transformation_context));
 
   // LHS and RHS ids do not match type
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 11, 17, SpvOpFOrdLessThan, 200)
+                   uses_of_true[0], 11, 17, spv::Op::OpFOrdLessThan, 200)
                    .IsApplicable(context.get(), transformation_context));
 
   // Opcode not appropriate
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 15, 17, SpvOpFDiv, 200)
+                   uses_of_true[0], 15, 17, spv::Op::OpFDiv, 200)
                    .IsApplicable(context.get(), transformation_context));
 
   auto replace_true_with_double_comparison =
       TransformationReplaceBooleanConstantWithConstantBinary(
-          uses_of_true[0], 11, 9, SpvOpFUnordGreaterThan, 100);
+          uses_of_true[0], 11, 9, spv::Op::OpFUnordGreaterThan, 100);
   auto replace_true_with_uint32_comparison =
       TransformationReplaceBooleanConstantWithConstantBinary(
-          uses_of_true[1], 27, 29, SpvOpULessThanEqual, 101);
+          uses_of_true[1], 27, 29, spv::Op::OpULessThanEqual, 101);
   auto replace_false_with_float_comparison =
       TransformationReplaceBooleanConstantWithConstantBinary(
-          uses_of_false[0], 17, 15, SpvOpFOrdLessThan, 102);
+          uses_of_false[0], 17, 15, spv::Op::OpFOrdLessThan, 102);
   auto replace_false_with_sint64_comparison =
       TransformationReplaceBooleanConstantWithConstantBinary(
-          uses_of_false[1], 33, 31, SpvOpSLessThan, 103);
+          uses_of_false[1], 33, 31, spv::Op::OpSLessThan, 103);
 
   ASSERT_TRUE(replace_true_with_double_comparison.IsApplicable(
       context.get(), transformation_context));
@@ -423,13 +427,13 @@
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[0]}},
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[1]}}};
     context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-        context.get(), SpvOpConstant, 6, 200, operands));
+        context.get(), spv::Op::OpConstant, 6, 200, operands));
     fuzzerutil::UpdateModuleIdBound(context.get(), 200);
     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
         context.get(), validator_options, kConsoleMessageConsumer));
     // The transformation is not applicable because %200 is NaN.
     ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                     uses_of_true[0], 11, 200, SpvOpFOrdLessThan, 300)
+                     uses_of_true[0], 11, 200, spv::Op::OpFOrdLessThan, 300)
                      .IsApplicable(context.get(), transformation_context));
   }
   if (std::numeric_limits<double>::has_infinity) {
@@ -440,14 +444,14 @@
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[0]}},
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[1]}}};
     context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-        context.get(), SpvOpConstant, 6, 201, operands));
+        context.get(), spv::Op::OpConstant, 6, 201, operands));
     fuzzerutil::UpdateModuleIdBound(context.get(), 201);
     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
         context.get(), validator_options, kConsoleMessageConsumer));
     // Even though the double constant %11 is less than the infinity %201, the
     // transformation is restricted to only apply to finite values.
     ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                     uses_of_true[0], 11, 201, SpvOpFOrdLessThan, 300)
+                     uses_of_true[0], 11, 201, spv::Op::OpFOrdLessThan, 300)
                      .IsApplicable(context.get(), transformation_context));
   }
   if (std::numeric_limits<float>::has_infinity) {
@@ -459,13 +463,14 @@
     memcpy(words_negative_infinity, &negative_infinity_float, sizeof(float));
     opt::Instruction::OperandList operands_positive_infinity = {
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words_positive_infinity[0]}}};
-    context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-        context.get(), SpvOpConstant, 12, 202, operands_positive_infinity));
+    context->module()->AddGlobalValue(
+        MakeUnique<opt::Instruction>(context.get(), spv::Op::OpConstant, 12,
+                                     202, operands_positive_infinity));
     fuzzerutil::UpdateModuleIdBound(context.get(), 202);
     opt::Instruction::OperandList operands = {
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words_negative_infinity[0]}}};
     context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-        context.get(), SpvOpConstant, 12, 203, operands));
+        context.get(), spv::Op::OpConstant, 12, 203, operands));
     fuzzerutil::UpdateModuleIdBound(context.get(), 203);
     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
         context.get(), validator_options, kConsoleMessageConsumer));
@@ -473,7 +478,7 @@
     // infinity %202, the transformation is restricted to only apply to finite
     // values.
     ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                     uses_of_true[0], 203, 202, SpvOpFOrdLessThan, 300)
+                     uses_of_true[0], 203, 202, spv::Op::OpFOrdLessThan, 300)
                      .IsApplicable(context.get(), transformation_context));
   }
 }
@@ -547,14 +552,14 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto use_of_true_in_if = MakeIdUseDescriptor(
-      13, MakeInstructionDescriptor(10, SpvOpBranchConditional, 0), 0);
+      13, MakeInstructionDescriptor(10, spv::Op::OpBranchConditional, 0), 0);
   auto use_of_false_in_while = MakeIdUseDescriptor(
-      21, MakeInstructionDescriptor(16, SpvOpBranchConditional, 0), 0);
+      21, MakeInstructionDescriptor(16, spv::Op::OpBranchConditional, 0), 0);
 
   auto replacement_1 = TransformationReplaceBooleanConstantWithConstantBinary(
-      use_of_true_in_if, 9, 11, SpvOpSLessThan, 100);
+      use_of_true_in_if, 9, 11, spv::Op::OpSLessThan, 100);
   auto replacement_2 = TransformationReplaceBooleanConstantWithConstantBinary(
-      use_of_false_in_while, 9, 11, SpvOpSGreaterThanEqual, 101);
+      use_of_false_in_while, 9, 11, spv::Op::OpSGreaterThanEqual, 101);
 
   ASSERT_TRUE(
       replacement_1.IsApplicable(context.get(), transformation_context));
@@ -662,10 +667,11 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto instruction_descriptor = MakeInstructionDescriptor(14, SpvOpPhi, 0);
+  auto instruction_descriptor =
+      MakeInstructionDescriptor(14, spv::Op::OpPhi, 0);
   auto id_use_descriptor = MakeIdUseDescriptor(8, instruction_descriptor, 0);
   auto transformation = TransformationReplaceBooleanConstantWithConstantBinary(
-      id_use_descriptor, 6, 7, SpvOpULessThan, 15);
+      id_use_descriptor, 6, 7, spv::Op::OpULessThan, 15);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -740,11 +746,12 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   MakeIdUseDescriptor(
-                       9, MakeInstructionDescriptor(50, SpvOpVariable, 0), 1),
-                   13, 15, SpvOpSLessThan, 100)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceBooleanConstantWithConstantBinary(
+          MakeIdUseDescriptor(
+              9, MakeInstructionDescriptor(50, spv::Op::OpVariable, 0), 1),
+          13, 15, spv::Op::OpSLessThan, 100)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp
index 6bba14f..012e317 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp
@@ -79,35 +79,37 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(20);
 
   // Bad: 4 is not a block
-  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(4, SpvOpKill, 0)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceBranchFromDeadBlockWithExit(4, spv::Op::OpKill, 0)
+          .IsApplicable(context.get(), transformation_context));
   // Bad: 200 does not exist
   ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(200, SpvOpKill, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(200, spv::Op::OpKill, 0)
           .IsApplicable(context.get(), transformation_context));
   // Bad: 21 is not a dead block
   ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(21, SpvOpKill, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(21, spv::Op::OpKill, 0)
           .IsApplicable(context.get(), transformation_context));
   // Bad: terminator of 8 is not OpBranch
-  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(8, SpvOpKill, 0)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceBranchFromDeadBlockWithExit(8, spv::Op::OpKill, 0)
+          .IsApplicable(context.get(), transformation_context));
   // Bad: 10's successor only has 10 as a predecessor
   ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(10, SpvOpKill, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(10, spv::Op::OpKill, 0)
           .IsApplicable(context.get(), transformation_context));
 
 #ifndef NDEBUG
   ASSERT_DEATH(
-      TransformationReplaceBranchFromDeadBlockWithExit(20, SpvOpSwitch, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(20, spv::Op::OpSwitch, 0)
           .IsApplicable(context.get(), transformation_context),
       "Invalid early exit opcode.");
 #endif
 
   auto transformation1 =
-      TransformationReplaceBranchFromDeadBlockWithExit(20, SpvOpKill, 0);
+      TransformationReplaceBranchFromDeadBlockWithExit(20, spv::Op::OpKill, 0);
   auto transformation2 =
-      TransformationReplaceBranchFromDeadBlockWithExit(16, SpvOpKill, 0);
+      TransformationReplaceBranchFromDeadBlockWithExit(16, spv::Op::OpKill, 0);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
@@ -281,48 +283,48 @@
 
   // Bad: OpKill not allowed in vertex shader
   ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(201, SpvOpKill, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(201, spv::Op::OpKill, 0)
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: OpReturn is not allowed in function that expects a returned value.
-  ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(200, SpvOpReturn, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
+                   200, spv::Op::OpReturn, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Return value id does not exist
   ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
-                   201, SpvOpReturnValue, 1000)
+                   201, spv::Op::OpReturnValue, 1000)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: Return value id does not have a type
-  ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(200, SpvOpReturnValue, 6)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
+                   200, spv::Op::OpReturnValue, 6)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Return value id does not have the right type
   ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
-                   201, SpvOpReturnValue, 48)
+                   201, spv::Op::OpReturnValue, 48)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: Return value id is not available
   ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
-                   200, SpvOpReturnValue, 400)
+                   200, spv::Op::OpReturnValue, 400)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: Early exit now allowed in continue construct
-  ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(101, SpvOpUnreachable, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
+                   101, spv::Op::OpUnreachable, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Early exit now allowed in continue construct (again)
   ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
-                   300, SpvOpReturnValue, 14)
+                   300, spv::Op::OpReturnValue, 14)
                    .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationReplaceBranchFromDeadBlockWithExit(
-      200, SpvOpUnreachable, 0);
+      200, spv::Op::OpUnreachable, 0);
   auto transformation2 = TransformationReplaceBranchFromDeadBlockWithExit(
-      201, SpvOpReturnValue, 400);
+      201, spv::Op::OpReturnValue, 400);
 
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
@@ -339,7 +341,7 @@
 
   opt::Instruction* return_value_inst =
       context->get_instr_block(201)->terminator();
-  ASSERT_EQ(SpvOpReturnValue, return_value_inst->opcode());
+  ASSERT_EQ(spv::Op::OpReturnValue, return_value_inst->opcode());
   ASSERT_EQ(SPV_OPERAND_TYPE_ID, return_value_inst->GetInOperand(0).type);
   ASSERT_EQ(400, return_value_inst->GetSingleWordInOperand(0));
 
@@ -504,9 +506,9 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(20);
 
   auto transformation1 =
-      TransformationReplaceBranchFromDeadBlockWithExit(20, SpvOpKill, 0);
+      TransformationReplaceBranchFromDeadBlockWithExit(20, spv::Op::OpKill, 0);
   auto transformation2 =
-      TransformationReplaceBranchFromDeadBlockWithExit(16, SpvOpKill, 0);
+      TransformationReplaceBranchFromDeadBlockWithExit(16, spv::Op::OpKill, 0);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
@@ -609,9 +611,9 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(9);
   transformation_context.GetFactManager()->AddFactBlockIsDead(11);
 
-  ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(11, SpvOpUnreachable, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
+                   11, spv::Op::OpUnreachable, 0)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceBranchFromDeadBlockWithExitTest,
@@ -658,7 +660,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(11);
 
   TransformationReplaceBranchFromDeadBlockWithExit transformation(
-      11, SpvOpUnreachable, 0);
+      11, spv::Op::OpUnreachable, 0);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   transformation.Apply(context.get(), &transformation_context);
@@ -741,7 +743,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(13);
 
   TransformationReplaceBranchFromDeadBlockWithExit transformation(
-      13, SpvOpUnreachable, 0);
+      13, spv::Op::OpUnreachable, 0);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   transformation.Apply(context.get(), &transformation_context);
@@ -823,7 +825,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(10);
 
   TransformationReplaceBranchFromDeadBlockWithExit transformation(
-      10, SpvOpUnreachable, 0);
+      10, spv::Op::OpUnreachable, 0);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   transformation.Apply(context.get(), &transformation_context);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_constant_with_uniform_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
index fe76068..7c6d126 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
@@ -121,12 +121,12 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 3, blockname_c));
 
   // The constant ids are 9, 11 and 14, for 1, 2 and 3 respectively.
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
-  protobufs::IdUseDescriptor use_of_11_in_add =
-      MakeIdUseDescriptor(11, MakeInstructionDescriptor(12, SpvOpIAdd, 0), 1);
-  protobufs::IdUseDescriptor use_of_14_in_add =
-      MakeIdUseDescriptor(14, MakeInstructionDescriptor(15, SpvOpIAdd, 0), 0);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_11_in_add = MakeIdUseDescriptor(
+      11, MakeInstructionDescriptor(12, spv::Op::OpIAdd, 0), 1);
+  protobufs::IdUseDescriptor use_of_14_in_add = MakeIdUseDescriptor(
+      14, MakeInstructionDescriptor(15, spv::Op::OpIAdd, 0), 0);
 
   // These transformations work: they match the facts.
   auto transformation_use_of_9_in_store =
@@ -172,8 +172,8 @@
 
   // The following transformation does not apply because the id descriptor is
   // not sensible.
-  protobufs::IdUseDescriptor nonsense_id_use_descriptor =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(15, SpvOpIAdd, 0), 0);
+  protobufs::IdUseDescriptor nonsense_id_use_descriptor = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(15, spv::Op::OpIAdd, 0), 0);
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(
                    nonsense_id_use_descriptor, blockname_a, 101, 102)
                    .IsApplicable(context.get(), transformation_context));
@@ -490,14 +490,14 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 4, blockname_4));
 
   // The constant ids are 13, 15, 17 and 20, for 1, 2, 3 and 4 respectively.
-  protobufs::IdUseDescriptor use_of_13_in_store =
-      MakeIdUseDescriptor(13, MakeInstructionDescriptor(21, SpvOpStore, 0), 1);
-  protobufs::IdUseDescriptor use_of_15_in_add =
-      MakeIdUseDescriptor(15, MakeInstructionDescriptor(16, SpvOpIAdd, 0), 1);
-  protobufs::IdUseDescriptor use_of_17_in_add =
-      MakeIdUseDescriptor(17, MakeInstructionDescriptor(19, SpvOpIAdd, 0), 0);
-  protobufs::IdUseDescriptor use_of_20_in_store =
-      MakeIdUseDescriptor(20, MakeInstructionDescriptor(19, SpvOpStore, 1), 1);
+  protobufs::IdUseDescriptor use_of_13_in_store = MakeIdUseDescriptor(
+      13, MakeInstructionDescriptor(21, spv::Op::OpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_15_in_add = MakeIdUseDescriptor(
+      15, MakeInstructionDescriptor(16, spv::Op::OpIAdd, 0), 1);
+  protobufs::IdUseDescriptor use_of_17_in_add = MakeIdUseDescriptor(
+      17, MakeInstructionDescriptor(19, spv::Op::OpIAdd, 0), 0);
+  protobufs::IdUseDescriptor use_of_20_in_store = MakeIdUseDescriptor(
+      20, MakeInstructionDescriptor(19, spv::Op::OpStore, 1), 1);
 
   // These transformations work: they match the facts.
   auto transformation_use_of_13_in_store =
@@ -726,8 +726,8 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 0, blockname_0));
 
   // The constant id is 9 for 0.
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 1);
 
   // This transformation is not available because no uniform pointer to integer
   // type is present:
@@ -803,8 +803,8 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 9, blockname_9));
 
   // The constant id is 9 for 9.
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 1);
 
   // This transformation is not available because no constant is present for the
   // index 1 required to index into the uniform buffer:
@@ -879,8 +879,8 @@
       AddFactHelper(&transformation_context, float_data[0], blockname_3));
 
   // The constant id is 9 for 3.0.
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 1);
 
   // This transformation is not available because no integer type is present to
   // allow a constant index to be expressed:
@@ -966,10 +966,10 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 10, blockname_10));
 
   // The constant ids for 9 and 10 are 9 and 11 respectively
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(10, SpvOpStore, 0), 1);
-  protobufs::IdUseDescriptor use_of_11_in_store =
-      MakeIdUseDescriptor(11, MakeInstructionDescriptor(10, SpvOpStore, 1), 1);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(10, spv::Op::OpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_11_in_store = MakeIdUseDescriptor(
+      11, MakeInstructionDescriptor(10, spv::Op::OpStore, 1), 1);
 
   // These are right:
   ASSERT_TRUE(TransformationReplaceConstantWithUniform(use_of_9_in_store,
@@ -1251,57 +1251,73 @@
   std::vector<TransformationReplaceConstantWithUniform> transformations;
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(18, MakeInstructionDescriptor(20, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          18, MakeInstructionDescriptor(20, spv::Op::OpStore, 0), 1),
       uniform_f_a_4, 200, 201));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(22, MakeInstructionDescriptor(23, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          22, MakeInstructionDescriptor(23, spv::Op::OpStore, 0), 1),
       uniform_f_a_3, 202, 203));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(25, MakeInstructionDescriptor(26, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          25, MakeInstructionDescriptor(26, spv::Op::OpStore, 0), 1),
       uniform_f_a_2, 204, 205));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(28, MakeInstructionDescriptor(29, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          28, MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 1),
       uniform_f_a_1, 206, 207));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(31, MakeInstructionDescriptor(32, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          31, MakeInstructionDescriptor(32, spv::Op::OpStore, 0), 1),
       uniform_f_a_0, 208, 209));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(30, MakeInstructionDescriptor(35, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          30, MakeInstructionDescriptor(35, spv::Op::OpStore, 0), 1),
       uniform_f_b_w, 210, 211));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(27, MakeInstructionDescriptor(37, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          27, MakeInstructionDescriptor(37, spv::Op::OpStore, 0), 1),
       uniform_f_b_z, 212, 213));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(24, MakeInstructionDescriptor(39, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          24, MakeInstructionDescriptor(39, spv::Op::OpStore, 0), 1),
       uniform_f_b_y, 214, 215));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(21, MakeInstructionDescriptor(41, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          21, MakeInstructionDescriptor(41, spv::Op::OpStore, 0), 1),
       uniform_f_b_x, 216, 217));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(44, MakeInstructionDescriptor(45, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          44, MakeInstructionDescriptor(45, spv::Op::OpStore, 0), 1),
       uniform_f_c_z, 220, 221));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(46, MakeInstructionDescriptor(47, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          46, MakeInstructionDescriptor(47, spv::Op::OpStore, 0), 1),
       uniform_f_c_y, 222, 223));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(48, MakeInstructionDescriptor(49, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          48, MakeInstructionDescriptor(49, spv::Op::OpStore, 0), 1),
       uniform_f_c_x, 224, 225));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(50, MakeInstructionDescriptor(52, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          50, MakeInstructionDescriptor(52, spv::Op::OpStore, 0), 1),
       uniform_f_d, 226, 227));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(53, MakeInstructionDescriptor(54, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          53, MakeInstructionDescriptor(54, spv::Op::OpStore, 0), 1),
       uniform_h_x, 228, 229));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(55, MakeInstructionDescriptor(56, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          55, MakeInstructionDescriptor(56, spv::Op::OpStore, 0), 1),
       uniform_h_y, 230, 231));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(42, MakeInstructionDescriptor(43, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          42, MakeInstructionDescriptor(43, spv::Op::OpStore, 0), 1),
       uniform_g, 218, 219));
 
   for (auto& transformation : transformations) {
@@ -1520,11 +1536,12 @@
 
   ASSERT_TRUE(AddFactHelper(&transformation_context, 0, blockname_a));
 
-  ASSERT_FALSE(TransformationReplaceConstantWithUniform(
-                   MakeIdUseDescriptor(
-                       50, MakeInstructionDescriptor(8, SpvOpVariable, 0), 1),
-                   blockname_a, 100, 101)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceConstantWithUniform(
+          MakeIdUseDescriptor(
+              50, MakeInstructionDescriptor(8, spv::Op::OpVariable, 0), 1),
+          blockname_a, 100, 101)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceConstantWithUniformTest, ReplaceOpPhiOperand) {
@@ -1579,7 +1596,8 @@
 
   {
     TransformationReplaceConstantWithUniform transformation(
-        MakeIdUseDescriptor(7, MakeInstructionDescriptor(23, SpvOpPhi, 0), 0),
+        MakeIdUseDescriptor(7, MakeInstructionDescriptor(23, spv::Op::OpPhi, 0),
+                            0),
         int_descriptor, 50, 51);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_copy_memory_with_load_store_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_copy_memory_with_load_store_test.cpp
index bcd04af..689cf19 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_copy_memory_with_load_store_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_copy_memory_with_load_store_test.cpp
@@ -75,11 +75,11 @@
                                                kConsoleMessageConsumer));
 
   auto instruction_descriptor_invalid_1 =
-      MakeInstructionDescriptor(5, SpvOpStore, 0);
+      MakeInstructionDescriptor(5, spv::Op::OpStore, 0);
   auto instruction_descriptor_valid_1 =
-      MakeInstructionDescriptor(5, SpvOpCopyMemory, 0);
+      MakeInstructionDescriptor(5, spv::Op::OpCopyMemory, 0);
   auto instruction_descriptor_valid_2 =
-      MakeInstructionDescriptor(5, SpvOpCopyMemory, 0);
+      MakeInstructionDescriptor(5, spv::Op::OpCopyMemory, 0);
 
   // Invalid: |source_id| is not a fresh id.
   auto transformation_invalid_1 = TransformationReplaceCopyMemoryWithLoadStore(
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_copy_object_with_store_load_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_copy_object_with_store_load_test.cpp
index fa8c068..368e208 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_copy_object_with_store_load_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_copy_object_with_store_load_test.cpp
@@ -88,44 +88,45 @@
 
   // Invalid: fresh_variable_id=10 is not fresh.
   auto transformation_invalid_1 = TransformationReplaceCopyObjectWithStoreLoad(
-      27, 10, SpvStorageClassFunction, 9);
+      27, 10, (uint32_t)spv::StorageClass::Function, 9);
   ASSERT_FALSE(transformation_invalid_1.IsApplicable(context.get(),
                                                      transformation_context));
 
   // Invalid: copy_object_result_id=26 is not a CopyObject instruction.
   auto transformation_invalid_2 = TransformationReplaceCopyObjectWithStoreLoad(
-      26, 30, SpvStorageClassFunction, 9);
+      26, 30, (uint32_t)spv::StorageClass::Function, 9);
   ASSERT_FALSE(transformation_invalid_2.IsApplicable(context.get(),
                                                      transformation_context));
 
   // Invalid: copy_object_result_id=40 is of type pointer.
   auto transformation_invalid_3 = TransformationReplaceCopyObjectWithStoreLoad(
-      40, 30, SpvStorageClassFunction, 9);
+      40, 30, (uint32_t)spv::StorageClass::Function, 9);
   ASSERT_FALSE(transformation_invalid_3.IsApplicable(context.get(),
                                                      transformation_context));
 
   // Invalid: Pointer type instruction in this storage class pointing to the
   // value type is not defined.
   auto transformation_invalid_4 = TransformationReplaceCopyObjectWithStoreLoad(
-      40, 30, SpvStorageClassPrivate, 9);
+      40, 30, (uint32_t)spv::StorageClass::Private, 9);
   ASSERT_FALSE(transformation_invalid_4.IsApplicable(context.get(),
                                                      transformation_context));
 
   // Invalid: initializer_id=15 has the wrong type relative to the OpCopyObject
   // instruction.
   auto transformation_invalid_5 = TransformationReplaceCopyObjectWithStoreLoad(
-      27, 30, SpvStorageClassFunction, 15);
+      27, 30, (uint32_t)spv::StorageClass::Function, 15);
   ASSERT_FALSE(transformation_invalid_5.IsApplicable(context.get(),
                                                      transformation_context));
 
-  // Invalid: SpvStorageClassUniform is not applicable to the transformation.
+  // Invalid: spv::StorageClass::Uniform is not applicable to the
+  // transformation.
   auto transformation_invalid_6 = TransformationReplaceCopyObjectWithStoreLoad(
-      27, 30, SpvStorageClassUniform, 9);
+      27, 30, (uint32_t)spv::StorageClass::Uniform, 9);
   ASSERT_FALSE(transformation_invalid_6.IsApplicable(context.get(),
                                                      transformation_context));
 
   auto transformation_valid_1 = TransformationReplaceCopyObjectWithStoreLoad(
-      27, 30, SpvStorageClassFunction, 9);
+      27, 30, (uint32_t)spv::StorageClass::Function, 9);
   ASSERT_TRUE(transformation_valid_1.IsApplicable(context.get(),
                                                   transformation_context));
   ApplyAndCheckFreshIds(transformation_valid_1, context.get(),
@@ -134,7 +135,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation_valid_2 = TransformationReplaceCopyObjectWithStoreLoad(
-      28, 32, SpvStorageClassPrivate, 15);
+      28, 32, (uint32_t)spv::StorageClass::Private, 15);
   ASSERT_TRUE(transformation_valid_2.IsApplicable(context.get(),
                                                   transformation_context));
   ApplyAndCheckFreshIds(transformation_valid_2, context.get(),
@@ -244,7 +245,7 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(11);
 
   auto transformation_1 = TransformationReplaceCopyObjectWithStoreLoad(
-      50, 100, SpvStorageClassFunction, 10);
+      50, 100, (uint32_t)spv::StorageClass::Function, 10);
   ASSERT_TRUE(
       transformation_1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_1, context.get(),
@@ -253,7 +254,7 @@
       MakeDataDescriptor(100, {}), MakeDataDescriptor(50, {})));
 
   auto transformation_2 = TransformationReplaceCopyObjectWithStoreLoad(
-      51, 101, SpvStorageClassFunction, 10);
+      51, 101, (uint32_t)spv::StorageClass::Function, 10);
   ASSERT_TRUE(
       transformation_2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_2, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_id_with_synonym_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_id_with_synonym_test.cpp
index b33dd48..bd27c29 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_id_with_synonym_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_id_with_synonym_test.cpp
@@ -230,7 +230,8 @@
   // %202 cannot replace %15 as in-operand 0 of %300, since %202 does not
   // dominate %300.
   auto synonym_does_not_dominate_use = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(15, MakeInstructionDescriptor(300, SpvOpIAdd, 0), 0),
+      MakeIdUseDescriptor(
+          15, MakeInstructionDescriptor(300, spv::Op::OpIAdd, 0), 0),
       202);
   ASSERT_FALSE(synonym_does_not_dominate_use.IsApplicable(
       context.get(), transformation_context));
@@ -239,8 +240,8 @@
   // incoming value for block %72, and %202 does not dominate %72.
   auto synonym_does_not_dominate_use_op_phi =
       TransformationReplaceIdWithSynonym(
-          MakeIdUseDescriptor(15, MakeInstructionDescriptor(301, SpvOpPhi, 0),
-                              2),
+          MakeIdUseDescriptor(
+              15, MakeInstructionDescriptor(301, spv::Op::OpPhi, 0), 2),
           202);
   ASSERT_FALSE(synonym_does_not_dominate_use_op_phi.IsApplicable(
       context.get(), transformation_context));
@@ -248,14 +249,15 @@
   // %200 is not a synonym for %84
   auto id_in_use_is_not_synonymous = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          84, MakeInstructionDescriptor(67, SpvOpSGreaterThan, 0), 0),
+          84, MakeInstructionDescriptor(67, spv::Op::OpSGreaterThan, 0), 0),
       200);
   ASSERT_FALSE(id_in_use_is_not_synonymous.IsApplicable(
       context.get(), transformation_context));
 
   // %86 is not a synonym for anything (and in particular not for %74)
   auto id_has_no_synonyms = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(86, MakeInstructionDescriptor(84, SpvOpPhi, 0), 2),
+      MakeIdUseDescriptor(86, MakeInstructionDescriptor(84, spv::Op::OpPhi, 0),
+                          2),
       74);
   ASSERT_FALSE(
       id_has_no_synonyms.IsApplicable(context.get(), transformation_context));
@@ -264,7 +266,7 @@
   auto synonym_use_is_in_synonym_definition =
       TransformationReplaceIdWithSynonym(
           MakeIdUseDescriptor(
-              84, MakeInstructionDescriptor(207, SpvOpCopyObject, 0), 0),
+              84, MakeInstructionDescriptor(207, spv::Op::OpCopyObject, 0), 0),
           207);
   ASSERT_FALSE(synonym_use_is_in_synonym_definition.IsApplicable(
       context.get(), transformation_context));
@@ -273,7 +275,7 @@
   // definition of %207)
   auto bad_id_use_descriptor = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          84, MakeInstructionDescriptor(200, SpvOpCopyObject, 0), 0),
+          84, MakeInstructionDescriptor(200, spv::Op::OpCopyObject, 0), 0),
       207);
   ASSERT_FALSE(bad_id_use_descriptor.IsApplicable(context.get(),
                                                   transformation_context));
@@ -282,7 +284,7 @@
   // non-constant index.
   auto bad_access_chain = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          12, MakeInstructionDescriptor(14, SpvOpAccessChain, 0), 1),
+          12, MakeInstructionDescriptor(14, spv::Op::OpAccessChain, 0), 1),
       209);
   ASSERT_FALSE(
       bad_access_chain.IsApplicable(context.get(), transformation_context));
@@ -301,7 +303,8 @@
   SetUpIdSynonyms(transformation_context.GetFactManager());
 
   auto global_constant_synonym = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(19, MakeInstructionDescriptor(47, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          19, MakeInstructionDescriptor(47, spv::Op::OpStore, 0), 1),
       210);
   uint32_t num_uses_of_original_id_before_replacement =
       context->get_def_use_mgr()->NumUses(19);
@@ -320,7 +323,7 @@
 
   auto replace_vector_access_chain_index = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          54, MakeInstructionDescriptor(55, SpvOpAccessChain, 0), 1),
+          54, MakeInstructionDescriptor(55, spv::Op::OpAccessChain, 0), 1),
       204);
   ASSERT_TRUE(replace_vector_access_chain_index.IsApplicable(
       context.get(), transformation_context));
@@ -333,7 +336,7 @@
   // copied with something that is already a synonym.
   auto regular_replacement = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          15, MakeInstructionDescriptor(202, SpvOpCopyObject, 0), 0),
+          15, MakeInstructionDescriptor(202, spv::Op::OpCopyObject, 0), 0),
       201);
   ASSERT_TRUE(
       regular_replacement.IsApplicable(context.get(), transformation_context));
@@ -343,7 +346,8 @@
                                                kConsoleMessageConsumer));
 
   auto regular_replacement2 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(55, MakeInstructionDescriptor(203, SpvOpStore, 0), 0),
+      MakeIdUseDescriptor(
+          55, MakeInstructionDescriptor(203, spv::Op::OpStore, 0), 0),
       203);
   ASSERT_TRUE(
       regular_replacement2.IsApplicable(context.get(), transformation_context));
@@ -353,7 +357,8 @@
                                                kConsoleMessageConsumer));
 
   auto good_op_phi = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(74, MakeInstructionDescriptor(86, SpvOpPhi, 0), 2),
+      MakeIdUseDescriptor(74, MakeInstructionDescriptor(86, spv::Op::OpPhi, 0),
+                          2),
       205);
   ASSERT_TRUE(good_op_phi.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(good_op_phi, context.get(), &transformation_context);
@@ -543,7 +548,8 @@
   // Replace %10 with %100 in:
   // %11 = OpLoad %6 %10
   auto replacement1 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(11, SpvOpLoad, 0), 0),
+      MakeIdUseDescriptor(10, MakeInstructionDescriptor(11, spv::Op::OpLoad, 0),
+                          0),
       100);
   ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement1, context.get(), &transformation_context);
@@ -553,7 +559,8 @@
   // Replace %8 with %101 in:
   // OpStore %8 %11
   auto replacement2 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(8, MakeInstructionDescriptor(11, SpvOpStore, 0), 0),
+      MakeIdUseDescriptor(8, MakeInstructionDescriptor(11, spv::Op::OpStore, 0),
+                          0),
       101);
   ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement2, context.get(), &transformation_context);
@@ -563,7 +570,8 @@
   // Replace %8 with %101 in:
   // %12 = OpLoad %6 %8
   auto replacement3 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(8, MakeInstructionDescriptor(12, SpvOpLoad, 0), 0),
+      MakeIdUseDescriptor(8, MakeInstructionDescriptor(12, spv::Op::OpLoad, 0),
+                          0),
       101);
   ASSERT_TRUE(replacement3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement3, context.get(), &transformation_context);
@@ -573,7 +581,8 @@
   // Replace %10 with %100 in:
   // OpStore %10 %12
   auto replacement4 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(12, SpvOpStore, 0), 0),
+      MakeIdUseDescriptor(
+          10, MakeInstructionDescriptor(12, spv::Op::OpStore, 0), 0),
       100);
   ASSERT_TRUE(replacement4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement4, context.get(), &transformation_context);
@@ -678,7 +687,7 @@
   // %16 = OpFunctionCall %2 %10 %14
   auto replacement = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          14, MakeInstructionDescriptor(16, SpvOpFunctionCall, 0), 1),
+          14, MakeInstructionDescriptor(16, spv::Op::OpFunctionCall, 0), 1),
       100);
   ASSERT_FALSE(replacement.IsApplicable(context.get(), transformation_context));
 }
@@ -871,7 +880,7 @@
   // The index %16 used for a cannot be replaced
   auto replacement1 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 1),
+          16, MakeInstructionDescriptor(20, spv::Op::OpAccessChain, 0), 1),
       100);
   ASSERT_FALSE(
       replacement1.IsApplicable(context.get(), transformation_context));
@@ -881,7 +890,7 @@
   // The index %16 used for f cannot be replaced
   auto replacement2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(39, SpvOpAccessChain, 0), 1),
+          16, MakeInstructionDescriptor(39, spv::Op::OpAccessChain, 0), 1),
       100);
   ASSERT_FALSE(
       replacement2.IsApplicable(context.get(), transformation_context));
@@ -891,7 +900,7 @@
   // The index %16 used for a cannot be replaced
   auto replacement3 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 2),
+          16, MakeInstructionDescriptor(41, spv::Op::OpAccessChain, 0), 2),
       100);
   ASSERT_FALSE(
       replacement3.IsApplicable(context.get(), transformation_context));
@@ -901,7 +910,7 @@
   // The index %16 used for 0 *can* be replaced
   auto replacement4 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 1),
+          16, MakeInstructionDescriptor(52, spv::Op::OpAccessChain, 0), 1),
       100);
   ASSERT_TRUE(replacement4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement4, context.get(), &transformation_context);
@@ -913,7 +922,7 @@
   // The index %16 used for f cannot be replaced
   auto replacement5 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 2),
+          16, MakeInstructionDescriptor(52, spv::Op::OpAccessChain, 0), 2),
       100);
   ASSERT_FALSE(
       replacement5.IsApplicable(context.get(), transformation_context));
@@ -923,7 +932,7 @@
   // The index %16 used for a cannot be replaced
   auto replacement6 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 3),
+          16, MakeInstructionDescriptor(53, spv::Op::OpAccessChain, 0), 3),
       100);
   ASSERT_FALSE(
       replacement6.IsApplicable(context.get(), transformation_context));
@@ -933,7 +942,7 @@
   // The index %16 used for 0 *can* be replaced
   auto replacement7 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 4),
+          16, MakeInstructionDescriptor(53, spv::Op::OpAccessChain, 0), 4),
       100);
   ASSERT_TRUE(replacement7.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement7, context.get(), &transformation_context);
@@ -947,7 +956,7 @@
   // The index %24 used for b cannot be replaced
   auto replacement8 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_FALSE(
       replacement8.IsApplicable(context.get(), transformation_context));
@@ -957,7 +966,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement9 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(41, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_FALSE(
       replacement9.IsApplicable(context.get(), transformation_context));
@@ -967,7 +976,7 @@
   // The index %24 used for 1 *can* be replaced
   auto replacement10 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 3),
+          21, MakeInstructionDescriptor(41, spv::Op::OpAccessChain, 0), 3),
       101);
   ASSERT_TRUE(
       replacement10.IsApplicable(context.get(), transformation_context));
@@ -980,7 +989,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement11 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(44, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_FALSE(
       replacement11.IsApplicable(context.get(), transformation_context));
@@ -990,7 +999,7 @@
   // The index %24 used for b cannot be replaced
   auto replacement12 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 2),
+          21, MakeInstructionDescriptor(44, spv::Op::OpAccessChain, 0), 2),
       101);
   ASSERT_FALSE(
       replacement12.IsApplicable(context.get(), transformation_context));
@@ -1000,7 +1009,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement13 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_FALSE(
       replacement13.IsApplicable(context.get(), transformation_context));
@@ -1010,7 +1019,7 @@
   // The index %24 used for 1 *can* be replaced
   auto replacement14 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(53, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_TRUE(
       replacement14.IsApplicable(context.get(), transformation_context));
@@ -1023,7 +1032,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement15 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 2),
+          21, MakeInstructionDescriptor(53, spv::Op::OpAccessChain, 0), 2),
       101);
   ASSERT_FALSE(
       replacement15.IsApplicable(context.get(), transformation_context));
@@ -1033,7 +1042,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement16 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 2),
+          21, MakeInstructionDescriptor(56, spv::Op::OpAccessChain, 0), 2),
       101);
   ASSERT_FALSE(
       replacement16.IsApplicable(context.get(), transformation_context));
@@ -1043,7 +1052,7 @@
   // The index %24 used for b cannot be replaced
   auto replacement17 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 3),
+          21, MakeInstructionDescriptor(56, spv::Op::OpAccessChain, 0), 3),
       101);
   ASSERT_FALSE(
       replacement17.IsApplicable(context.get(), transformation_context));
@@ -1053,7 +1062,8 @@
   // The index %24 used for g cannot be replaced
   auto replacement18 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(58, SpvOpInBoundsAccessChain, 0), 2),
+          21, MakeInstructionDescriptor(58, spv::Op::OpInBoundsAccessChain, 0),
+          2),
       101);
   ASSERT_FALSE(
       replacement18.IsApplicable(context.get(), transformation_context));
@@ -1065,7 +1075,7 @@
   // The index %17 used for 2 *can* be replaced
   auto replacement19 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 2),
+          17, MakeInstructionDescriptor(20, spv::Op::OpAccessChain, 0), 2),
       102);
   ASSERT_TRUE(
       replacement19.IsApplicable(context.get(), transformation_context));
@@ -1078,7 +1088,7 @@
   // The index %17 used for c cannot be replaced
   auto replacement20 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(27, SpvOpAccessChain, 0), 1),
+          17, MakeInstructionDescriptor(27, spv::Op::OpAccessChain, 0), 1),
       102);
   ASSERT_FALSE(
       replacement20.IsApplicable(context.get(), transformation_context));
@@ -1088,7 +1098,7 @@
   // The index %17 used for c cannot be replaced
   auto replacement21 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 2),
+          17, MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 2),
       102);
   ASSERT_FALSE(
       replacement21.IsApplicable(context.get(), transformation_context));
@@ -1098,7 +1108,7 @@
   // The index %17 used for 2 *can* be replaced
   auto replacement22 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 1),
+          17, MakeInstructionDescriptor(56, spv::Op::OpAccessChain, 0), 1),
       102);
   ASSERT_TRUE(
       replacement22.IsApplicable(context.get(), transformation_context));
@@ -1111,7 +1121,8 @@
   // The index %17 used for c cannot be replaced
   auto replacement23 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(58, SpvOpInBoundsAccessChain, 0), 3),
+          17, MakeInstructionDescriptor(58, spv::Op::OpInBoundsAccessChain, 0),
+          3),
       102);
   ASSERT_FALSE(
       replacement23.IsApplicable(context.get(), transformation_context));
@@ -1123,7 +1134,8 @@
   // The index %57 used for 3 *can* be replaced
   auto replacement24 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          57, MakeInstructionDescriptor(58, SpvOpInBoundsAccessChain, 0), 1),
+          57, MakeInstructionDescriptor(58, spv::Op::OpInBoundsAccessChain, 0),
+          1),
       103);
   ASSERT_TRUE(
       replacement24.IsApplicable(context.get(), transformation_context));
@@ -1138,7 +1150,7 @@
   // The index %32 used for 17 *can* be replaced
   auto replacement25 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          32, MakeInstructionDescriptor(34, SpvOpAccessChain, 0), 1),
+          32, MakeInstructionDescriptor(34, spv::Op::OpAccessChain, 0), 1),
       106);
   ASSERT_TRUE(
       replacement25.IsApplicable(context.get(), transformation_context));
@@ -1153,7 +1165,7 @@
   // The index %43 used for 0 *can* be replaced
   auto replacement26 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          43, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 3),
+          43, MakeInstructionDescriptor(44, spv::Op::OpAccessChain, 0), 3),
       107);
   ASSERT_TRUE(
       replacement26.IsApplicable(context.get(), transformation_context));
@@ -1168,7 +1180,7 @@
   // The index %55 used for 1 *can* be replaced
   auto replacement27 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          55, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 4),
+          55, MakeInstructionDescriptor(56, spv::Op::OpAccessChain, 0), 4),
       108);
   ASSERT_TRUE(
       replacement27.IsApplicable(context.get(), transformation_context));
@@ -1182,8 +1194,8 @@
   // Corresponds to d.b[*3*]
   // The index %8 used for 3 *can* be replaced
   auto replacement28 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(8, MakeInstructionDescriptor(24, SpvOpAccessChain, 0),
-                          2),
+      MakeIdUseDescriptor(
+          8, MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0), 2),
       109);
   ASSERT_TRUE(
       replacement28.IsApplicable(context.get(), transformation_context));
@@ -1356,14 +1368,14 @@
   ASSERT_FALSE(
       TransformationReplaceIdWithSynonym(
           MakeIdUseDescriptor(
-              12, MakeInstructionDescriptor(16, SpvOpAccessChain, 0), 1),
+              12, MakeInstructionDescriptor(16, spv::Op::OpAccessChain, 0), 1),
           50)
           .IsApplicable(context.get(), transformation_context));
 
   // Fine to replace an index into a runtime array.
   auto replacement1 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          12, MakeInstructionDescriptor(16, SpvOpAccessChain, 0), 2),
+          12, MakeInstructionDescriptor(16, spv::Op::OpAccessChain, 0), 2),
       50);
   ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement1, context.get(), &transformation_context);
@@ -1371,7 +1383,7 @@
   // Fine to replace an index into a vector inside the runtime array.
   auto replacement2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          14, MakeInstructionDescriptor(16, SpvOpAccessChain, 0), 3),
+          14, MakeInstructionDescriptor(16, spv::Op::OpAccessChain, 0), 3),
       51);
   ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement2, context.get(), &transformation_context);
@@ -1466,7 +1478,8 @@
   ASSERT_FALSE(
       TransformationReplaceIdWithSynonym(
           MakeIdUseDescriptor(
-              9, MakeInstructionDescriptor(20, SpvOpImageTexelPointer, 0), 2),
+              9, MakeInstructionDescriptor(20, spv::Op::OpImageTexelPointer, 0),
+              2),
           100)
           .IsApplicable(context.get(), transformation_context));
 }
@@ -1524,56 +1537,61 @@
 
   // Legal because OpSNegate always considers the integer as signed
   auto replacement1 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(15, SpvOpSNegate, 0),
-                          0),
+      MakeIdUseDescriptor(
+          10, MakeInstructionDescriptor(15, spv::Op::OpSNegate, 0), 0),
       13);
   ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement1, context.get(), &transformation_context);
 
   // Legal because OpIAdd does not care about the signedness of the operands
   auto replacement2 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(16, SpvOpIAdd, 0), 0),
+      MakeIdUseDescriptor(10, MakeInstructionDescriptor(16, spv::Op::OpIAdd, 0),
+                          0),
       13);
   ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement2, context.get(), &transformation_context);
 
   // Legal because OpSDiv does not care about the signedness of the operands
   auto replacement3 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(17, SpvOpSDiv, 0), 0),
+      MakeIdUseDescriptor(10, MakeInstructionDescriptor(17, spv::Op::OpSDiv, 0),
+                          0),
       13);
   ASSERT_TRUE(replacement3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement3, context.get(), &transformation_context);
 
   // Not legal because OpUDiv requires unsigned integers
-  ASSERT_FALSE(TransformationReplaceIdWithSynonym(
-                   MakeIdUseDescriptor(
-                       13, MakeInstructionDescriptor(18, SpvOpUDiv, 0), 0),
-                   10)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIdWithSynonym(
+          MakeIdUseDescriptor(
+              13, MakeInstructionDescriptor(18, spv::Op::OpUDiv, 0), 0),
+          10)
+          .IsApplicable(context.get(), transformation_context));
 
   // Legal because OpSDiv does not care about the signedness of the operands
   auto replacement4 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(19, SpvOpBitwiseAnd, 0),
-                          0),
+      MakeIdUseDescriptor(
+          10, MakeInstructionDescriptor(19, spv::Op::OpBitwiseAnd, 0), 0),
       13);
   ASSERT_TRUE(replacement4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement4, context.get(), &transformation_context);
 
   // Not legal because OpSelect requires both operands to have the same type as
   // the result type
-  ASSERT_FALSE(TransformationReplaceIdWithSynonym(
-                   MakeIdUseDescriptor(
-                       10, MakeInstructionDescriptor(20, SpvOpUDiv, 0), 1),
-                   13)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIdWithSynonym(
+          MakeIdUseDescriptor(
+              10, MakeInstructionDescriptor(20, spv::Op::OpUDiv, 0), 1),
+          13)
+          .IsApplicable(context.get(), transformation_context));
 
   // Not legal because OpStore requires the object to match the type pointed
   // to by the pointer.
-  ASSERT_FALSE(TransformationReplaceIdWithSynonym(
-                   MakeIdUseDescriptor(
-                       10, MakeInstructionDescriptor(21, SpvOpStore, 0), 1),
-                   13)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIdWithSynonym(
+          MakeIdUseDescriptor(
+              10, MakeInstructionDescriptor(21, spv::Op::OpStore, 0), 1),
+          13)
+          .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
@@ -1668,18 +1686,20 @@
 
   // Legal because OpIAdd does not consider the signedness of the operands
   auto replacement1 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(14, MakeInstructionDescriptor(18, SpvOpIAdd, 0), 0),
+      MakeIdUseDescriptor(14, MakeInstructionDescriptor(18, spv::Op::OpIAdd, 0),
+                          0),
       15);
   ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement1, context.get(), &transformation_context);
 
   // Not legal because OpStore requires the object to match the type pointed
   // to by the pointer.
-  ASSERT_FALSE(TransformationReplaceIdWithSynonym(
-                   MakeIdUseDescriptor(
-                       14, MakeInstructionDescriptor(18, SpvOpStore, 0), 1),
-                   15)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIdWithSynonym(
+          MakeIdUseDescriptor(
+              14, MakeInstructionDescriptor(18, spv::Op::OpStore, 0), 1),
+          15)
+          .IsApplicable(context.get(), transformation_context));
 
   // Add synonym fact relating %12 and %13 (equivalent integer constants with
   // different signedness).
@@ -1689,7 +1709,7 @@
   // Legal because the indices of OpAccessChain are always treated as signed
   auto replacement2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          13, MakeInstructionDescriptor(19, SpvOpAccessChain, 0), 1),
+          13, MakeInstructionDescriptor(19, spv::Op::OpAccessChain, 0), 1),
       12);
   ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement2, context.get(), &transformation_context);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_irrelevant_id_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_irrelevant_id_test.cpp
index c04a091..c5d6981 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_irrelevant_id_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_irrelevant_id_test.cpp
@@ -82,8 +82,9 @@
   SetUpIrrelevantIdFacts(transformation_context.GetFactManager());
 
   auto instruction_21_descriptor =
-      MakeInstructionDescriptor(21, SpvOpAccessChain, 0);
-  auto instruction_24_descriptor = MakeInstructionDescriptor(24, SpvOpIAdd, 0);
+      MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0);
+  auto instruction_24_descriptor =
+      MakeInstructionDescriptor(24, spv::Op::OpIAdd, 0);
 
   // %20 has not been declared as irrelevant.
   ASSERT_FALSE(TransformationReplaceIrrelevantId(
@@ -132,7 +133,8 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   SetUpIrrelevantIdFacts(transformation_context.GetFactManager());
 
-  auto instruction_24_descriptor = MakeInstructionDescriptor(24, SpvOpIAdd, 0);
+  auto instruction_24_descriptor =
+      MakeInstructionDescriptor(24, spv::Op::OpIAdd, 0);
 
   // Replace the use of %23 in %24 with %22.
   auto transformation = TransformationReplaceIrrelevantId(
@@ -229,11 +231,12 @@
 
   // We cannot replace the use of %13 in the initializer of %12 with %9 because
   // %9 is not a constant.
-  ASSERT_FALSE(TransformationReplaceIrrelevantId(
-                   MakeIdUseDescriptor(
-                       13, MakeInstructionDescriptor(12, SpvOpVariable, 0), 1),
-                   9)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIrrelevantId(
+          MakeIdUseDescriptor(
+              13, MakeInstructionDescriptor(12, spv::Op::OpVariable, 0), 1),
+          9)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceIrrelevantIdTest,
@@ -280,7 +283,7 @@
   ASSERT_FALSE(
       TransformationReplaceIrrelevantId(
           MakeIdUseDescriptor(
-              20, MakeInstructionDescriptor(21, SpvOpCopyObject, 0), 0),
+              20, MakeInstructionDescriptor(21, spv::Op::OpCopyObject, 0), 0),
           10)
           .IsApplicable(context.get(), transformation_context));
 }
@@ -326,7 +329,7 @@
   ASSERT_FALSE(
       TransformationReplaceIrrelevantId(
           MakeIdUseDescriptor(
-              10, MakeInstructionDescriptor(12, SpvOpAccessChain, 0), 1),
+              10, MakeInstructionDescriptor(12, spv::Op::OpAccessChain, 0), 1),
           11)
           .IsApplicable(context.get(), transformation_context));
 }
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_linear_algebra_instruction_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_linear_algebra_instruction_test.cpp
index 8ec5552..2dedea1 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_linear_algebra_instruction_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_linear_algebra_instruction_test.cpp
@@ -76,54 +76,56 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests linear algebra instructions.
-  auto instruction_descriptor = MakeInstructionDescriptor(24, SpvOpDot, 0);
+  auto instruction_descriptor =
+      MakeInstructionDescriptor(24, spv::Op::OpDot, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37, 38}, instruction_descriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(27, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(27, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36}, instruction_descriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests non-linear algebra instructions.
-  instruction_descriptor = MakeInstructionDescriptor(30, SpvOpCopyObject, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(30, spv::Op::OpCopyObject, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37, 38}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(31, SpvOpFAdd, 0);
+  instruction_descriptor = MakeInstructionDescriptor(31, spv::Op::OpFAdd, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(32, SpvOpFMul, 0);
+  instruction_descriptor = MakeInstructionDescriptor(32, spv::Op::OpFMul, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests number of fresh ids is different than necessary.
-  instruction_descriptor = MakeInstructionDescriptor(25, SpvOpDot, 0);
+  instruction_descriptor = MakeInstructionDescriptor(25, spv::Op::OpDot, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(28, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(28, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37, 38, 39}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests non-fresh ids.
-  instruction_descriptor = MakeInstructionDescriptor(26, SpvOpDot, 0);
+  instruction_descriptor = MakeInstructionDescriptor(26, spv::Op::OpDot, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 5, 36, 37, 8, 39, 40, 1, 42, 3, 44, 45, 46},
       instruction_descriptor);
@@ -131,7 +133,7 @@
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(29, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(29, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 7, 38, 9, 40}, instruction_descriptor);
   ASSERT_FALSE(
@@ -249,32 +251,36 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpTranspose, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpTranspose, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(57, SpvOpTranspose, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(57, spv::Op::OpTranspose, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(58, SpvOpTranspose, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(58, spv::Op::OpTranspose, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
        106},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(59, SpvOpTranspose, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(59, spv::Op::OpTranspose, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
        121},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(60, SpvOpTranspose, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(60, spv::Op::OpTranspose, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
        133, 134, 135, 136, 137, 138, 139, 140, 141, 142},
@@ -506,19 +512,19 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(17, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(17, spv::Op::OpVectorTimesScalar, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {20, 21, 22, 23}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(18, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(18, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {24, 25, 26, 27, 28, 29}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(19, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(19, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {30, 31, 32, 33, 34, 35, 36, 37}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -677,20 +683,20 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpMatrixTimesScalar, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpMatrixTimesScalar, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(57, SpvOpMatrixTimesScalar, 0);
+      MakeInstructionDescriptor(57, spv::Op::OpMatrixTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(58, SpvOpMatrixTimesScalar, 0);
+      MakeInstructionDescriptor(58, spv::Op::OpMatrixTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106,
        107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118},
@@ -964,14 +970,14 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpVectorTimesMatrix, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpVectorTimesMatrix, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(57, SpvOpVectorTimesMatrix, 0);
+      MakeInstructionDescriptor(57, spv::Op::OpVectorTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
        89, 90, 91, 92, 93, 94, 95, 96, 97, 98},
@@ -979,7 +985,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(58, SpvOpVectorTimesMatrix, 0);
+      MakeInstructionDescriptor(58, spv::Op::OpVectorTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
        112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124},
@@ -987,7 +993,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(59, SpvOpVectorTimesMatrix, 0);
+      MakeInstructionDescriptor(59, spv::Op::OpVectorTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
        136, 137, 138, 139, 140, 141, 142, 143, 144, 145},
@@ -1298,14 +1304,14 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpMatrixTimesVector, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpMatrixTimesVector, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(57, SpvOpMatrixTimesVector, 0);
+      MakeInstructionDescriptor(57, spv::Op::OpMatrixTimesVector, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
        97},
@@ -1313,7 +1319,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(58, SpvOpMatrixTimesVector, 0);
+      MakeInstructionDescriptor(58, spv::Op::OpMatrixTimesVector, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
        110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121},
@@ -1321,7 +1327,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(59, SpvOpMatrixTimesVector, 0);
+      MakeInstructionDescriptor(59, spv::Op::OpMatrixTimesVector, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
        133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143},
@@ -1684,7 +1690,7 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpMatrixTimesMatrix, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpMatrixTimesMatrix, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,
        97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
@@ -1693,7 +1699,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(57, SpvOpMatrixTimesMatrix, 0);
+      MakeInstructionDescriptor(57, spv::Op::OpMatrixTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
        135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
@@ -1704,7 +1710,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(58, SpvOpMatrixTimesMatrix, 0);
+      MakeInstructionDescriptor(58, spv::Op::OpMatrixTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
        197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
@@ -2157,25 +2163,28 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(47, SpvOpOuterProduct, 0);
+      MakeInstructionDescriptor(47, spv::Op::OpOuterProduct, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(48, SpvOpOuterProduct, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(48, spv::Op::OpOuterProduct, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(49, SpvOpOuterProduct, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(49, spv::Op::OpOuterProduct, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {86, 87, 88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
        98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(50, SpvOpOuterProduct, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(50, spv::Op::OpOuterProduct, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
        124, 125},
@@ -2393,17 +2402,18 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto instruction_descriptor = MakeInstructionDescriptor(24, SpvOpDot, 0);
+  auto instruction_descriptor =
+      MakeInstructionDescriptor(24, spv::Op::OpDot, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {27, 28, 29, 30, 31, 32}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(25, SpvOpDot, 0);
+  instruction_descriptor = MakeInstructionDescriptor(25, spv::Op::OpDot, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37, 38, 39, 40, 41, 42}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(26, SpvOpDot, 0);
+  instruction_descriptor = MakeInstructionDescriptor(26, spv::Op::OpDot, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56},
       instruction_descriptor);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_load_store_with_copy_memory_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_load_store_with_copy_memory_test.cpp
index bc10099..74da98b 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_replace_load_store_with_copy_memory_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_replace_load_store_with_copy_memory_test.cpp
@@ -118,29 +118,29 @@
                                                kConsoleMessageConsumer));
 
   auto bad_instruction_descriptor_1 =
-      MakeInstructionDescriptor(11, SpvOpConstant, 0);
+      MakeInstructionDescriptor(11, spv::Op::OpConstant, 0);
 
   auto load_instruction_descriptor_1 =
-      MakeInstructionDescriptor(22, SpvOpLoad, 0);
+      MakeInstructionDescriptor(22, spv::Op::OpLoad, 0);
   auto load_instruction_descriptor_2 =
-      MakeInstructionDescriptor(23, SpvOpLoad, 0);
+      MakeInstructionDescriptor(23, spv::Op::OpLoad, 0);
   auto load_instruction_descriptor_3 =
-      MakeInstructionDescriptor(24, SpvOpLoad, 0);
+      MakeInstructionDescriptor(24, spv::Op::OpLoad, 0);
   auto load_instruction_descriptor_other_block =
-      MakeInstructionDescriptor(34, SpvOpLoad, 0);
+      MakeInstructionDescriptor(34, spv::Op::OpLoad, 0);
   auto load_instruction_descriptor_unsafe =
-      MakeInstructionDescriptor(29, SpvOpLoad, 0);
+      MakeInstructionDescriptor(29, spv::Op::OpLoad, 0);
 
   auto store_instruction_descriptor_1 =
-      MakeInstructionDescriptor(22, SpvOpStore, 0);
+      MakeInstructionDescriptor(22, spv::Op::OpStore, 0);
   auto store_instruction_descriptor_2 =
-      MakeInstructionDescriptor(23, SpvOpStore, 0);
+      MakeInstructionDescriptor(23, spv::Op::OpStore, 0);
   auto store_instruction_descriptor_3 =
-      MakeInstructionDescriptor(24, SpvOpStore, 0);
+      MakeInstructionDescriptor(24, spv::Op::OpStore, 0);
   auto store_instruction_descriptor_other_block =
-      MakeInstructionDescriptor(37, SpvOpStore, 0);
+      MakeInstructionDescriptor(37, spv::Op::OpStore, 0);
   auto store_instruction_descriptor_unsafe =
-      MakeInstructionDescriptor(29, SpvOpStore, 0);
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0);
 
   // Bad: |load_instruction_descriptor| is incorrect.
   auto transformation_bad_1 = TransformationReplaceLoadStoreWithCopyMemory(
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_set_function_control_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_set_function_control_test.cpp
index 85402e1..e51e24a 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_set_function_control_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_set_function_control_test.cpp
@@ -124,19 +124,22 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // %36 is not a function
-  ASSERT_FALSE(TransformationSetFunctionControl(36, SpvFunctionControlMaskNone)
+  ASSERT_FALSE(TransformationSetFunctionControl(
+                   36, uint32_t(spv::FunctionControlMask::MaskNone))
                    .IsApplicable(context.get(), transformation_context));
   // Cannot add the Pure function control to %4 as it did not already have it
-  ASSERT_FALSE(TransformationSetFunctionControl(4, SpvFunctionControlPureMask)
+  ASSERT_FALSE(TransformationSetFunctionControl(
+                   4, uint32_t(spv::FunctionControlMask::Pure))
                    .IsApplicable(context.get(), transformation_context));
   // Cannot add the Const function control to %21 as it did not already
   // have it
-  ASSERT_FALSE(TransformationSetFunctionControl(21, SpvFunctionControlConstMask)
+  ASSERT_FALSE(TransformationSetFunctionControl(
+                   21, uint32_t(spv::FunctionControlMask::Const))
                    .IsApplicable(context.get(), transformation_context));
 
   // Set to None, removing Const
-  TransformationSetFunctionControl transformation1(11,
-                                                   SpvFunctionControlMaskNone);
+  TransformationSetFunctionControl transformation1(
+      11, uint32_t(spv::FunctionControlMask::MaskNone));
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -144,15 +147,15 @@
 
   // Set to Inline; silly to do it on an entry point, but it is allowed
   TransformationSetFunctionControl transformation2(
-      4, SpvFunctionControlInlineMask);
+      4, uint32_t(spv::FunctionControlMask::Inline));
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
                         &transformation_context);
 
   // Set to Pure, removing DontInline
-  TransformationSetFunctionControl transformation3(17,
-                                                   SpvFunctionControlPureMask);
+  TransformationSetFunctionControl transformation3(
+      17, uint32_t(spv::FunctionControlMask::Pure));
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -160,7 +163,7 @@
 
   // Change from Inline to DontInline
   TransformationSetFunctionControl transformation4(
-      13, SpvFunctionControlDontInlineMask);
+      13, uint32_t(spv::FunctionControlMask::DontInline));
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_set_loop_control_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_set_loop_control_test.cpp
index 88b4aab..94a5b36 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_set_loop_control_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_set_loop_control_test.cpp
@@ -278,398 +278,458 @@
   // DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount
   // 2 5 90 4 7 14
 
-  ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(10, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
-                   10, SpvLoopControlDependencyInfiniteMask, 0, 0)
+                   10, (uint32_t)spv::LoopControlMask::DependencyInfinite, 0, 0)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlDependencyLengthMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlMinIterationsMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlMaxIterationsMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
-                   10, SpvLoopControlIterationMultipleMask, 0, 0)
+                   10, (uint32_t)spv::LoopControlMask::DependencyLength, 0, 0)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 3)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 0, 3)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 3, 3)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::MinIterations, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::MaxIterations, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::IterationMultiple, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::PeelCount, 3, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::PeelCount, 3, 3)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::PartialCount, 0, 3)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::PartialCount, 3, 3)
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   10,
-                  SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
+                  (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
                   3, 3)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(10,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlPeelCountMask |
-                                               SpvLoopControlPartialCountMask,
-                                           3, 3)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  3, 3)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationSetLoopControl(10,
-                                            SpvLoopControlDontUnrollMask |
-                                                SpvLoopControlPeelCountMask |
-                                                SpvLoopControlPartialCountMask,
-                                            3, 3)
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10,
+                   (uint32_t)spv::LoopControlMask::DontUnroll |
+                       (uint32_t)spv::LoopControlMask::PeelCount |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
+                   3, 3)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  23, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  23, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  23, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   23,
-                  SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
+                  (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
                   3, 3)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(23, SpvLoopControlMaxIterationsMask, 2, 3)
-          .IsApplicable(context.get(), transformation_context));
-
-  ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(33, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(33, SpvLoopControlMinIterationsMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          33, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationSetLoopControl(33,
-                                            SpvLoopControlDontUnrollMask |
-                                                SpvLoopControlPartialCountMask,
-                                            0, 10)
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   23, (uint32_t)spv::LoopControlMask::MaxIterations, 2, 3)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  33, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  33, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(43, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  33, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   33, (uint32_t)spv::LoopControlMask::MinIterations, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  33,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  5, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   33,
+                   (uint32_t)spv::LoopControlMask::DontUnroll |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
+                   0, 10)
+                   .IsApplicable(context.get(), transformation_context));
+
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   43,
-                  SpvLoopControlMaskNone | SpvLoopControlDependencyInfiniteMask,
+                  (uint32_t)spv::LoopControlMask::MaskNone |
+                      (uint32_t)spv::LoopControlMask::DependencyInfinite,
                   0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          43, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask,
-          0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          43,
-          SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask,
-          0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(43,
-                                   SpvLoopControlDependencyInfiniteMask |
-                                       SpvLoopControlDependencyLengthMask,
-                                   0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          43, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::DependencyInfinite,
+                  0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43,
+                  (uint32_t)spv::LoopControlMask::DontUnroll |
+                      (uint32_t)spv::LoopControlMask::DependencyInfinite,
+                  0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   43,
+                   (uint32_t)spv::LoopControlMask::DependencyInfinite |
+                       (uint32_t)spv::LoopControlMask::DependencyLength,
+                   0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  5, 0)
+                  .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(53, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(53, SpvLoopControlMaxIterationsMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          53, SpvLoopControlMaskNone | SpvLoopControlDependencyLengthMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(
-          53, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask,
-          0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          53, SpvLoopControlDontUnrollMask | SpvLoopControlDependencyLengthMask,
-          0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(53,
-                                   SpvLoopControlDependencyInfiniteMask |
-                                       SpvLoopControlDependencyLengthMask,
-                                   0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          53,
-          SpvLoopControlUnrollMask | SpvLoopControlDependencyLengthMask |
-              SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
-          5, 3)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   53, (uint32_t)spv::LoopControlMask::MaxIterations, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53,
+                  (uint32_t)spv::LoopControlMask::MaskNone |
+                      (uint32_t)spv::LoopControlMask::DependencyLength,
+                  0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   53,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::DependencyInfinite,
+                   0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53,
+                  (uint32_t)spv::LoopControlMask::DontUnroll |
+                      (uint32_t)spv::LoopControlMask::DependencyLength,
+                  0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   53,
+                   (uint32_t)spv::LoopControlMask::DependencyInfinite |
+                       (uint32_t)spv::LoopControlMask::DependencyLength,
+                   0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::DependencyLength |
+                      (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  5, 3)
+                  .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(63, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(63,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlMinIterationsMask |
-                                               SpvLoopControlPeelCountMask |
-                                               SpvLoopControlPartialCountMask,
-                                           5, 3)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(63,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlMinIterationsMask |
-                                               SpvLoopControlPeelCountMask,
-                                           23, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::MinIterations |
+                      (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  5, 3)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::MinIterations |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  23, 0)
                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    63,
-                   SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-                       SpvLoopControlPeelCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::PeelCount,
                    2, 23)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  73, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  73, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(73, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  73, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    73,
-                   SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-                       SpvLoopControlPeelCountMask |
-                       SpvLoopControlPartialCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::PeelCount |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
                    5, 3)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(73,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlMaxIterationsMask |
-                                               SpvLoopControlPeelCountMask,
-                                           23, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  73,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::MaxIterations |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  23, 0)
                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    73,
-                   SpvLoopControlUnrollMask | SpvLoopControlMaxIterationsMask |
-                       SpvLoopControlPeelCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MaxIterations |
+                       (uint32_t)spv::LoopControlMask::PeelCount,
                    2, 23)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  83, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  83, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  83, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    83,
-                   SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-                       SpvLoopControlPeelCountMask |
-                       SpvLoopControlPartialCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::PeelCount |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
                    5, 3)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(83,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlIterationMultipleMask |
-                                       SpvLoopControlPeelCountMask,
-                                   23, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(83,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlIterationMultipleMask |
-                                       SpvLoopControlPeelCountMask,
-                                   2, 23)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  83,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::IterationMultiple |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  23, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   83,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::IterationMultiple |
+                       (uint32_t)spv::LoopControlMask::PeelCount,
+                   2, 23)
+                   .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(93, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 8)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(93, SpvLoopControlPartialCountMask, 0, 8)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::PeelCount, 8, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   93, (uint32_t)spv::LoopControlMask::PeelCount, 8, 8)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::PartialCount, 0, 8)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   93,
-                  SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
+                  (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
                   16, 8)
                   .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  103, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  103, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(103, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationSetLoopControl(103,
-                                            SpvLoopControlDontUnrollMask |
-                                                SpvLoopControlPartialCountMask,
-                                            0, 60)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  103, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  103, (uint32_t)spv::LoopControlMask::PartialCount, 0, 60)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   103,
+                   (uint32_t)spv::LoopControlMask::DontUnroll |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
+                   0, 60)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  113, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  113, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(113, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(
-          113,
-          SpvLoopControlIterationMultipleMask | SpvLoopControlPeelCountMask, 12,
-          0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  113, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  113, (uint32_t)spv::LoopControlMask::PeelCount, 12, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   113,
+                   (uint32_t)spv::LoopControlMask::IterationMultiple |
+                       (uint32_t)spv::LoopControlMask::PeelCount,
+                   12, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(123, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          123,
-          SpvLoopControlMinIterationsMask | SpvLoopControlMaxIterationsMask |
-              SpvLoopControlIterationMultipleMask |
-              SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
-          7, 8)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(123,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlMinIterationsMask |
-                                               SpvLoopControlMaxIterationsMask |
-                                               SpvLoopControlPartialCountMask,
-                                           0, 9)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123,
+                  (uint32_t)spv::LoopControlMask::MinIterations |
+                      (uint32_t)spv::LoopControlMask::MaxIterations |
+                      (uint32_t)spv::LoopControlMask::IterationMultiple |
+                      (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  7, 8)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::MinIterations |
+                      (uint32_t)spv::LoopControlMask::MaxIterations |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  0, 9)
                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    123,
-                   SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-                       SpvLoopControlMaxIterationsMask |
-                       SpvLoopControlPartialCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::MaxIterations |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
                    7, 9)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(
-          123,
-          SpvLoopControlDontUnrollMask | SpvLoopControlMinIterationsMask |
-              SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask,
-          7, 9)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   123,
+                   (uint32_t)spv::LoopControlMask::DontUnroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::MaxIterations |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
+                   7, 9)
+                   .IsApplicable(context.get(), transformation_context));
 
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            10,
+                            (uint32_t)spv::LoopControlMask::Unroll |
+                                (uint32_t)spv::LoopControlMask::PeelCount |
+                                (uint32_t)spv::LoopControlMask::PartialCount,
+                            3, 3),
+                        context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(10,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlPeelCountMask |
-                                       SpvLoopControlPartialCountMask,
-                                   3, 3),
+      TransformationSetLoopControl(
+          23, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0),
       context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0),
-      context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            33, (uint32_t)spv::LoopControlMask::Unroll, 0, 0),
+                        context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
       TransformationSetLoopControl(
           43,
-          SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask,
+          (uint32_t)spv::LoopControlMask::DontUnroll |
+              (uint32_t)spv::LoopControlMask::DependencyInfinite,
           0, 0),
       context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            53, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0),
+                        context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            63,
+                            (uint32_t)spv::LoopControlMask::Unroll |
+                                (uint32_t)spv::LoopControlMask::MinIterations |
+                                (uint32_t)spv::LoopControlMask::PeelCount,
+                            23, 0),
+                        context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            73,
+                            (uint32_t)spv::LoopControlMask::Unroll |
+                                (uint32_t)spv::LoopControlMask::MaxIterations |
+                                (uint32_t)spv::LoopControlMask::PeelCount,
+                            23, 0),
+                        context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0),
+      TransformationSetLoopControl(
+          83, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0),
       context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            93,
+                            (uint32_t)spv::LoopControlMask::PeelCount |
+                                (uint32_t)spv::LoopControlMask::PartialCount,
+                            16, 8),
+                        context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(63,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlMinIterationsMask |
-                                       SpvLoopControlPeelCountMask,
-                                   23, 0),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(73,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlMaxIterationsMask |
-                                       SpvLoopControlPeelCountMask,
-                                   23, 0),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0),
+      TransformationSetLoopControl(
+          103, (uint32_t)spv::LoopControlMask::PartialCount, 0, 60),
       context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
       TransformationSetLoopControl(
-          93, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 16,
-          8),
+          113, (uint32_t)spv::LoopControlMask::PeelCount, 12, 0),
       context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(
-          123,
-          SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-              SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask,
-          0, 9),
-      context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            123,
+                            (uint32_t)spv::LoopControlMask::Unroll |
+                                (uint32_t)spv::LoopControlMask::MinIterations |
+                                (uint32_t)spv::LoopControlMask::MaxIterations |
+                                (uint32_t)spv::LoopControlMask::PartialCount,
+                            0, 9),
+                        context.get(), &transformation_context);
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -958,10 +1018,10 @@
         context.get(), validator_options, kConsoleMessageConsumer));
     TransformationContext transformation_context(
         MakeUnique<FactManager>(context.get()), validator_options);
-    TransformationSetLoopControl peel_count(10, SpvLoopControlPeelCountMask, 4,
-                                            0);
+    TransformationSetLoopControl peel_count(
+        10, (uint32_t)spv::LoopControlMask::PeelCount, 4, 0);
     TransformationSetLoopControl partial_count(
-        10, SpvLoopControlPartialCountMask, 0, 4);
+        10, (uint32_t)spv::LoopControlMask::PartialCount, 0, 4);
 
     switch (env) {
       case SPV_ENV_UNIVERSAL_1_0:
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_set_memory_operands_mask_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_set_memory_operands_mask_test.cpp
index 29e57f4..44901f9 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_set_memory_operands_mask_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_set_memory_operands_mask_test.cpp
@@ -106,8 +106,10 @@
     {
       // Not OK: multiple operands are not supported pre SPIR-V 1.4.
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 3),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          1);
       ASSERT_DEATH(
           transformation.IsApplicable(context.get(), transformation_context),
           "Multiple memory operand masks are not supported");
@@ -116,21 +118,24 @@
 
     // Not OK: the instruction is not a memory access.
     ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                     MakeInstructionDescriptor(21, SpvOpAccessChain, 0),
-                     SpvMemoryAccessMaskNone, 0)
+                     MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0),
+                     (uint32_t)spv::MemoryAccessMask::MaskNone, 0)
                      .IsApplicable(context.get(), transformation_context));
 
     // Not OK to remove Aligned
-    ASSERT_FALSE(
-        TransformationSetMemoryOperandsMask(
-            MakeInstructionDescriptor(147, SpvOpLoad, 0),
-            SpvMemoryAccessVolatileMask | SpvMemoryAccessNontemporalMask, 0)
-            .IsApplicable(context.get(), transformation_context));
+    ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+                     MakeInstructionDescriptor(147, spv::Op::OpLoad, 0),
+                     (uint32_t)spv::MemoryAccessMask::Volatile |
+                         (uint32_t)spv::MemoryAccessMask::Nontemporal,
+                     0)
+                     .IsApplicable(context.get(), transformation_context));
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(147, SpvOpLoad, 0),
-          SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(147, spv::Op::OpLoad, 0),
+          (uint32_t)spv::MemoryAccessMask::Aligned |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -139,22 +144,23 @@
 
     // Not OK to remove Aligned
     ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                     MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-                     SpvMemoryAccessMaskNone, 0)
+                     MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+                     (uint32_t)spv::MemoryAccessMask::MaskNone, 0)
                      .IsApplicable(context.get(), transformation_context));
 
     // OK: leaves the mask as is
     ASSERT_TRUE(TransformationSetMemoryOperandsMask(
-                    MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-                    SpvMemoryAccessAlignedMask, 0)
+                    MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+                    (uint32_t)spv::MemoryAccessMask::Aligned, 0)
                     .IsApplicable(context.get(), transformation_context));
 
     {
       // OK: adds Nontemporal and Volatile
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-          SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask |
-              SpvMemoryAccessVolatileMask,
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+          (uint32_t)spv::MemoryAccessMask::Aligned |
+              (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
           0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
@@ -164,22 +170,25 @@
 
     // Not OK to remove Volatile
     ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                     MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-                     SpvMemoryAccessNontemporalMask, 0)
+                     MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+                     (uint32_t)spv::MemoryAccessMask::Nontemporal, 0)
                      .IsApplicable(context.get(), transformation_context));
 
     // Not OK to add Aligned
     ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                     MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-                     SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask,
+                     MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+                     (uint32_t)spv::MemoryAccessMask::Aligned |
+                         (uint32_t)spv::MemoryAccessMask::Volatile,
                      0)
                      .IsApplicable(context.get(), transformation_context));
 
     {
       // OK: adds Nontemporal
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -189,8 +198,10 @@
     {
       // OK: adds Nontemporal (creates new operand)
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 2),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -200,8 +211,10 @@
     {
       // OK: adds Nontemporal and Volatile
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(138, spv::Op::OpCopyMemory, 0),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -211,8 +224,8 @@
     {
       // OK: removes Nontemporal, adds Volatile
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(148, SpvOpStore, 0),
-          SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(148, spv::Op::OpStore, 0),
+          (uint32_t)spv::MemoryAccessMask::Volatile, 0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -369,12 +382,14 @@
         MakeUnique<FactManager>(context.get()), validator_options);
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-          SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+          (uint32_t)spv::MemoryAccessMask::Aligned |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          1);
       // Bad: cannot remove aligned
       ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                       MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-                       SpvMemoryAccessVolatileMask, 1)
+                       MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+                       (uint32_t)spv::MemoryAccessMask::Volatile, 1)
                        .IsApplicable(context.get(), transformation_context));
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
@@ -384,12 +399,14 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          1);
       // Bad: cannot remove volatile
       ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                       MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-                       SpvMemoryAccessNontemporalMask, 0)
+                       MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+                       (uint32_t)spv::MemoryAccessMask::Nontemporal, 0)
                        .IsApplicable(context.get(), transformation_context));
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
@@ -400,8 +417,10 @@
     {
       // Creates the first operand.
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 2),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -411,8 +430,10 @@
     {
       // Creates both operands.
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 3),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          1);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -421,14 +442,17 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
-          SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 1);
+          MakeInstructionDescriptor(138, spv::Op::OpCopyMemory, 0),
+          (uint32_t)spv::MemoryAccessMask::Aligned |
+              (uint32_t)spv::MemoryAccessMask::Nontemporal,
+          1);
       // Bad: the first mask is None, so Aligned cannot be added to it.
-      ASSERT_FALSE(
-          TransformationSetMemoryOperandsMask(
-              MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
-              SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 0)
-              .IsApplicable(context.get(), transformation_context));
+      ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+                       MakeInstructionDescriptor(138, spv::Op::OpCopyMemory, 0),
+                       (uint32_t)spv::MemoryAccessMask::Aligned |
+                           (uint32_t)spv::MemoryAccessMask::Nontemporal,
+                       0)
+                       .IsApplicable(context.get(), transformation_context));
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -437,8 +461,8 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(138, SpvOpCopyMemory, 1),
-          SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(138, spv::Op::OpCopyMemory, 1),
+          (uint32_t)spv::MemoryAccessMask::Volatile, 1);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -447,8 +471,10 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(147, SpvOpLoad, 0),
-          SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask, 0);
+          MakeInstructionDescriptor(147, spv::Op::OpLoad, 0),
+          (uint32_t)spv::MemoryAccessMask::Volatile |
+              (uint32_t)spv::MemoryAccessMask::Aligned,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -457,8 +483,8 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(148, SpvOpStore, 0),
-          SpvMemoryAccessMaskNone, 0);
+          MakeInstructionDescriptor(148, spv::Op::OpStore, 0),
+          (uint32_t)spv::MemoryAccessMask::MaskNone, 0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_set_selection_control_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_set_selection_control_test.cpp
index c584ff1..4cecd23 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_set_selection_control_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_set_selection_control_test.cpp
@@ -109,41 +109,41 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // %44 is not a block
-  ASSERT_FALSE(
-      TransformationSetSelectionControl(44, SpvSelectionControlFlattenMask)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetSelectionControl(
+                   44, uint32_t(spv::SelectionControlMask::Flatten))
+                   .IsApplicable(context.get(), transformation_context));
   // %13 does not end with OpSelectionMerge
-  ASSERT_FALSE(
-      TransformationSetSelectionControl(13, SpvSelectionControlMaskNone)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetSelectionControl(
+                   13, uint32_t(spv::SelectionControlMask::MaskNone))
+                   .IsApplicable(context.get(), transformation_context));
   // %10 ends in OpLoopMerge, not OpSelectionMerge
-  ASSERT_FALSE(
-      TransformationSetSelectionControl(10, SpvSelectionControlMaskNone)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetSelectionControl(
+                   10, uint32_t(spv::SelectionControlMask::MaskNone))
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationSetSelectionControl transformation1(
-      11, SpvSelectionControlDontFlattenMask);
+      11, uint32_t(spv::SelectionControlMask::DontFlatten));
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
                         &transformation_context);
 
   TransformationSetSelectionControl transformation2(
-      23, SpvSelectionControlFlattenMask);
+      23, uint32_t(spv::SelectionControlMask::Flatten));
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
                         &transformation_context);
 
   TransformationSetSelectionControl transformation3(
-      31, SpvSelectionControlMaskNone);
+      31, uint32_t(spv::SelectionControlMask::MaskNone));
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
                         &transformation_context);
 
   TransformationSetSelectionControl transformation4(
-      31, SpvSelectionControlFlattenMask);
+      31, uint32_t(spv::SelectionControlMask::Flatten));
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_split_block_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_split_block_test.cpp
index 55091de..1cef182 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_split_block_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_split_block_test.cpp
@@ -96,53 +96,54 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // No split before OpVariable
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(8, SpvOpVariable, 0), 100)
+                   MakeInstructionDescriptor(8, spv::Op::OpVariable, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(8, SpvOpVariable, 1), 100)
+                   MakeInstructionDescriptor(8, spv::Op::OpVariable, 1), 100)
                    .IsApplicable(context.get(), transformation_context));
 
   // No split before OpLabel
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(14, SpvOpLabel, 0), 100)
+                   MakeInstructionDescriptor(14, spv::Op::OpLabel, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
 
   // No split if base instruction is outside a function
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(1, SpvOpLabel, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(1, SpvOpExecutionMode, 0), 100)
+                   MakeInstructionDescriptor(1, spv::Op::OpLabel, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationSplitBlock(
+          MakeInstructionDescriptor(1, spv::Op::OpExecutionMode, 0), 100)
+          .IsApplicable(context.get(), transformation_context));
 
   // No split if block is loop header
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 1), 100)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(27, spv::Op::OpPhi, 0), 100)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(27, spv::Op::OpPhi, 1), 100)
+                   .IsApplicable(context.get(), transformation_context));
 
   // No split if base instruction does not exist
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(88, SpvOpIAdd, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(88, SpvOpIMul, 22), 100)
+                   MakeInstructionDescriptor(88, spv::Op::OpIAdd, 0), 100)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(88, spv::Op::OpIMul, 22), 100)
                    .IsApplicable(context.get(), transformation_context));
 
   // No split if too many instructions with the desired opcode are skipped
   ASSERT_FALSE(
       TransformationSplitBlock(
-          MakeInstructionDescriptor(18, SpvOpBranchConditional, 1), 100)
+          MakeInstructionDescriptor(18, spv::Op::OpBranchConditional, 1), 100)
           .IsApplicable(context.get(), transformation_context));
 
   // No split if id in use
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(18, SpvOpSLessThan, 0), 27)
+                   MakeInstructionDescriptor(18, spv::Op::OpSLessThan, 0), 27)
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(18, SpvOpSLessThan, 0), 14)
+                   MakeInstructionDescriptor(18, spv::Op::OpSLessThan, 0), 14)
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -206,7 +207,7 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto split_1 = TransformationSplitBlock(
-      MakeInstructionDescriptor(5, SpvOpStore, 0), 100);
+      MakeInstructionDescriptor(5, spv::Op::OpStore, 0), 100);
   ASSERT_TRUE(split_1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split_1, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -255,7 +256,7 @@
   ASSERT_TRUE(IsEqual(env, after_split_1, context.get()));
 
   auto split_2 = TransformationSplitBlock(
-      MakeInstructionDescriptor(11, SpvOpStore, 0), 101);
+      MakeInstructionDescriptor(11, spv::Op::OpStore, 0), 101);
   ASSERT_TRUE(split_2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split_2, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -306,7 +307,7 @@
   ASSERT_TRUE(IsEqual(env, after_split_2, context.get()));
 
   auto split_3 = TransformationSplitBlock(
-      MakeInstructionDescriptor(14, SpvOpLoad, 0), 102);
+      MakeInstructionDescriptor(14, spv::Op::OpLoad, 0), 102);
   ASSERT_TRUE(split_3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split_3, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -425,15 +426,15 @@
   // Illegal to split between the merge and the conditional branch.
   ASSERT_FALSE(
       TransformationSplitBlock(
-          MakeInstructionDescriptor(14, SpvOpBranchConditional, 0), 100)
+          MakeInstructionDescriptor(14, spv::Op::OpBranchConditional, 0), 100)
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSplitBlock(
-          MakeInstructionDescriptor(12, SpvOpBranchConditional, 0), 100)
+          MakeInstructionDescriptor(12, spv::Op::OpBranchConditional, 0), 100)
           .IsApplicable(context.get(), transformation_context));
 
   auto split = TransformationSplitBlock(
-      MakeInstructionDescriptor(14, SpvOpSelectionMerge, 0), 100);
+      MakeInstructionDescriptor(14, spv::Op::OpSelectionMerge, 0), 100);
   ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -555,14 +556,14 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Illegal to split between the merge and the conditional branch.
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(9, SpvOpSwitch, 0), 100)
+                   MakeInstructionDescriptor(9, spv::Op::OpSwitch, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(15, SpvOpSwitch, 0), 100)
+                   MakeInstructionDescriptor(15, spv::Op::OpSwitch, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
 
   auto split = TransformationSplitBlock(
-      MakeInstructionDescriptor(9, SpvOpSelectionMerge, 0), 100);
+      MakeInstructionDescriptor(9, spv::Op::OpSelectionMerge, 0), 100);
   ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -690,15 +691,15 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // We cannot split before OpPhi instructions, since the number of incoming
   // blocks may not appropriately match after splitting.
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(26, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 1), 100)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(26, spv::Op::OpPhi, 0), 100)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(27, spv::Op::OpPhi, 0), 100)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(27, spv::Op::OpPhi, 1), 100)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationSplitBlockTest, SplitOpPhiWithSinglePredecessor) {
@@ -741,13 +742,13 @@
   spvtools::ValidatorOptions validator_options;
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  ASSERT_TRUE(
-      TransformationSplitBlock(MakeInstructionDescriptor(21, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSplitBlock(
+                  MakeInstructionDescriptor(21, spv::Op::OpPhi, 0), 100)
+                  .IsApplicable(context.get(), transformation_context));
   // An equivalent transformation to the above, just described with respect to a
   // different base instruction.
-  auto split =
-      TransformationSplitBlock(MakeInstructionDescriptor(20, SpvOpPhi, 0), 100);
+  auto split = TransformationSplitBlock(
+      MakeInstructionDescriptor(20, spv::Op::OpPhi, 0), 100);
   ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -826,7 +827,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(8);
 
   auto split = TransformationSplitBlock(
-      MakeInstructionDescriptor(8, SpvOpBranch, 0), 100);
+      MakeInstructionDescriptor(8, spv::Op::OpBranch, 0), 100);
   ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -912,7 +913,8 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto split = TransformationSplitBlock(
-      MakeInstructionDescriptor(217, SpvOpImageSampleImplicitLod, 0), 500);
+      MakeInstructionDescriptor(217, spv::Op::OpImageSampleImplicitLod, 0),
+      500);
   ASSERT_FALSE(split.IsApplicable(context.get(), transformation_context));
 }
 
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_store_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_store_test.cpp
index dd653e2..fe24d74 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_store_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_store_test.cpp
@@ -148,107 +148,107 @@
   //  61 - undefined
 
   // Bad: attempt to store to 11 from outside its function
-  ASSERT_FALSE(
-      TransformationStore(11, false, 0, 0, 80,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   11, false, 0, 0, 80,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer is not available
-  ASSERT_FALSE(
-      TransformationStore(81, false, 0, 0, 80,
-                          MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   81, false, 0, 0, 80,
+                   MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to insert before OpVariable
   ASSERT_FALSE(
       TransformationStore(52, false, 0, 0, 24,
-                          MakeInstructionDescriptor(27, SpvOpVariable, 0))
+                          MakeInstructionDescriptor(27, spv::Op::OpVariable, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id does not exist
-  ASSERT_FALSE(
-      TransformationStore(1000, false, 0, 0, 24,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   1000, false, 0, 0, 24,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists but does not have a type
-  ASSERT_FALSE(
-      TransformationStore(5, false, 0, 0, 24,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   5, false, 0, 0, 24,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists and has a type, but is not a pointer
-  ASSERT_FALSE(
-      TransformationStore(24, false, 0, 0, 24,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   24, false, 0, 0, 24,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to store to a null pointer
-  ASSERT_FALSE(
-      TransformationStore(60, false, 0, 0, 24,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   60, false, 0, 0, 24,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to store to an undefined pointer
-  ASSERT_FALSE(
-      TransformationStore(61, false, 0, 0, 21,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   61, false, 0, 0, 21,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: %82 is not available at the program point
   ASSERT_FALSE(
       TransformationStore(82, false, 0, 0, 80,
-                          MakeInstructionDescriptor(37, SpvOpReturn, 0))
+                          MakeInstructionDescriptor(37, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: value id does not exist
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 1000,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 1000,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: value id exists but does not have a type
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 15,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 15,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: value id exists but has the wrong type
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 14,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 14,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to store to read-only variable
-  ASSERT_FALSE(
-      TransformationStore(92, false, 0, 0, 93,
-                          MakeInstructionDescriptor(40, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   92, false, 0, 0, 93,
+                   MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: value is not available
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 95,
-                          MakeInstructionDescriptor(40, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 95,
+                   MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: variable being stored to does not have an irrelevant pointee value,
   // and the store is not in a dead block.
-  ASSERT_FALSE(
-      TransformationStore(20, false, 0, 0, 95,
-                          MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   20, false, 0, 0, 95,
+                   MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // The described instruction does not exist.
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 80,
-                          MakeInstructionDescriptor(1000, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 80,
+                   MakeInstructionDescriptor(1000, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   {
     // Store to irrelevant variable from dead block.
     TransformationStore transformation(
         27, false, 0, 0, 80,
-        MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -261,7 +261,7 @@
     // Store to irrelevant variable from live block.
     TransformationStore transformation(
         11, false, 0, 0, 95,
-        MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -274,7 +274,7 @@
     // Store to irrelevant variable from live block.
     TransformationStore transformation(
         46, false, 0, 0, 80,
-        MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -287,7 +287,7 @@
     // Store to irrelevant variable from live block.
     TransformationStore transformation(
         16, false, 0, 0, 21,
-        MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -300,7 +300,7 @@
     // Store to non-irrelevant variable from dead block.
     TransformationStore transformation(
         53, false, 0, 0, 21,
-        MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -436,15 +436,15 @@
 
   ASSERT_FALSE(
       TransformationStore(15, false, 0, 0, 13,
-                          MakeInstructionDescriptor(27, SpvOpReturn, 0))
+                          MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationStore(19, false, 0, 0, 50,
-                          MakeInstructionDescriptor(27, SpvOpReturn, 0))
+                          MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationStore(27, false, 0, 0, 50,
-                          MakeInstructionDescriptor(27, SpvOpReturn, 0))
+                          MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
 }
 
@@ -495,84 +495,85 @@
       14);
 
   // Bad: id 100 of memory scope instruction does not exist.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 100, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 100, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: id 100 of memory semantics instruction does not exist.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 100, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 100, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: memory scope should be |OpConstant| opcode.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 5, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 5, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: memory semantics should be |OpConstant| opcode.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 5, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 5, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: The memory scope instruction must have an Integer operand.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 19, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 19, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: The memory memory semantics instruction must have an Integer operand.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 19, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 19, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Integer size of the memory scope must be equal to 32 bits.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 17, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 17, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Integer size of memory semantics must be equal to 32 bits.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 17, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 17, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
-  // Bad: memory scope value must be 4 (SpvScopeInvocation).
-  ASSERT_FALSE(
-      TransformationStore(14, true, 16, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  // Bad: memory scope value must be 4 (spv::Scope::Invocation).
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 16, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: memory semantics value must be either:
   // 64 (SpvMemorySemanticsUniformMemoryMask)
   // 256 (SpvMemorySemanticsWorkgroupMemoryMask)
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 16, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 16, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: The described instruction does not exist
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 20, 21,
-                          MakeInstructionDescriptor(150, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 20, 21,
+                   MakeInstructionDescriptor(150, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Can't insert OpAccessChain before the id 15 of memory scope.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 20, 21,
-                          MakeInstructionDescriptor(15, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 20, 21,
+                   MakeInstructionDescriptor(15, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Can't insert OpAccessChain before the id 20 of memory semantics.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 20, 21,
-                          MakeInstructionDescriptor(20, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 20, 21,
+                   MakeInstructionDescriptor(20, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Successful transformations.
   {
     TransformationStore transformation(
-        14, true, 15, 20, 21, MakeInstructionDescriptor(24, SpvOpReturn, 0));
+        14, true, 15, 20, 21,
+        MakeInstructionDescriptor(24, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_swap_commutable_operands_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_swap_commutable_operands_test.cpp
index 0731529..789dd09 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_swap_commutable_operands_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_swap_commutable_operands_test.cpp
@@ -118,103 +118,108 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests existing commutative instructions
-  auto instructionDescriptor = MakeInstructionDescriptor(22, SpvOpIAdd, 0);
+  auto instructionDescriptor =
+      MakeInstructionDescriptor(22, spv::Op::OpIAdd, 0);
   auto transformation =
       TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(28, SpvOpIMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(28, spv::Op::OpIMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(42, SpvOpFAdd, 0);
+  instructionDescriptor = MakeInstructionDescriptor(42, spv::Op::OpFAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(48, SpvOpFMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(48, spv::Op::OpFMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(66, SpvOpDot, 0);
+  instructionDescriptor = MakeInstructionDescriptor(66, spv::Op::OpDot, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests existing non-commutative instructions
-  instructionDescriptor = MakeInstructionDescriptor(1, SpvOpExtInstImport, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(1, spv::Op::OpExtInstImport, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(5, SpvOpLabel, 0);
+  instructionDescriptor = MakeInstructionDescriptor(5, spv::Op::OpLabel, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(8, SpvOpConstant, 0);
+  instructionDescriptor = MakeInstructionDescriptor(8, spv::Op::OpConstant, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(11, SpvOpVariable, 0);
+  instructionDescriptor = MakeInstructionDescriptor(11, spv::Op::OpVariable, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(14, SpvOpConstantComposite, 0);
+      MakeInstructionDescriptor(14, spv::Op::OpConstantComposite, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests the base instruction id not existing
-  instructionDescriptor = MakeInstructionDescriptor(67, SpvOpIAddCarry, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(67, spv::Op::OpIAddCarry, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(68, SpvOpIEqual, 0);
+  instructionDescriptor = MakeInstructionDescriptor(68, spv::Op::OpIEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(69, SpvOpINotEqual, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(69, spv::Op::OpINotEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(70, SpvOpFOrdEqual, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(70, spv::Op::OpFOrdEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(71, SpvOpPtrEqual, 0);
+  instructionDescriptor = MakeInstructionDescriptor(71, spv::Op::OpPtrEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests there being no instruction with the desired opcode after the base
   // instruction id
-  instructionDescriptor = MakeInstructionDescriptor(24, SpvOpIAdd, 0);
+  instructionDescriptor = MakeInstructionDescriptor(24, spv::Op::OpIAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(38, SpvOpIMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(38, spv::Op::OpIMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(45, SpvOpFAdd, 0);
+  instructionDescriptor = MakeInstructionDescriptor(45, spv::Op::OpFAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(66, SpvOpFMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(66, spv::Op::OpFMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
@@ -222,27 +227,27 @@
   // Tests there being an instruction with the desired opcode after the base
   // instruction id, but the skip count associated with the instruction
   // descriptor being so high.
-  instructionDescriptor = MakeInstructionDescriptor(11, SpvOpIAdd, 100);
+  instructionDescriptor = MakeInstructionDescriptor(11, spv::Op::OpIAdd, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(16, SpvOpIMul, 100);
+  instructionDescriptor = MakeInstructionDescriptor(16, spv::Op::OpIMul, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(23, SpvOpFAdd, 100);
+  instructionDescriptor = MakeInstructionDescriptor(23, spv::Op::OpFAdd, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(32, SpvOpFMul, 100);
+  instructionDescriptor = MakeInstructionDescriptor(32, spv::Op::OpFMul, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(37, SpvOpDot, 100);
+  instructionDescriptor = MakeInstructionDescriptor(37, spv::Op::OpDot, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
@@ -342,24 +347,25 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto instructionDescriptor = MakeInstructionDescriptor(22, SpvOpIAdd, 0);
+  auto instructionDescriptor =
+      MakeInstructionDescriptor(22, spv::Op::OpIAdd, 0);
   auto transformation =
       TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(28, SpvOpIMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(28, spv::Op::OpIMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(42, SpvOpFAdd, 0);
+  instructionDescriptor = MakeInstructionDescriptor(42, spv::Op::OpFAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(48, SpvOpFMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(48, spv::Op::OpFMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(66, SpvOpDot, 0);
+  instructionDescriptor = MakeInstructionDescriptor(66, spv::Op::OpDot, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
index 6133a7a..5f7ffe4 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
@@ -76,27 +76,29 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Invalid instruction descriptor.
   ASSERT_FALSE(TransformationSwapConditionalBranchOperands(
-                   MakeInstructionDescriptor(26, SpvOpPhi, 0), 26)
+                   MakeInstructionDescriptor(26, spv::Op::OpPhi, 0), 26)
                    .IsApplicable(context.get(), transformation_context));
 
   // Descriptor for a wrong instruction.
   ASSERT_FALSE(TransformationSwapConditionalBranchOperands(
-                   MakeInstructionDescriptor(25, SpvOpPhi, 0), 26)
+                   MakeInstructionDescriptor(25, spv::Op::OpPhi, 0), 26)
                    .IsApplicable(context.get(), transformation_context));
 
   // Fresh id is not fresh.
-  ASSERT_FALSE(TransformationSwapConditionalBranchOperands(
-                   MakeInstructionDescriptor(15, SpvOpBranchConditional, 0), 25)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationSwapConditionalBranchOperands(
+          MakeInstructionDescriptor(15, spv::Op::OpBranchConditional, 0), 25)
+          .IsApplicable(context.get(), transformation_context));
 
   TransformationSwapConditionalBranchOperands transformation(
-      MakeInstructionDescriptor(15, SpvOpBranchConditional, 0), 26);
+      MakeInstructionDescriptor(15, spv::Op::OpBranchConditional, 0), 26);
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(26));
   ASSERT_EQ(nullptr, context->get_instr_block(26));
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpLogicalNot, context->get_def_use_mgr()->GetDef(26)->opcode());
+  ASSERT_EQ(spv::Op::OpLogicalNot,
+            context->get_def_use_mgr()->GetDef(26)->opcode());
   ASSERT_EQ(5, context->get_instr_block(26)->id());
   ASSERT_EQ(1, context->get_def_use_mgr()->NumUses(26));
 
@@ -109,7 +111,7 @@
     context->get_def_use_mgr()->WhileEachUse(
         entry.first,
         [&entry](opt::Instruction* inst, uint32_t operand_index) -> bool {
-          if (inst->opcode() == SpvOpBranchConditional) {
+          if (inst->opcode() == spv::Op::OpBranchConditional) {
             EXPECT_EQ(entry.second, operand_index);
             return false;
           }
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp
index 84ed20d..94ca804 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp
@@ -119,67 +119,71 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests existing access chain instructions
   auto instructionDescriptor =
-      MakeInstructionDescriptor(18, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(18, spv::Op::OpAccessChain, 0);
   auto transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(20, SpvOpInBoundsAccessChain, 0);
-  transformation =
-      TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_TRUE(
-      transformation.IsApplicable(context.get(), transformation_context));
-
-  instructionDescriptor = MakeInstructionDescriptor(24, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(20, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(26, SpvOpInBoundsAccessChain, 0);
+      MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0);
+  transformation =
+      TransformationToggleAccessChainInstruction(instructionDescriptor);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+
+  instructionDescriptor =
+      MakeInstructionDescriptor(26, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests existing non-access chain instructions
-  instructionDescriptor = MakeInstructionDescriptor(1, SpvOpExtInstImport, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(1, spv::Op::OpExtInstImport, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(5, SpvOpLabel, 0);
+  instructionDescriptor = MakeInstructionDescriptor(5, spv::Op::OpLabel, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(14, SpvOpConstantComposite, 0);
+      MakeInstructionDescriptor(14, spv::Op::OpConstantComposite, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests the base instruction id not existing
-  instructionDescriptor = MakeInstructionDescriptor(67, SpvOpAccessChain, 0);
-  transformation =
-      TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(
-      transformation.IsApplicable(context.get(), transformation_context));
-
-  instructionDescriptor = MakeInstructionDescriptor(68, SpvOpAccessChain, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(67, spv::Op::OpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(69, SpvOpInBoundsAccessChain, 0);
+      MakeInstructionDescriptor(68, spv::Op::OpAccessChain, 0);
+  transformation =
+      TransformationToggleAccessChainInstruction(instructionDescriptor);
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
+
+  instructionDescriptor =
+      MakeInstructionDescriptor(69, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
@@ -187,14 +191,15 @@
 
   // Tests there being no instruction with the desired opcode after the base
   // instruction id
-  instructionDescriptor = MakeInstructionDescriptor(65, SpvOpAccessChain, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(65, spv::Op::OpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(66, SpvOpInBoundsAccessChain, 0);
+      MakeInstructionDescriptor(66, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
@@ -203,14 +208,15 @@
   // Tests there being an instruction with the desired opcode after the base
   // instruction id, but the skip count associated with the instruction
   // descriptor being so high.
-  instructionDescriptor = MakeInstructionDescriptor(11, SpvOpAccessChain, 100);
+  instructionDescriptor =
+      MakeInstructionDescriptor(11, spv::Op::OpAccessChain, 100);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(16, SpvOpInBoundsAccessChain, 100);
+      MakeInstructionDescriptor(16, spv::Op::OpInBoundsAccessChain, 100);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
@@ -312,29 +318,31 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instructionDescriptor =
-      MakeInstructionDescriptor(18, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(18, spv::Op::OpAccessChain, 0);
   auto transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instructionDescriptor =
-      MakeInstructionDescriptor(20, SpvOpInBoundsAccessChain, 0);
-  transformation =
-      TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-
-  instructionDescriptor = MakeInstructionDescriptor(24, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(20, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instructionDescriptor =
-      MakeInstructionDescriptor(26, SpvOpInBoundsAccessChain, 0);
+      MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(26, spv::Op::OpInBoundsAccessChain, 0);
+  transformation =
+      TransformationToggleAccessChainInstruction(instructionDescriptor);
+  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+
+  instructionDescriptor =
+      MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_vector_shuffle_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_vector_shuffle_test.cpp
index e3dc0a7..4d8f985 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_vector_shuffle_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_vector_shuffle_test.cpp
@@ -172,80 +172,82 @@
 
   // %103 does not dominate the return instruction.
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 103, 65,
-                   {3, 5, 7})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   103, 65, {3, 5, 7})
                    .IsApplicable(context.get(), transformation_context));
 
   // Illegal to shuffle a bvec2 and a vec3
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 112, 61,
-                   {0, 2, 4})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   112, 61, {0, 2, 4})
                    .IsApplicable(context.get(), transformation_context));
 
   // Illegal to shuffle an ivec2 and a uvec4
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 50,
-                   {1, 3, 5})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   27, 50, {1, 3, 5})
                    .IsApplicable(context.get(), transformation_context));
 
   // Vector 1 does not exist
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 300, 50,
-                   {1, 3, 5})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   300, 50, {1, 3, 5})
                    .IsApplicable(context.get(), transformation_context));
 
   // Vector 2 does not exist
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 300,
-                   {1, 3, 5})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   27, 300, {1, 3, 5})
                    .IsApplicable(context.get(), transformation_context));
 
   // Index out of range
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0, 20})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   12, 112, {0, 20})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Too many indices
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112,
-                   {0, 1, 0, 1, 0, 1, 0, 1})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   12, 112, {0, 1, 0, 1, 0, 1, 0, 1})
                    .IsApplicable(context.get(), transformation_context));
 
   // Too few indices
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   12, 112, {})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Too few indices again
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   12, 112, {0})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Indices define unknown type: we do not have vec2
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 65, 65, {0, 1})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   65, 65, {0, 1})
+                   .IsApplicable(context.get(), transformation_context));
 
   // The instruction to insert before does not exist
-  ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpCompositeConstruct, 1),
-                   201, 20, 12, {0xFFFFFFFF, 3, 5})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(100, spv::Op::OpCompositeConstruct, 1), 201,
+          20, 12, {0xFFFFFFFF, 3, 5})
+          .IsApplicable(context.get(), transformation_context));
 
   // The 'fresh' id is already in use
   ASSERT_FALSE(
       TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 12, 12, 112, {})
+          MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 12, 12, 112, {})
           .IsApplicable(context.get(), transformation_context));
 
   protobufs::DataDescriptor temp_dd;
 
   TransformationVectorShuffle transformation1(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {1, 0});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200, 12, 112,
+      {1, 0});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -258,7 +260,7 @@
       MakeDataDescriptor(10, {}), temp_dd));
 
   TransformationVectorShuffle transformation2(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 201, 20, 12,
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 201, 20, 12,
       {0xFFFFFFFF, 3, 5});
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
@@ -272,7 +274,8 @@
       MakeDataDescriptor(11, {}), temp_dd));
 
   TransformationVectorShuffle transformation3(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 202, 27, 35, {5, 4, 1});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 202, 27, 35,
+      {5, 4, 1});
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -288,7 +291,8 @@
       MakeDataDescriptor(26, {}), temp_dd));
 
   TransformationVectorShuffle transformation4(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 203, 42, 46, {0, 1});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 203, 42, 46,
+      {0, 1});
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
@@ -301,7 +305,8 @@
       MakeDataDescriptor(41, {}), temp_dd));
 
   TransformationVectorShuffle transformation5(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 204, 42, 46, {2, 3, 4});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 204, 42, 46,
+      {2, 3, 4});
   ASSERT_TRUE(
       transformation5.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation5, context.get(),
@@ -317,7 +322,7 @@
       MakeDataDescriptor(40, {}), temp_dd));
 
   TransformationVectorShuffle transformation6(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 205, 42, 42,
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 205, 42, 42,
       {0, 1, 2, 3});
   ASSERT_TRUE(
       transformation6.IsApplicable(context.get(), transformation_context));
@@ -338,7 +343,7 @@
 
   // swizzle vec4 from vec4 and vec4 using some undefs
   TransformationVectorShuffle transformation7(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 206, 65, 65,
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 206, 65, 65,
       {0xFFFFFFFF, 3, 6, 0xFFFFFFFF});
   ASSERT_TRUE(
       transformation7.IsApplicable(context.get(), transformation_context));
@@ -500,50 +505,52 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Cannot insert before the OpVariables of a function.
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, 14, {0, 1})
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, 14, {1, 2})
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, 14, {1, 2})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(101, spv::Op::OpVariable, 0), 200,
+                   14, 14, {0, 1})
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(101, spv::Op::OpVariable, 1), 200,
+                   14, 14, {1, 2})
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(102, spv::Op::OpVariable, 0), 200,
+                   14, 14, {1, 2})
+                   .IsApplicable(context.get(), transformation_context));
   // OK to insert right after the OpVariables.
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, 14, {1, 1})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(102, spv::Op::OpBranch, 1), 200,
+                   14, 14, {1, 1})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before the OpPhis of a block.
   ASSERT_FALSE(
-      TransformationVectorShuffle(MakeInstructionDescriptor(60, SpvOpPhi, 0),
-                                  200, 14, 14, {2, 0})
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(60, spv::Op::OpPhi, 0), 200, 14, 14, {2, 0})
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
-      TransformationVectorShuffle(MakeInstructionDescriptor(59, SpvOpPhi, 0),
-                                  200, 14, 14, {3, 0})
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(59, spv::Op::OpPhi, 0), 200, 14, 14, {3, 0})
           .IsApplicable(context.get(), transformation_context));
   // OK to insert after the OpPhis.
   ASSERT_TRUE(TransformationVectorShuffle(
-                  MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14,
-                  14, {3, 4})
+                  MakeInstructionDescriptor(59, spv::Op::OpAccessChain, 0), 200,
+                  14, 14, {3, 4})
                   .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpLoopMerge
-  ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
-                   200, 14, 14, {3})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0), 200,
+          14, 14, {3})
+          .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpSelectionMerge
-  ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
-                   200, 14, 14, {2})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0), 200,
+          14, 14, {2})
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationVectorShuffleTest, HandlesIrrelevantIds1) {
@@ -615,7 +622,8 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationVectorShuffle transformation(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {2, 0});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200, 12, 112,
+      {2, 0});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -697,7 +705,8 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(112);
   TransformationVectorShuffle transformation(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {2, 0});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200, 12, 112,
+      {2, 0});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -755,7 +764,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
 
   TransformationVectorShuffle transformation1(
-      MakeInstructionDescriptor(15, SpvOpBranch, 0), 200, 12, 12, {0, 3});
+      MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 200, 12, 12, {0, 3});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -766,7 +775,7 @@
       MakeDataDescriptor(200, {1}), MakeDataDescriptor(12, {1})));
 
   TransformationVectorShuffle transformation2(
-      MakeInstructionDescriptor(16, SpvOpReturn, 0), 201, 12, 40, {0, 1});
+      MakeInstructionDescriptor(16, spv::Op::OpReturn, 0), 201, 12, 40, {0, 1});
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -777,7 +786,7 @@
       MakeDataDescriptor(201, {1}), MakeDataDescriptor(12, {1})));
 
   TransformationVectorShuffle transformation3(
-      MakeInstructionDescriptor(16, SpvOpReturn, 0), 202, 40, 12, {2, 3});
+      MakeInstructionDescriptor(16, spv::Op::OpReturn, 0), 202, 40, 12, {2, 3});
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -788,7 +797,7 @@
       MakeDataDescriptor(202, {1}), MakeDataDescriptor(12, {1})));
 
   TransformationVectorShuffle transformation4(
-      MakeInstructionDescriptor(16, SpvOpReturn, 0), 203, 40, 12, {0, 3});
+      MakeInstructionDescriptor(16, spv::Op::OpReturn, 0), 203, 40, 12, {0, 3});
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
diff --git a/third_party/SPIRV-Tools/test/fuzz/transformation_wrap_early_terminator_in_function_test.cpp b/third_party/SPIRV-Tools/test/fuzz/transformation_wrap_early_terminator_in_function_test.cpp
index 7b4e487..fbbf57b 100644
--- a/third_party/SPIRV-Tools/test/fuzz/transformation_wrap_early_terminator_in_function_test.cpp
+++ b/third_party/SPIRV-Tools/test/fuzz/transformation_wrap_early_terminator_in_function_test.cpp
@@ -98,48 +98,50 @@
 
   // Bad: id is not fresh
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   61, MakeInstructionDescriptor(8, SpvOpKill, 0), 0)
+                   61, MakeInstructionDescriptor(8, spv::Op::OpKill, 0), 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: early terminator instruction descriptor does not exist
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(82, SpvOpKill, 0), 0)
+                   100, MakeInstructionDescriptor(82, spv::Op::OpKill, 0), 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: early terminator instruction does not identify an early terminator
-  ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(5, SpvOpSelectionMerge, 0), 0)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationWrapEarlyTerminatorInFunction(
+          100, MakeInstructionDescriptor(5, spv::Op::OpSelectionMerge, 0), 0)
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: no wrapper function is available
-  ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(9, SpvOpUnreachable, 0), 0)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationWrapEarlyTerminatorInFunction(
+          100, MakeInstructionDescriptor(9, spv::Op::OpUnreachable, 0), 0)
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: returned value does not exist
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(62, SpvOpKill, 0), 1000)
+                   100, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 1000)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: returned value does not have a type
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(62, SpvOpKill, 0), 61)
+                   100, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 61)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: returned value type does not match
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(62, SpvOpKill, 0), 91)
+                   100, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 91)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: returned value is not available
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(62, SpvOpKill, 0), 81)
+                   100, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 81)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: the OpKill being targeted is in the only available wrapper; we cannot
   // have the wrapper call itself.
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(31, SpvOpKill, 0), 0)
+                   100, MakeInstructionDescriptor(31, spv::Op::OpKill, 0), 0)
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -220,17 +222,20 @@
 
   for (auto& transformation :
        {TransformationWrapEarlyTerminatorInFunction(
-            100, MakeInstructionDescriptor(8, SpvOpKill, 0), 0),
+            100, MakeInstructionDescriptor(8, spv::Op::OpKill, 0), 0),
         TransformationWrapEarlyTerminatorInFunction(
-            101, MakeInstructionDescriptor(9, SpvOpUnreachable, 0), 0),
+            101, MakeInstructionDescriptor(9, spv::Op::OpUnreachable, 0), 0),
         TransformationWrapEarlyTerminatorInFunction(
-            102, MakeInstructionDescriptor(10, SpvOpTerminateInvocation, 0), 0),
+            102,
+            MakeInstructionDescriptor(10, spv::Op::OpTerminateInvocation, 0),
+            0),
         TransformationWrapEarlyTerminatorInFunction(
-            103, MakeInstructionDescriptor(62, SpvOpKill, 0), 0),
+            103, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 0),
         TransformationWrapEarlyTerminatorInFunction(
-            104, MakeInstructionDescriptor(71, SpvOpUnreachable, 0), 7),
+            104, MakeInstructionDescriptor(71, spv::Op::OpUnreachable, 0), 7),
         TransformationWrapEarlyTerminatorInFunction(
-            105, MakeInstructionDescriptor(82, SpvOpTerminateInvocation, 0),
+            105,
+            MakeInstructionDescriptor(82, spv::Op::OpTerminateInvocation, 0),
             0)}) {
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
diff --git a/third_party/SPIRV-Tools/test/immediate_int_test.cpp b/third_party/SPIRV-Tools/test/immediate_int_test.cpp
index 393075a..8e7a8fd 100644
--- a/third_party/SPIRV-Tools/test/immediate_int_test.cpp
+++ b/third_party/SPIRV-Tools/test/immediate_int_test.cpp
@@ -57,34 +57,34 @@
 
 TEST_F(ImmediateIntTest, AnyWordInSimpleStatement) {
   EXPECT_THAT(CompiledInstructions("!0x00040018 %a %b %123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 3})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 3})));
   EXPECT_THAT(CompiledInstructions("!0x00040018 !1 %b %123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 1, 2})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 1, 2})));
   EXPECT_THAT(CompiledInstructions("%a = OpTypeMatrix !2 %123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 2})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 2})));
   EXPECT_THAT(CompiledInstructions("%a = OpTypeMatrix  %b !123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 123})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 123})));
   EXPECT_THAT(CompiledInstructions("!0x00040018 %a !2 %123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 2})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 2})));
   EXPECT_THAT(CompiledInstructions("!0x00040018 !1 %b !123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 1, 123})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 1, 123})));
   EXPECT_THAT(CompiledInstructions("!0x00040018 !1 !2 !123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 123})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 123})));
 }
 
 TEST_F(ImmediateIntTest, AnyWordAfterEqualsAndOpCode) {
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength !2 %c 123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {2, 1, 2, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {2, 1, 2, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength %b !3 123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {1, 2, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {1, 2, 3, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength %b %c !123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {1, 2, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {1, 2, 3, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength %b !3 !123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {1, 2, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {1, 2, 3, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength !2 !3 123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {2, 1, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {2, 1, 3, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength !2 !3 !123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {2, 1, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {2, 1, 3, 123})));
 }
 
 TEST_F(ImmediateIntTest, ResultIdInAssignment) {
@@ -108,8 +108,8 @@
   // With !<integer>, we can (and can only) accept 32-bit number literals,
   // even when we declare the return type is 64-bit.
   EXPECT_EQ(Concatenate({
-                MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-                MakeInstruction(SpvOpConstant, {1, 2, 4294967295}),
+                MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+                MakeInstruction(spv::Op::OpConstant, {1, 2, 4294967295}),
             }),
             CompiledInstructions("%i64 = OpTypeInt 64 0\n"
                                  "!0x0004002b %i64 !2 4294967295"));
@@ -151,9 +151,9 @@
       CompiledInstructions("%1 = OpTypeFloat 32\n!0x0004002b %1 %2 -0.5"));
 
   EXPECT_EQ(Concatenate({
-                MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-                MakeInstruction(SpvOpConstant, {1, 2, 0xb, 0xa}),
-                MakeInstruction(SpvOpSwitch,
+                MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+                MakeInstruction(spv::Op::OpConstant, {1, 2, 0xb, 0xa}),
+                MakeInstruction(spv::Op::OpSwitch,
                                 {2, 1234, BitwiseCast<uint32_t>(2.5f), 3}),
             }),
             CompiledInstructions("%i64 = OpTypeInt 64 0\n"
@@ -174,7 +174,7 @@
               CompiledInstructions("OpMemberName !1 !4 \"" + name + "\""))
         << name;
     const uint16_t wordCount = static_cast<uint16_t>(4 + name.size() / 4);
-    const uint32_t firstWord = spvOpcodeMake(wordCount, SpvOpMemberName);
+    const uint32_t firstWord = spvOpcodeMake(wordCount, spv::Op::OpMemberName);
     EXPECT_EQ(original, CompiledInstructions("!" + std::to_string(firstWord) +
                                              " %10 !4 \"" + name + "\""))
         << name;
@@ -205,8 +205,8 @@
   EXPECT_THAT(Subvector(CompileSuccessfully(
                             "%10 = OpTypeFloat 32 !5 !6 !7 OpEmitVertex"),
                         kFirstInstruction),
-              ElementsAre(spvOpcodeMake(3, SpvOpTypeFloat), 1, 32, 5, 6, 7,
-                          spvOpcodeMake(1, SpvOpEmitVertex)));
+              ElementsAre(spvOpcodeMake(3, spv::Op::OpTypeFloat), 1, 32, 5, 6,
+                          7, spvOpcodeMake(1, spv::Op::OpEmitVertex)));
 }
 
 TEST_F(ImmediateIntTest, NextOpcodeRecognized) {
diff --git a/third_party/SPIRV-Tools/test/link/binary_version_test.cpp b/third_party/SPIRV-Tools/test/link/binary_version_test.cpp
index a56030f..78da1ae 100644
--- a/third_party/SPIRV-Tools/test/link/binary_version_test.cpp
+++ b/third_party/SPIRV-Tools/test/link/binary_version_test.cpp
@@ -27,20 +27,20 @@
   return {
       // clang-format off
       // Header
-      SpvMagicNumber,
+      static_cast<uint32_t>(spv::MagicNumber),
       version,
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
       1u,  // NOTE: Bound
       0u,  // NOTE: Schema; reserved
 
       // OpCapability Shader
-      SpvOpCapability | 2u << SpvWordCountShift,
-      SpvCapabilityShader,
+      static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::Capability::Shader),
 
       // OpMemoryModel Logical Simple
-      SpvOpMemoryModel | 3u << SpvWordCountShift,
-      SpvAddressingModelLogical,
-      SpvMemoryModelSimple
+      static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::AddressingModel::Logical),
+      static_cast<uint32_t>(spv::MemoryModel::Simple)
       // clang-format on
   };
 }
diff --git a/third_party/SPIRV-Tools/test/link/global_values_amount_test.cpp b/third_party/SPIRV-Tools/test/link/global_values_amount_test.cpp
index 3158b7e..fda55d6 100644
--- a/third_party/SPIRV-Tools/test/link/global_values_amount_test.cpp
+++ b/third_party/SPIRV-Tools/test/link/global_values_amount_test.cpp
@@ -34,26 +34,26 @@
 
     spvtest::Binary common_binary = {
         // clang-format off
-        SpvMagicNumber,
-        SpvVersion,
+        static_cast<uint32_t>(spv::MagicNumber),
+        static_cast<uint32_t>(spv::Version),
         SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
         3u + global_variable_count_per_binary,  // NOTE: Bound
         0u,                                     // NOTE: Schema; reserved
 
-        SpvOpCapability | 2u << SpvWordCountShift,
-        SpvCapabilityShader,
+        static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+        static_cast<uint32_t>(spv::Capability::Shader),
 
-        SpvOpMemoryModel | 3u << SpvWordCountShift,
-        SpvAddressingModelLogical,
-        SpvMemoryModelSimple,
+        static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+        static_cast<uint32_t>(spv::AddressingModel::Logical),
+        static_cast<uint32_t>(spv::MemoryModel::Simple),
 
-        SpvOpTypeFloat | 3u << SpvWordCountShift,
+        static_cast<uint32_t>(spv::Op::OpTypeFloat) | 3u << spv::WordCountShift,
         1u,   // NOTE: Result ID
         32u,  // NOTE: Width
 
-        SpvOpTypePointer | 4u << SpvWordCountShift,
+        static_cast<uint32_t>(spv::Op::OpTypePointer) | 4u << spv::WordCountShift,
         2u,  // NOTE: Result ID
-        SpvStorageClassInput,
+        static_cast<uint32_t>(spv::StorageClass::Input),
         1u  // NOTE: Type ID
         // clang-format on
     };
@@ -64,10 +64,11 @@
     binary.insert(binary.end(), common_binary.cbegin(), common_binary.cend());
 
     for (uint32_t i = 0u; i < global_variable_count_per_binary; ++i) {
-      binary.push_back(SpvOpVariable | 4u << SpvWordCountShift);
+      binary.push_back(static_cast<uint32_t>(spv::Op::OpVariable) |
+                       4u << spv::WordCountShift);
       binary.push_back(2u);      // NOTE: Type ID
       binary.push_back(3u + i);  // NOTE: Result ID
-      binary.push_back(SpvStorageClassInput);
+      binary.push_back(static_cast<uint32_t>(spv::StorageClass::Input));
     }
 
     for (uint32_t i = 0u; i < binary_count - 1u; ++i) {
@@ -89,37 +90,37 @@
 TEST_F(EntryPointsAmountTest, OverLimit) {
   binaries.push_back({
       // clang-format off
-      SpvMagicNumber,
-      SpvVersion,
+      static_cast<uint32_t>(spv::MagicNumber),
+      static_cast<uint32_t>(spv::Version),
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
       5u,  // NOTE: Bound
       0u,  // NOTE: Schema; reserved
 
-      SpvOpCapability | 2u << SpvWordCountShift,
-      SpvCapabilityShader,
+      static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::Capability::Shader),
 
-      SpvOpMemoryModel | 3u << SpvWordCountShift,
-      SpvAddressingModelLogical,
-      SpvMemoryModelSimple,
+      static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::AddressingModel::Logical),
+      static_cast<uint32_t>(spv::MemoryModel::Simple),
 
-      SpvOpTypeFloat | 3u << SpvWordCountShift,
+      static_cast<uint32_t>(spv::Op::OpTypeFloat) | 3u << spv::WordCountShift,
       1u,   // NOTE: Result ID
       32u,  // NOTE: Width
 
-      SpvOpTypePointer | 4u << SpvWordCountShift,
+      static_cast<uint32_t>(spv::Op::OpTypePointer) | 4u << spv::WordCountShift,
       2u,  // NOTE: Result ID
-      SpvStorageClassInput,
+      static_cast<uint32_t>(spv::StorageClass::Input),
       1u,  // NOTE: Type ID
 
-      SpvOpVariable | 4u << SpvWordCountShift,
+      static_cast<uint32_t>(spv::Op::OpVariable) | 4u << spv::WordCountShift,
       2u,  // NOTE: Type ID
       3u,  // NOTE: Result ID
-      SpvStorageClassInput,
+      static_cast<uint32_t>(spv::StorageClass::Input),
 
-      SpvOpVariable | 4u << SpvWordCountShift,
+      static_cast<uint32_t>(spv::Op::OpVariable) | 4u << spv::WordCountShift,
       2u,  // NOTE: Type ID
       4u,  // NOTE: Result ID
-      SpvStorageClassInput
+      static_cast<uint32_t>(spv::StorageClass::Input)
       // clang-format on
   });
 
diff --git a/third_party/SPIRV-Tools/test/link/ids_limit_test.cpp b/third_party/SPIRV-Tools/test/link/ids_limit_test.cpp
index 846fbef..8182e5d 100644
--- a/third_party/SPIRV-Tools/test/link/ids_limit_test.cpp
+++ b/third_party/SPIRV-Tools/test/link/ids_limit_test.cpp
@@ -36,20 +36,20 @@
     // running the RemoveDuplicates pass.
     spvtest::Binary common_binary = {
         // clang-format off
-        SpvMagicNumber,
-        SpvVersion,
+        spv::MagicNumber,
+        spv::Version,
         SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
         id_bound,  // NOTE: Bound
         0u,        // NOTE: Schema; reserved
 
-        SpvOpCapability | 2u << SpvWordCountShift,
-        SpvCapabilityShader,
+        static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+        static_cast<uint32_t>(spv::Capability::Shader),
 
-        SpvOpMemoryModel | 3u << SpvWordCountShift,
-        SpvAddressingModelLogical,
-        SpvMemoryModelSimple,
+        static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+        static_cast<uint32_t>(spv::AddressingModel::Logical),
+        static_cast<uint32_t>(spv::MemoryModel::Simple),
 
-        SpvOpTypeBool | 2u << SpvWordCountShift,
+        static_cast<uint32_t>(spv::Op::OpTypeBool) | 2u << spv::WordCountShift,
         1u    // NOTE: Result ID
         // clang-format on
     };
@@ -60,7 +60,8 @@
     binary.insert(binary.end(), common_binary.cbegin(), common_binary.cend());
 
     for (uint32_t i = 0u; i < constant_count; ++i) {
-      binary.push_back(SpvOpConstantTrue | 3u << SpvWordCountShift);
+      binary.push_back(static_cast<uint32_t>(spv::Op::OpConstantTrue) |
+                       3u << spv::WordCountShift);
       binary.push_back(1u);      // NOTE: Type ID
       binary.push_back(2u + i);  // NOTE: Result ID
     }
@@ -74,20 +75,20 @@
   return {
       // clang-format off
       // Header
-      SpvMagicNumber,
-      SpvVersion,
+      spv::MagicNumber,
+      spv::Version,
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
       id_bound,  // NOTE: Bound
       0u,        // NOTE: Schema; reserved
 
       // OpCapability Shader
-      SpvOpCapability | 2u << SpvWordCountShift,
-      SpvCapabilityShader,
+      static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::Capability::Shader),
 
       // OpMemoryModel Logical Simple
-      SpvOpMemoryModel | 3u << SpvWordCountShift,
-      SpvAddressingModelLogical,
-      SpvMemoryModelSimple
+      static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::AddressingModel::Logical),
+      static_cast<uint32_t>(spv::MemoryModel::Simple)
       // clang-format on
   };
 }
@@ -105,7 +106,8 @@
   const uint32_t id_bound = binary[3];
   binary[3] = id_bound + 1u;
 
-  binary.push_back(SpvOpConstantFalse | 3u << SpvWordCountShift);
+  binary.push_back(static_cast<uint32_t>(spv::Op::OpConstantFalse) |
+                   3u << spv::WordCountShift);
   binary.push_back(1u);        // NOTE: Type ID
   binary.push_back(id_bound);  // NOTE: Result ID
 
diff --git a/third_party/SPIRV-Tools/test/link/memory_model_test.cpp b/third_party/SPIRV-Tools/test/link/memory_model_test.cpp
index 280a776..ee63c59 100644
--- a/third_party/SPIRV-Tools/test/link/memory_model_test.cpp
+++ b/third_party/SPIRV-Tools/test/link/memory_model_test.cpp
@@ -35,8 +35,10 @@
   ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary));
   EXPECT_THAT(GetErrorMessage(), std::string());
 
-  EXPECT_EQ(SpvAddressingModelLogical, linked_binary[6]);
-  EXPECT_EQ(SpvMemoryModelSimple, linked_binary[7]);
+  EXPECT_EQ(spv::AddressingModel::Logical,
+            static_cast<spv::AddressingModel>(linked_binary[6]));
+  EXPECT_EQ(spv::MemoryModel::Simple,
+            static_cast<spv::MemoryModel>(linked_binary[7]));
 }
 
 TEST_F(MemoryModel, AddressingMismatch) {
diff --git a/third_party/SPIRV-Tools/test/opcode_make_test.cpp b/third_party/SPIRV-Tools/test/opcode_make_test.cpp
index 6481ef3..6c1dab6 100644
--- a/third_party/SPIRV-Tools/test/opcode_make_test.cpp
+++ b/third_party/SPIRV-Tools/test/opcode_make_test.cpp
@@ -35,7 +35,7 @@
       uint32_t word = 0;
       word |= uint32_t(opcode);
       word |= uint32_t(wordCount) << 16;
-      EXPECT_EQ(word, spvOpcodeMake(wordCount, SpvOp(opcode)));
+      EXPECT_EQ(word, spvOpcodeMake(wordCount, spv::Op(opcode)));
     }
   }
 }
diff --git a/third_party/SPIRV-Tools/test/opcode_require_capabilities_test.cpp b/third_party/SPIRV-Tools/test/opcode_require_capabilities_test.cpp
index 07e86f8..37097c6 100644
--- a/third_party/SPIRV-Tools/test/opcode_require_capabilities_test.cpp
+++ b/third_party/SPIRV-Tools/test/opcode_require_capabilities_test.cpp
@@ -23,7 +23,7 @@
 
 // Capabilities required by an Opcode.
 struct ExpectedOpCodeCapabilities {
-  SpvOp opcode;
+  spv::Op opcode;
   CapabilitySet capabilities;
 };
 
@@ -46,33 +46,36 @@
     TableRowTest, OpcodeTableCapabilitiesTest,
     // Spot-check a few opcodes.
     ::testing::Values(
+        ExpectedOpCodeCapabilities{spv::Op::OpImageQuerySize,
+                                   CapabilitySet{spv::Capability::Kernel,
+                                                 spv::Capability::ImageQuery}},
+        ExpectedOpCodeCapabilities{spv::Op::OpImageQuerySizeLod,
+                                   CapabilitySet{spv::Capability::Kernel,
+                                                 spv::Capability::ImageQuery}},
+        ExpectedOpCodeCapabilities{spv::Op::OpImageQueryLevels,
+                                   CapabilitySet{spv::Capability::Kernel,
+                                                 spv::Capability::ImageQuery}},
+        ExpectedOpCodeCapabilities{spv::Op::OpImageQuerySamples,
+                                   CapabilitySet{spv::Capability::Kernel,
+                                                 spv::Capability::ImageQuery}},
         ExpectedOpCodeCapabilities{
-            SpvOpImageQuerySize,
-            CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}},
+            spv::Op::OpImageSparseSampleImplicitLod,
+            CapabilitySet{spv::Capability::SparseResidency}},
+        ExpectedOpCodeCapabilities{spv::Op::OpCopyMemorySized,
+                                   CapabilitySet{spv::Capability::Addresses}},
+        ExpectedOpCodeCapabilities{spv::Op::OpArrayLength,
+                                   CapabilitySet{spv::Capability::Shader}},
+        ExpectedOpCodeCapabilities{spv::Op::OpFunction, CapabilitySet()},
+        ExpectedOpCodeCapabilities{spv::Op::OpConvertFToS, CapabilitySet()},
         ExpectedOpCodeCapabilities{
-            SpvOpImageQuerySizeLod,
-            CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}},
+            spv::Op::OpEmitStreamVertex,
+            CapabilitySet{spv::Capability::GeometryStreams}},
         ExpectedOpCodeCapabilities{
-            SpvOpImageQueryLevels,
-            CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}},
+            spv::Op::OpTypeNamedBarrier,
+            CapabilitySet{spv::Capability::NamedBarrier}},
         ExpectedOpCodeCapabilities{
-            SpvOpImageQuerySamples,
-            CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}},
-        ExpectedOpCodeCapabilities{SpvOpImageSparseSampleImplicitLod,
-                                   CapabilitySet{SpvCapabilitySparseResidency}},
-        ExpectedOpCodeCapabilities{SpvOpCopyMemorySized,
-                                   CapabilitySet{SpvCapabilityAddresses}},
-        ExpectedOpCodeCapabilities{SpvOpArrayLength,
-                                   CapabilitySet{SpvCapabilityShader}},
-        ExpectedOpCodeCapabilities{SpvOpFunction, CapabilitySet()},
-        ExpectedOpCodeCapabilities{SpvOpConvertFToS, CapabilitySet()},
-        ExpectedOpCodeCapabilities{SpvOpEmitStreamVertex,
-                                   CapabilitySet{SpvCapabilityGeometryStreams}},
-        ExpectedOpCodeCapabilities{SpvOpTypeNamedBarrier,
-                                   CapabilitySet{SpvCapabilityNamedBarrier}},
-        ExpectedOpCodeCapabilities{
-            SpvOpGetKernelMaxNumSubgroups,
-            CapabilitySet{SpvCapabilitySubgroupDispatch}}));
+            spv::Op::OpGetKernelMaxNumSubgroups,
+            CapabilitySet{spv::Capability::SubgroupDispatch}}));
 
 }  // namespace
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opcode_split_test.cpp b/third_party/SPIRV-Tools/test/opcode_split_test.cpp
index 43fedb3..e8a67b6 100644
--- a/third_party/SPIRV-Tools/test/opcode_split_test.cpp
+++ b/third_party/SPIRV-Tools/test/opcode_split_test.cpp
@@ -18,7 +18,7 @@
 namespace {
 
 TEST(OpcodeSplit, Default) {
-  uint32_t word = spvOpcodeMake(42, (SpvOp)23);
+  uint32_t word = spvOpcodeMake(42, (spv::Op)23);
   uint16_t wordCount = 0;
   uint16_t opcode;
   spvOpcodeSplit(word, &wordCount, &opcode);
diff --git a/third_party/SPIRV-Tools/test/operand_capabilities_test.cpp b/third_party/SPIRV-Tools/test/operand_capabilities_test.cpp
index bc0ee05..10ed82a 100644
--- a/third_party/SPIRV-Tools/test/operand_capabilities_test.cpp
+++ b/third_party/SPIRV-Tools/test/operand_capabilities_test.cpp
@@ -62,39 +62,47 @@
 
 #define CASE0(TYPE, VALUE)                            \
   {                                                   \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), {} \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), {} \
   }
 #define CASE1(TYPE, VALUE, CAP)                                    \
   {                                                                \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet { \
-      SpvCapability##CAP                                           \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet { \
+      spv::Capability::CAP                                         \
     }                                                              \
   }
 #define CASE2(TYPE, VALUE, CAP1, CAP2)                             \
   {                                                                \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet { \
-      SpvCapability##CAP1, SpvCapability##CAP2                     \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet { \
+      spv::Capability::CAP1, spv::Capability::CAP2                 \
     }                                                              \
   }
-#define CASE3(TYPE, VALUE, CAP1, CAP2, CAP3)                        \
-  {                                                                 \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet {  \
-      SpvCapability##CAP1, SpvCapability##CAP2, SpvCapability##CAP3 \
-    }                                                               \
+#define CASE3(TYPE, VALUE, CAP1, CAP2, CAP3)                              \
+  {                                                                       \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet {        \
+      spv::Capability::CAP1, spv::Capability::CAP2, spv::Capability::CAP3 \
+    }                                                                     \
   }
-#define CASE4(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4)                   \
-  {                                                                  \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet {   \
-      SpvCapability##CAP1, SpvCapability##CAP2, SpvCapability##CAP3, \
-          SpvCapability##CAP4                                        \
-    }                                                                \
+#define CASE4(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4)                         \
+  {                                                                        \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet {         \
+      spv::Capability::CAP1, spv::Capability::CAP2, spv::Capability::CAP3, \
+          spv::Capability::CAP4                                            \
+    }                                                                      \
   }
-#define CASE5(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4, CAP5)             \
-  {                                                                  \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet {   \
-      SpvCapability##CAP1, SpvCapability##CAP2, SpvCapability##CAP3, \
-          SpvCapability##CAP4, SpvCapability##CAP5                   \
-    }                                                                \
+#define CASE5(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4, CAP5)                   \
+  {                                                                        \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet {         \
+      spv::Capability::CAP1, spv::Capability::CAP2, spv::Capability::CAP3, \
+          spv::Capability::CAP4, spv::Capability::CAP5                     \
+    }                                                                      \
+  }
+
+#define CASE6(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4, CAP5, CAP6)                \
+  {                                                                           \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet {            \
+      spv::Capability::CAP1, spv::Capability::CAP2, spv::Capability::CAP3,    \
+          spv::Capability::CAP4, spv::Capability::CAP5, spv::Capability::CAP6 \
+    }                                                                         \
   }
 
 // See SPIR-V Section 3.3 Execution Model
@@ -102,15 +110,15 @@
     ExecutionModel, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(EXECUTION_MODEL, ExecutionModelVertex, Shader),
-                CASE1(EXECUTION_MODEL, ExecutionModelTessellationControl,
+                CASE1(EXECUTION_MODEL, ExecutionModel::Vertex, Shader),
+                CASE1(EXECUTION_MODEL, ExecutionModel::TessellationControl,
                       Tessellation),
-                CASE1(EXECUTION_MODEL, ExecutionModelTessellationEvaluation,
+                CASE1(EXECUTION_MODEL, ExecutionModel::TessellationEvaluation,
                       Tessellation),
-                CASE1(EXECUTION_MODEL, ExecutionModelGeometry, Geometry),
-                CASE1(EXECUTION_MODEL, ExecutionModelFragment, Shader),
-                CASE1(EXECUTION_MODEL, ExecutionModelGLCompute, Shader),
-                CASE1(EXECUTION_MODEL, ExecutionModelKernel, Kernel),
+                CASE1(EXECUTION_MODEL, ExecutionModel::Geometry, Geometry),
+                CASE1(EXECUTION_MODEL, ExecutionModel::Fragment, Shader),
+                CASE1(EXECUTION_MODEL, ExecutionModel::GLCompute, Shader),
+                CASE1(EXECUTION_MODEL, ExecutionModel::Kernel, Kernel),
             })));
 
 // See SPIR-V Section 3.4 Addressing Model
@@ -118,9 +126,9 @@
     AddressingModel, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(ADDRESSING_MODEL, AddressingModelLogical),
-                CASE1(ADDRESSING_MODEL, AddressingModelPhysical32, Addresses),
-                CASE1(ADDRESSING_MODEL, AddressingModelPhysical64, Addresses),
+                CASE0(ADDRESSING_MODEL, AddressingModel::Logical),
+                CASE1(ADDRESSING_MODEL, AddressingModel::Physical32, Addresses),
+                CASE1(ADDRESSING_MODEL, AddressingModel::Physical64, Addresses),
             })));
 
 // See SPIR-V Section 3.5 Memory Model
@@ -128,9 +136,9 @@
     MemoryModel, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(MEMORY_MODEL, MemoryModelSimple, Shader),
-                CASE1(MEMORY_MODEL, MemoryModelGLSL450, Shader),
-                CASE1(MEMORY_MODEL, MemoryModelOpenCL, Kernel),
+                CASE1(MEMORY_MODEL, MemoryModel::Simple, Shader),
+                CASE1(MEMORY_MODEL, MemoryModel::GLSL450, Shader),
+                CASE1(MEMORY_MODEL, MemoryModel::OpenCL, Kernel),
             })));
 
 // See SPIR-V Section 3.6 Execution Mode
@@ -139,54 +147,54 @@
     Combine(
         Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
         ValuesIn(std::vector<EnumCapabilityCase>{
-            CASE1(EXECUTION_MODE, ExecutionModeInvocations, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeSpacingEqual, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeSpacingFractionalEven,
+            CASE1(EXECUTION_MODE, ExecutionMode::Invocations, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::SpacingEqual, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::SpacingFractionalEven,
                   Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeSpacingFractionalOdd,
+            CASE1(EXECUTION_MODE, ExecutionMode::SpacingFractionalOdd,
                   Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeVertexOrderCw, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeVertexOrderCcw, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModePixelCenterInteger, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeOriginUpperLeft, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeOriginLowerLeft, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeEarlyFragmentTests, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModePointMode, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeXfb, TransformFeedback),
-            CASE1(EXECUTION_MODE, ExecutionModeDepthReplacing, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeDepthGreater, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeDepthLess, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeDepthUnchanged, Shader),
-            CASE0(EXECUTION_MODE, ExecutionModeLocalSize),
-            CASE1(EXECUTION_MODE, ExecutionModeLocalSizeHint, Kernel),
-            CASE1(EXECUTION_MODE, ExecutionModeInputPoints, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeInputLines, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeInputLinesAdjacency, Geometry),
-            CASE2(EXECUTION_MODE, ExecutionModeTriangles, Geometry,
+            CASE1(EXECUTION_MODE, ExecutionMode::VertexOrderCw, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::VertexOrderCcw, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::PixelCenterInteger, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::OriginUpperLeft, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::OriginLowerLeft, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::EarlyFragmentTests, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::PointMode, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::Xfb, TransformFeedback),
+            CASE1(EXECUTION_MODE, ExecutionMode::DepthReplacing, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::DepthGreater, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::DepthLess, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::DepthUnchanged, Shader),
+            CASE0(EXECUTION_MODE, ExecutionMode::LocalSize),
+            CASE1(EXECUTION_MODE, ExecutionMode::LocalSizeHint, Kernel),
+            CASE1(EXECUTION_MODE, ExecutionMode::InputPoints, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::InputLines, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::InputLinesAdjacency, Geometry),
+            CASE2(EXECUTION_MODE, ExecutionMode::Triangles, Geometry,
                   Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeInputTrianglesAdjacency,
+            CASE1(EXECUTION_MODE, ExecutionMode::InputTrianglesAdjacency,
                   Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeQuads, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeIsolines, Tessellation),
-            CASE3(EXECUTION_MODE, ExecutionModeOutputVertices, Geometry,
-                  Tessellation, MeshShadingNV),
-            CASE2(EXECUTION_MODE, ExecutionModeOutputPoints, Geometry,
-                  MeshShadingNV),
-            CASE1(EXECUTION_MODE, ExecutionModeOutputLineStrip, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeOutputTriangleStrip, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeVecTypeHint, Kernel),
-            CASE1(EXECUTION_MODE, ExecutionModeContractionOff, Kernel),
+            CASE1(EXECUTION_MODE, ExecutionMode::Quads, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::Isolines, Tessellation),
+            CASE4(EXECUTION_MODE, ExecutionMode::OutputVertices, Geometry,
+                  Tessellation, MeshShadingNV, MeshShadingEXT),
+            CASE3(EXECUTION_MODE, ExecutionMode::OutputPoints, Geometry,
+                  MeshShadingNV, MeshShadingEXT),
+            CASE1(EXECUTION_MODE, ExecutionMode::OutputLineStrip, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::OutputTriangleStrip, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::VecTypeHint, Kernel),
+            CASE1(EXECUTION_MODE, ExecutionMode::ContractionOff, Kernel),
         })));
 
 INSTANTIATE_TEST_SUITE_P(
     ExecutionModeV11, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(EXECUTION_MODE, ExecutionModeInitializer, Kernel),
-                CASE1(EXECUTION_MODE, ExecutionModeFinalizer, Kernel),
-                CASE1(EXECUTION_MODE, ExecutionModeSubgroupSize,
+                CASE1(EXECUTION_MODE, ExecutionMode::Initializer, Kernel),
+                CASE1(EXECUTION_MODE, ExecutionMode::Finalizer, Kernel),
+                CASE1(EXECUTION_MODE, ExecutionMode::SubgroupSize,
                       SubgroupDispatch),
-                CASE1(EXECUTION_MODE, ExecutionModeSubgroupsPerWorkgroup,
+                CASE1(EXECUTION_MODE, ExecutionMode::SubgroupsPerWorkgroup,
                       SubgroupDispatch)})));
 
 // See SPIR-V Section 3.7 Storage Class
@@ -194,19 +202,20 @@
     StorageClass, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(STORAGE_CLASS, StorageClassUniformConstant),
-                CASE1(STORAGE_CLASS, StorageClassUniform, Shader),
-                CASE1(STORAGE_CLASS, StorageClassOutput, Shader),
-                CASE0(STORAGE_CLASS, StorageClassWorkgroup),
-                CASE0(STORAGE_CLASS, StorageClassCrossWorkgroup),
-                CASE2(STORAGE_CLASS, StorageClassPrivate, Shader,
+                CASE0(STORAGE_CLASS, StorageClass::UniformConstant),
+                CASE1(STORAGE_CLASS, StorageClass::Uniform, Shader),
+                CASE1(STORAGE_CLASS, StorageClass::Output, Shader),
+                CASE0(STORAGE_CLASS, StorageClass::Workgroup),
+                CASE0(STORAGE_CLASS, StorageClass::CrossWorkgroup),
+                CASE2(STORAGE_CLASS, StorageClass::Private, Shader,
                       VectorComputeINTEL),
-                CASE0(STORAGE_CLASS, StorageClassFunction),
-                CASE1(STORAGE_CLASS, StorageClassGeneric,
+                CASE0(STORAGE_CLASS, StorageClass::Function),
+                CASE1(STORAGE_CLASS, StorageClass::Generic,
                       GenericPointer),  // Bug 14287
-                CASE1(STORAGE_CLASS, StorageClassPushConstant, Shader),
-                CASE1(STORAGE_CLASS, StorageClassAtomicCounter, AtomicStorage),
-                CASE0(STORAGE_CLASS, StorageClassImage),
+                CASE1(STORAGE_CLASS, StorageClass::PushConstant, Shader),
+                CASE1(STORAGE_CLASS, StorageClass::AtomicCounter,
+                      AtomicStorage),
+                CASE0(STORAGE_CLASS, StorageClass::Image),
             })));
 
 // See SPIR-V Section 3.8 Dim
@@ -214,37 +223,39 @@
     Dim, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE2(DIMENSIONALITY, Dim1D, Sampled1D, Image1D),
-                CASE3(DIMENSIONALITY, Dim2D, Kernel, Shader, ImageMSArray),
-                CASE0(DIMENSIONALITY, Dim3D),
-                CASE2(DIMENSIONALITY, DimCube, Shader, ImageCubeArray),
-                CASE2(DIMENSIONALITY, DimRect, SampledRect, ImageRect),
-                CASE2(DIMENSIONALITY, DimBuffer, SampledBuffer, ImageBuffer),
-                CASE1(DIMENSIONALITY, DimSubpassData, InputAttachment),
+                CASE2(DIMENSIONALITY, Dim::Dim1D, Sampled1D, Image1D),
+                CASE3(DIMENSIONALITY, Dim::Dim2D, Kernel, Shader, ImageMSArray),
+                CASE0(DIMENSIONALITY, Dim::Dim3D),
+                CASE2(DIMENSIONALITY, Dim::Cube, Shader, ImageCubeArray),
+                CASE2(DIMENSIONALITY, Dim::Rect, SampledRect, ImageRect),
+                CASE2(DIMENSIONALITY, Dim::Buffer, SampledBuffer, ImageBuffer),
+                CASE1(DIMENSIONALITY, Dim::SubpassData, InputAttachment),
             })));
 
 // See SPIR-V Section 3.9 Sampler Addressing Mode
 INSTANTIATE_TEST_SUITE_P(
     SamplerAddressingMode, EnumCapabilityTest,
-    Combine(
-        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-        ValuesIn(std::vector<EnumCapabilityCase>{
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeNone, Kernel),
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeClampToEdge,
-                  Kernel),
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeClamp, Kernel),
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeRepeat, Kernel),
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeRepeatMirrored,
-                  Kernel),
-        })));
+    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
+            ValuesIn(std::vector<EnumCapabilityCase>{
+                CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingMode::None,
+                      Kernel),
+                CASE1(SAMPLER_ADDRESSING_MODE,
+                      SamplerAddressingMode::ClampToEdge, Kernel),
+                CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingMode::Clamp,
+                      Kernel),
+                CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingMode::Repeat,
+                      Kernel),
+                CASE1(SAMPLER_ADDRESSING_MODE,
+                      SamplerAddressingMode::RepeatMirrored, Kernel),
+            })));
 
 // See SPIR-V Section 3.10 Sampler Filter Mode
 INSTANTIATE_TEST_SUITE_P(
     SamplerFilterMode, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(SAMPLER_FILTER_MODE, SamplerFilterModeNearest, Kernel),
-                CASE1(SAMPLER_FILTER_MODE, SamplerFilterModeLinear, Kernel),
+                CASE1(SAMPLER_FILTER_MODE, SamplerFilterMode::Nearest, Kernel),
+                CASE1(SAMPLER_FILTER_MODE, SamplerFilterMode::Linear, Kernel),
             })));
 
 // See SPIR-V Section 3.11 Image Format
@@ -253,76 +264,76 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
                 // clang-format off
-        CASE0(SAMPLER_IMAGE_FORMAT, ImageFormatUnknown),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba32f, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16f, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR32f, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8Snorm, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg32f, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16f, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR11fG11fB10f, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16f, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgb10A2, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba32i, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16i, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8i, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR32i, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg32i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba32ui, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16ui, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8ui, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8ui, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgb10a2ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg32ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8ui, StorageImageExtendedFormats),
+        CASE0(SAMPLER_IMAGE_FORMAT, ImageFormat::Unknown),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba32f, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16f, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R32f, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8Snorm, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg32f, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16f, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R11fG11fB10f, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16f, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgb10A2, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg8, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R8, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg8Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R8Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba32i, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16i, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8i, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R32i, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg32i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg8i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R8i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba32ui, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16ui, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8ui, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8ui, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgb10a2ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg32ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg8ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R8ui, StorageImageExtendedFormats),
                 // clang-format on
             })));
 
 // See SPIR-V Section 3.12 Image Channel Order
 INSTANTIATE_TEST_SUITE_P(
     ImageChannelOrder, EnumCapabilityTest,
-    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderR, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRG, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGB, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGBA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderBGRA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderARGB, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderIntensity, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderLuminance, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRx, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGx, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGBx, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderDepth, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderDepthStencil,
-                      Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGB, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGBx, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGBA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersBGRA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderABGR, Kernel),
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
+        ValuesIn(std::vector<EnumCapabilityCase>{
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::R, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::A, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RG, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RGB, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RGBA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::BGRA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::ARGB, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::Intensity, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::Luminance, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::Rx, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RGx, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RGBx, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::Depth, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::DepthStencil, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::sRGB, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::sRGBx, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::sRGBA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::sBGRA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::ABGR, Kernel),
+        })));
 
 // See SPIR-V Section 3.13 Image Channel Data Type
 INSTANTIATE_TEST_SUITE_P(
@@ -330,23 +341,23 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
                 // clang-format off
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSnormInt8, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSnormInt16, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt8, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt16, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormShort565, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormShort555, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt101010, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSignedInt8, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSignedInt16, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSignedInt32, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnsignedInt8, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnsignedInt16, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnsignedInt32, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeHalfFloat, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeFloat, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt24, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt101010_2, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SnormInt8, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SnormInt16, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt8, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt16, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormShort565, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormShort555, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt101010, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SignedInt8, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SignedInt16, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SignedInt32, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnsignedInt8, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnsignedInt16, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnsignedInt32, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::HalfFloat, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::Float, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt24, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt101010_2, Kernel),
                 // clang-format on
             })));
 
@@ -356,15 +367,15 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
                 // clang-format off
-                CASE0(OPTIONAL_IMAGE, ImageOperandsMaskNone),
-                CASE1(OPTIONAL_IMAGE, ImageOperandsBiasMask, Shader),
-                CASE0(OPTIONAL_IMAGE, ImageOperandsLodMask),
-                CASE0(OPTIONAL_IMAGE, ImageOperandsGradMask),
-                CASE0(OPTIONAL_IMAGE, ImageOperandsConstOffsetMask),
-                CASE1(OPTIONAL_IMAGE, ImageOperandsOffsetMask, ImageGatherExtended),
-                CASE1(OPTIONAL_IMAGE, ImageOperandsConstOffsetsMask, ImageGatherExtended),
-                CASE0(OPTIONAL_IMAGE, ImageOperandsSampleMask),
-                CASE1(OPTIONAL_IMAGE, ImageOperandsMinLodMask, MinLod),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::MaskNone),
+                CASE1(OPTIONAL_IMAGE, ImageOperandsMask::Bias, Shader),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::Lod),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::Grad),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::ConstOffset),
+                CASE1(OPTIONAL_IMAGE, ImageOperandsMask::Offset, ImageGatherExtended),
+                CASE1(OPTIONAL_IMAGE, ImageOperandsMask::ConstOffsets, ImageGatherExtended),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::Sample),
+                CASE1(OPTIONAL_IMAGE, ImageOperandsMask::MinLod, MinLod),
                 // clang-format on
             })));
 
@@ -373,8 +384,8 @@
     LinkageType, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(LINKAGE_TYPE, LinkageTypeExport, Linkage),
-                CASE1(LINKAGE_TYPE, LinkageTypeImport, Linkage),
+                CASE1(LINKAGE_TYPE, LinkageType::Export, Linkage),
+                CASE1(LINKAGE_TYPE, LinkageType::Import, Linkage),
             })));
 
 // See SPIR-V Section 3.18 Access Qualifier
@@ -382,9 +393,9 @@
     AccessQualifier, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(ACCESS_QUALIFIER, AccessQualifierReadOnly, Kernel),
-                CASE1(ACCESS_QUALIFIER, AccessQualifierWriteOnly, Kernel),
-                CASE1(ACCESS_QUALIFIER, AccessQualifierReadWrite, Kernel),
+                CASE1(ACCESS_QUALIFIER, AccessQualifier::ReadOnly, Kernel),
+                CASE1(ACCESS_QUALIFIER, AccessQualifier::WriteOnly, Kernel),
+                CASE1(ACCESS_QUALIFIER, AccessQualifier::ReadWrite, Kernel),
             })));
 
 // See SPIR-V Section 3.19 Function Parameter Attribute
@@ -393,14 +404,14 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
                 // clang-format off
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeZext, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeSext, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeByVal, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeSret, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoAlias, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoCapture, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoWrite, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoReadWrite, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::Zext, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::Sext, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::ByVal, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::Sret, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::NoAlias, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::NoCapture, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::NoWrite, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::NoReadWrite, Kernel),
                 // clang-format on
             })));
 
@@ -409,52 +420,53 @@
     Decoration, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(DECORATION, DecorationRelaxedPrecision, Shader),
+                CASE1(DECORATION, Decoration::RelaxedPrecision, Shader),
                 // DecorationSpecId handled below.
-                CASE1(DECORATION, DecorationBlock, Shader),
-                CASE1(DECORATION, DecorationBufferBlock, Shader),
-                CASE1(DECORATION, DecorationRowMajor, Matrix),
-                CASE1(DECORATION, DecorationColMajor, Matrix),
-                CASE1(DECORATION, DecorationArrayStride, Shader),
-                CASE1(DECORATION, DecorationMatrixStride, Matrix),  // Bug 15234
-                CASE1(DECORATION, DecorationGLSLShared, Shader),
-                CASE1(DECORATION, DecorationGLSLPacked, Shader),
-                CASE1(DECORATION, DecorationCPacked, Kernel),
-                CASE0(DECORATION, DecorationBuiltIn),  // Bug 15248
+                CASE1(DECORATION, Decoration::Block, Shader),
+                CASE1(DECORATION, Decoration::BufferBlock, Shader),
+                CASE1(DECORATION, Decoration::RowMajor, Matrix),
+                CASE1(DECORATION, Decoration::ColMajor, Matrix),
+                CASE1(DECORATION, Decoration::ArrayStride, Shader),
+                CASE1(DECORATION, Decoration::MatrixStride,
+                      Matrix),  // Bug 15234
+                CASE1(DECORATION, Decoration::GLSLShared, Shader),
+                CASE1(DECORATION, Decoration::GLSLPacked, Shader),
+                CASE1(DECORATION, Decoration::CPacked, Kernel),
+                CASE0(DECORATION, Decoration::BuiltIn),  // Bug 15248
                 // Value 12 placeholder
-                CASE1(DECORATION, DecorationNoPerspective, Shader),
-                CASE1(DECORATION, DecorationFlat, Shader),
-                CASE1(DECORATION, DecorationPatch, Tessellation),
-                CASE1(DECORATION, DecorationCentroid, Shader),
-                CASE1(DECORATION, DecorationSample,
+                CASE1(DECORATION, Decoration::NoPerspective, Shader),
+                CASE1(DECORATION, Decoration::Flat, Shader),
+                CASE1(DECORATION, Decoration::Patch, Tessellation),
+                CASE1(DECORATION, Decoration::Centroid, Shader),
+                CASE1(DECORATION, Decoration::Sample,
                       SampleRateShading),  // Bug 15234
-                CASE1(DECORATION, DecorationInvariant, Shader),
-                CASE0(DECORATION, DecorationRestrict),
-                CASE0(DECORATION, DecorationAliased),
-                CASE0(DECORATION, DecorationVolatile),
-                CASE1(DECORATION, DecorationConstant, Kernel),
-                CASE0(DECORATION, DecorationCoherent),
-                CASE0(DECORATION, DecorationNonWritable),
-                CASE0(DECORATION, DecorationNonReadable),
-                CASE1(DECORATION, DecorationUniform, Shader),
+                CASE1(DECORATION, Decoration::Invariant, Shader),
+                CASE0(DECORATION, Decoration::Restrict),
+                CASE0(DECORATION, Decoration::Aliased),
+                CASE0(DECORATION, Decoration::Volatile),
+                CASE1(DECORATION, Decoration::Constant, Kernel),
+                CASE0(DECORATION, Decoration::Coherent),
+                CASE0(DECORATION, Decoration::NonWritable),
+                CASE0(DECORATION, Decoration::NonReadable),
+                CASE1(DECORATION, Decoration::Uniform, Shader),
                 // Value 27 is an intentional gap in the spec numbering.
-                CASE1(DECORATION, DecorationSaturatedConversion, Kernel),
-                CASE1(DECORATION, DecorationStream, GeometryStreams),
-                CASE1(DECORATION, DecorationLocation, Shader),
-                CASE1(DECORATION, DecorationComponent, Shader),
-                CASE1(DECORATION, DecorationIndex, Shader),
-                CASE1(DECORATION, DecorationBinding, Shader),
-                CASE1(DECORATION, DecorationDescriptorSet, Shader),
-                CASE1(DECORATION, DecorationOffset, Shader),  // Bug 15268
-                CASE1(DECORATION, DecorationXfbBuffer, TransformFeedback),
-                CASE1(DECORATION, DecorationXfbStride, TransformFeedback),
-                CASE1(DECORATION, DecorationFuncParamAttr, Kernel),
-                CASE1(DECORATION, DecorationFPFastMathMode, Kernel),
-                CASE1(DECORATION, DecorationLinkageAttributes, Linkage),
-                CASE1(DECORATION, DecorationNoContraction, Shader),
-                CASE1(DECORATION, DecorationInputAttachmentIndex,
+                CASE1(DECORATION, Decoration::SaturatedConversion, Kernel),
+                CASE1(DECORATION, Decoration::Stream, GeometryStreams),
+                CASE1(DECORATION, Decoration::Location, Shader),
+                CASE1(DECORATION, Decoration::Component, Shader),
+                CASE1(DECORATION, Decoration::Index, Shader),
+                CASE1(DECORATION, Decoration::Binding, Shader),
+                CASE1(DECORATION, Decoration::DescriptorSet, Shader),
+                CASE1(DECORATION, Decoration::Offset, Shader),  // Bug 15268
+                CASE1(DECORATION, Decoration::XfbBuffer, TransformFeedback),
+                CASE1(DECORATION, Decoration::XfbStride, TransformFeedback),
+                CASE1(DECORATION, Decoration::FuncParamAttr, Kernel),
+                CASE1(DECORATION, Decoration::FPFastMathMode, Kernel),
+                CASE1(DECORATION, Decoration::LinkageAttributes, Linkage),
+                CASE1(DECORATION, Decoration::NoContraction, Shader),
+                CASE1(DECORATION, Decoration::InputAttachmentIndex,
                       InputAttachment),
-                CASE1(DECORATION, DecorationAlignment, Kernel),
+                CASE1(DECORATION, Decoration::Alignment, Kernel),
             })));
 
 #if 0
@@ -469,8 +481,8 @@
     DecorationV11, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE2(DECORATION, DecorationSpecId, Shader, Kernel),
-                CASE1(DECORATION, DecorationMaxByteOffset, Addresses)})));
+                CASE2(DECORATION, Decoration::SpecId, Shader, Kernel),
+                CASE1(DECORATION, Decoration::MaxByteOffset, Addresses)})));
 
 // See SPIR-V Section 3.21 BuiltIn
 INSTANTIATE_TEST_SUITE_P(
@@ -479,51 +491,51 @@
         Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
         ValuesIn(std::vector<EnumCapabilityCase>{
             // clang-format off
-            CASE1(BUILT_IN, BuiltInPosition, Shader),
-            CASE1(BUILT_IN, BuiltInPointSize, Shader),
+            CASE1(BUILT_IN, BuiltIn::Position, Shader),
+            CASE1(BUILT_IN, BuiltIn::PointSize, Shader),
             // 2 is an intentional gap in the spec numbering.
-            CASE1(BUILT_IN, BuiltInClipDistance, ClipDistance),  // Bug 1407, 15234
-            CASE1(BUILT_IN, BuiltInCullDistance, CullDistance),  // Bug 1407, 15234
-            CASE1(BUILT_IN, BuiltInVertexId, Shader),
-            CASE1(BUILT_IN, BuiltInInstanceId, Shader),
-            CASE5(BUILT_IN, BuiltInPrimitiveId, Geometry, Tessellation,
-                  RayTracingNV, RayTracingKHR, MeshShadingNV),
-            CASE2(BUILT_IN, BuiltInInvocationId, Geometry, Tessellation),
-            CASE3(BUILT_IN, BuiltInLayer, Geometry, ShaderViewportIndexLayerEXT, MeshShadingNV),
-            CASE3(BUILT_IN, BuiltInViewportIndex, MultiViewport, ShaderViewportIndexLayerEXT, MeshShadingNV),  // Bug 15234
-            CASE1(BUILT_IN, BuiltInTessLevelOuter, Tessellation),
-            CASE1(BUILT_IN, BuiltInTessLevelInner, Tessellation),
-            CASE1(BUILT_IN, BuiltInTessCoord, Tessellation),
-            CASE1(BUILT_IN, BuiltInPatchVertices, Tessellation),
-            CASE1(BUILT_IN, BuiltInFragCoord, Shader),
-            CASE1(BUILT_IN, BuiltInPointCoord, Shader),
-            CASE1(BUILT_IN, BuiltInFrontFacing, Shader),
-            CASE1(BUILT_IN, BuiltInSampleId, SampleRateShading),  // Bug 15234
-            CASE1(BUILT_IN, BuiltInSamplePosition, SampleRateShading), // Bug 15234
-            CASE1(BUILT_IN, BuiltInSampleMask, Shader),  // Bug 15234, Issue 182
+            CASE1(BUILT_IN, BuiltIn::ClipDistance, ClipDistance),  // Bug 1407, 15234
+            CASE1(BUILT_IN, BuiltIn::CullDistance, CullDistance),  // Bug 1407, 15234
+            CASE1(BUILT_IN, BuiltIn::VertexId, Shader),
+            CASE1(BUILT_IN, BuiltIn::InstanceId, Shader),
+            CASE6(BUILT_IN, BuiltIn::PrimitiveId, Geometry, Tessellation,
+                  RayTracingNV, RayTracingKHR, MeshShadingNV, MeshShadingEXT),
+            CASE2(BUILT_IN, BuiltIn::InvocationId, Geometry, Tessellation),
+            CASE4(BUILT_IN, BuiltIn::Layer, Geometry, ShaderViewportIndexLayerEXT, MeshShadingNV, MeshShadingEXT),
+            CASE4(BUILT_IN, BuiltIn::ViewportIndex, MultiViewport, ShaderViewportIndexLayerEXT, MeshShadingNV, MeshShadingEXT),  // Bug 15234
+            CASE1(BUILT_IN, BuiltIn::TessLevelOuter, Tessellation),
+            CASE1(BUILT_IN, BuiltIn::TessLevelInner, Tessellation),
+            CASE1(BUILT_IN, BuiltIn::TessCoord, Tessellation),
+            CASE1(BUILT_IN, BuiltIn::PatchVertices, Tessellation),
+            CASE1(BUILT_IN, BuiltIn::FragCoord, Shader),
+            CASE1(BUILT_IN, BuiltIn::PointCoord, Shader),
+            CASE1(BUILT_IN, BuiltIn::FrontFacing, Shader),
+            CASE1(BUILT_IN, BuiltIn::SampleId, SampleRateShading),  // Bug 15234
+            CASE1(BUILT_IN, BuiltIn::SamplePosition, SampleRateShading), // Bug 15234
+            CASE1(BUILT_IN, BuiltIn::SampleMask, Shader),  // Bug 15234, Issue 182
             // Value 21 intentionally missing
-            CASE1(BUILT_IN, BuiltInFragDepth, Shader),
-            CASE1(BUILT_IN, BuiltInHelperInvocation, Shader),
-            CASE0(BUILT_IN, BuiltInNumWorkgroups),
-            CASE0(BUILT_IN, BuiltInWorkgroupSize),
-            CASE0(BUILT_IN, BuiltInWorkgroupId),
-            CASE0(BUILT_IN, BuiltInLocalInvocationId),
-            CASE0(BUILT_IN, BuiltInGlobalInvocationId),
-            CASE0(BUILT_IN, BuiltInLocalInvocationIndex),
-            CASE1(BUILT_IN, BuiltInWorkDim, Kernel),
-            CASE1(BUILT_IN, BuiltInGlobalSize, Kernel),
-            CASE1(BUILT_IN, BuiltInEnqueuedWorkgroupSize, Kernel),
-            CASE1(BUILT_IN, BuiltInGlobalOffset, Kernel),
-            CASE1(BUILT_IN, BuiltInGlobalLinearId, Kernel),
+            CASE1(BUILT_IN, BuiltIn::FragDepth, Shader),
+            CASE1(BUILT_IN, BuiltIn::HelperInvocation, Shader),
+            CASE0(BUILT_IN, BuiltIn::NumWorkgroups),
+            CASE0(BUILT_IN, BuiltIn::WorkgroupSize),
+            CASE0(BUILT_IN, BuiltIn::WorkgroupId),
+            CASE0(BUILT_IN, BuiltIn::LocalInvocationId),
+            CASE0(BUILT_IN, BuiltIn::GlobalInvocationId),
+            CASE0(BUILT_IN, BuiltIn::LocalInvocationIndex),
+            CASE1(BUILT_IN, BuiltIn::WorkDim, Kernel),
+            CASE1(BUILT_IN, BuiltIn::GlobalSize, Kernel),
+            CASE1(BUILT_IN, BuiltIn::EnqueuedWorkgroupSize, Kernel),
+            CASE1(BUILT_IN, BuiltIn::GlobalOffset, Kernel),
+            CASE1(BUILT_IN, BuiltIn::GlobalLinearId, Kernel),
             // Value 35 intentionally missing
-            CASE2(BUILT_IN, BuiltInSubgroupSize, Kernel, SubgroupBallotKHR),
-            CASE1(BUILT_IN, BuiltInSubgroupMaxSize, Kernel),
-            CASE1(BUILT_IN, BuiltInNumSubgroups, Kernel),
-            CASE1(BUILT_IN, BuiltInNumEnqueuedSubgroups, Kernel),
-            CASE1(BUILT_IN, BuiltInSubgroupId, Kernel),
-            CASE2(BUILT_IN, BuiltInSubgroupLocalInvocationId, Kernel, SubgroupBallotKHR),
-            CASE1(BUILT_IN, BuiltInVertexIndex, Shader),
-            CASE1(BUILT_IN, BuiltInInstanceIndex, Shader),
+            CASE2(BUILT_IN, BuiltIn::SubgroupSize, Kernel, SubgroupBallotKHR),
+            CASE1(BUILT_IN, BuiltIn::SubgroupMaxSize, Kernel),
+            CASE1(BUILT_IN, BuiltIn::NumSubgroups, Kernel),
+            CASE1(BUILT_IN, BuiltIn::NumEnqueuedSubgroups, Kernel),
+            CASE1(BUILT_IN, BuiltIn::SubgroupId, Kernel),
+            CASE2(BUILT_IN, BuiltIn::SubgroupLocalInvocationId, Kernel, SubgroupBallotKHR),
+            CASE1(BUILT_IN, BuiltIn::VertexIndex, Shader),
+            CASE1(BUILT_IN, BuiltIn::InstanceIndex, Shader),
             // clang-format on
         })));
 
@@ -533,11 +545,11 @@
         Values(SPV_ENV_UNIVERSAL_1_5),
         ValuesIn(std::vector<EnumCapabilityCase>{
             // SPIR-V 1.5 adds new capabilities to enable these two builtins.
-            CASE4(BUILT_IN, BuiltInLayer, Geometry, ShaderLayer,
-                  ShaderViewportIndexLayerEXT, MeshShadingNV),
-            CASE4(BUILT_IN, BuiltInViewportIndex, MultiViewport,
+            CASE5(BUILT_IN, BuiltIn::Layer, Geometry, ShaderLayer,
+                  ShaderViewportIndexLayerEXT, MeshShadingNV, MeshShadingEXT),
+            CASE5(BUILT_IN, BuiltIn::ViewportIndex, MultiViewport,
                   ShaderViewportIndex, ShaderViewportIndexLayerEXT,
-                  MeshShadingNV),
+                  MeshShadingNV, MeshShadingEXT),
         })));
 
 // See SPIR-V Section 3.22 Selection Control
@@ -545,9 +557,9 @@
     SelectionControl, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(SELECTION_CONTROL, SelectionControlMaskNone),
-                CASE0(SELECTION_CONTROL, SelectionControlFlattenMask),
-                CASE0(SELECTION_CONTROL, SelectionControlDontFlattenMask),
+                CASE0(SELECTION_CONTROL, SelectionControlMask::MaskNone),
+                CASE0(SELECTION_CONTROL, SelectionControlMask::Flatten),
+                CASE0(SELECTION_CONTROL, SelectionControlMask::DontFlatten),
             })));
 
 // See SPIR-V Section 3.23 Loop Control
@@ -555,17 +567,17 @@
     LoopControl, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(LOOP_CONTROL, LoopControlMaskNone),
-                CASE0(LOOP_CONTROL, LoopControlUnrollMask),
-                CASE0(LOOP_CONTROL, LoopControlDontUnrollMask),
+                CASE0(LOOP_CONTROL, LoopControlMask::MaskNone),
+                CASE0(LOOP_CONTROL, LoopControlMask::Unroll),
+                CASE0(LOOP_CONTROL, LoopControlMask::DontUnroll),
             })));
 
 INSTANTIATE_TEST_SUITE_P(
     LoopControlV11, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(LOOP_CONTROL, LoopControlDependencyInfiniteMask),
-                CASE0(LOOP_CONTROL, LoopControlDependencyLengthMask),
+                CASE0(LOOP_CONTROL, LoopControlMask::DependencyInfinite),
+                CASE0(LOOP_CONTROL, LoopControlMask::DependencyLength),
             })));
 
 // See SPIR-V Section 3.24 Function Control
@@ -573,11 +585,11 @@
     FunctionControl, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(FUNCTION_CONTROL, FunctionControlMaskNone),
-                CASE0(FUNCTION_CONTROL, FunctionControlInlineMask),
-                CASE0(FUNCTION_CONTROL, FunctionControlDontInlineMask),
-                CASE0(FUNCTION_CONTROL, FunctionControlPureMask),
-                CASE0(FUNCTION_CONTROL, FunctionControlConstMask),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::MaskNone),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::Inline),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::DontInline),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::Pure),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::Const),
             })));
 
 // See SPIR-V Section 3.25 Memory Semantics <id>
@@ -586,20 +598,21 @@
     Combine(
         Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
         ValuesIn(std::vector<EnumCapabilityCase>{
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMaskNone),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsAcquireMask),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsReleaseMask),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsAcquireReleaseMask),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::MaskNone),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::Acquire),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::Release),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::AcquireRelease),
             CASE0(MEMORY_SEMANTICS_ID,
-                  MemorySemanticsSequentiallyConsistentMask),
-            CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsUniformMemoryMask,
+                  MemorySemanticsMask::SequentiallyConsistent),
+            CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsMask::UniformMemory,
                   Shader),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsSubgroupMemoryMask),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsWorkgroupMemoryMask),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsCrossWorkgroupMemoryMask),
-            CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsAtomicCounterMemoryMask,
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::SubgroupMemory),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::WorkgroupMemory),
+            CASE0(MEMORY_SEMANTICS_ID,
+                  MemorySemanticsMask::CrossWorkgroupMemory),
+            CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsMask::AtomicCounterMemory,
                   AtomicStorage),  // Bug 15234
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsImageMemoryMask),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::ImageMemory),
         })));
 
 // See SPIR-V Section 3.26 Memory Access
@@ -607,10 +620,10 @@
     MemoryAccess, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMaskNone),
-                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessVolatileMask),
-                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessAlignedMask),
-                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessNontemporalMask),
+                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMask::MaskNone),
+                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMask::Volatile),
+                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMask::Aligned),
+                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMask::Nontemporal),
             })));
 
 // See SPIR-V Section 3.27 Scope <id>
@@ -619,12 +632,12 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
                    SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(SCOPE_ID, ScopeCrossDevice),
-                CASE0(SCOPE_ID, ScopeDevice),
-                CASE0(SCOPE_ID, ScopeWorkgroup),
-                CASE0(SCOPE_ID, ScopeSubgroup),
-                CASE0(SCOPE_ID, ScopeInvocation),
-                CASE1(SCOPE_ID, ScopeQueueFamilyKHR, VulkanMemoryModelKHR),
+                CASE0(SCOPE_ID, Scope::CrossDevice),
+                CASE0(SCOPE_ID, Scope::Device),
+                CASE0(SCOPE_ID, Scope::Workgroup),
+                CASE0(SCOPE_ID, Scope::Subgroup),
+                CASE0(SCOPE_ID, Scope::Invocation),
+                CASE1(SCOPE_ID, Scope::QueueFamilyKHR, VulkanMemoryModelKHR),
             })));
 
 // See SPIR-V Section 3.28 Group Operation
@@ -632,11 +645,11 @@
     GroupOperation, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE3(GROUP_OPERATION, GroupOperationReduce, Kernel,
+                CASE3(GROUP_OPERATION, GroupOperation::Reduce, Kernel,
                       GroupNonUniformArithmetic, GroupNonUniformBallot),
-                CASE3(GROUP_OPERATION, GroupOperationInclusiveScan, Kernel,
+                CASE3(GROUP_OPERATION, GroupOperation::InclusiveScan, Kernel,
                       GroupNonUniformArithmetic, GroupNonUniformBallot),
-                CASE3(GROUP_OPERATION, GroupOperationExclusiveScan, Kernel,
+                CASE3(GROUP_OPERATION, GroupOperation::ExclusiveScan, Kernel,
                       GroupNonUniformArithmetic, GroupNonUniformBallot),
             })));
 
@@ -645,9 +658,9 @@
     KernelEnqueueFlags, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlagsNoWait, Kernel),
-                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlagsWaitKernel, Kernel),
-                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlagsWaitWorkGroup,
+                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlags::NoWait, Kernel),
+                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlags::WaitKernel, Kernel),
+                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlags::WaitWorkGroup,
                       Kernel),
             })));
 
@@ -656,9 +669,9 @@
     KernelProfilingInfo, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(KERNEL_PROFILING_INFO, KernelProfilingInfoMaskNone),
-                CASE1(KERNEL_PROFILING_INFO, KernelProfilingInfoCmdExecTimeMask,
-                      Kernel),
+                CASE0(KERNEL_PROFILING_INFO, KernelProfilingInfoMask::MaskNone),
+                CASE1(KERNEL_PROFILING_INFO,
+                      KernelProfilingInfoMask::CmdExecTime, Kernel),
             })));
 
 // See SPIR-V Section 3.31 Capability
@@ -668,62 +681,62 @@
         Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
         ValuesIn(std::vector<EnumCapabilityCase>{
             // clang-format off
-            CASE0(CAPABILITY, CapabilityMatrix),
-            CASE1(CAPABILITY, CapabilityShader, Matrix),
-            CASE1(CAPABILITY, CapabilityGeometry, Shader),
-            CASE1(CAPABILITY, CapabilityTessellation, Shader),
-            CASE0(CAPABILITY, CapabilityAddresses),
-            CASE0(CAPABILITY, CapabilityLinkage),
-            CASE0(CAPABILITY, CapabilityKernel),
-            CASE1(CAPABILITY, CapabilityVector16, Kernel),
-            CASE1(CAPABILITY, CapabilityFloat16Buffer, Kernel),
-            CASE0(CAPABILITY, CapabilityFloat16),  // Bug 15234
-            CASE0(CAPABILITY, CapabilityFloat64),
-            CASE0(CAPABILITY, CapabilityInt64),
-            CASE1(CAPABILITY, CapabilityInt64Atomics, Int64),
-            CASE1(CAPABILITY, CapabilityImageBasic, Kernel),
-            CASE1(CAPABILITY, CapabilityImageReadWrite, ImageBasic),
-            CASE1(CAPABILITY, CapabilityImageMipmap, ImageBasic),
+            CASE0(CAPABILITY, Capability::Matrix),
+            CASE1(CAPABILITY, Capability::Shader, Matrix),
+            CASE1(CAPABILITY, Capability::Geometry, Shader),
+            CASE1(CAPABILITY, Capability::Tessellation, Shader),
+            CASE0(CAPABILITY, Capability::Addresses),
+            CASE0(CAPABILITY, Capability::Linkage),
+            CASE0(CAPABILITY, Capability::Kernel),
+            CASE1(CAPABILITY, Capability::Vector16, Kernel),
+            CASE1(CAPABILITY, Capability::Float16Buffer, Kernel),
+            CASE0(CAPABILITY, Capability::Float16),  // Bug 15234
+            CASE0(CAPABILITY, Capability::Float64),
+            CASE0(CAPABILITY, Capability::Int64),
+            CASE1(CAPABILITY, Capability::Int64Atomics, Int64),
+            CASE1(CAPABILITY, Capability::ImageBasic, Kernel),
+            CASE1(CAPABILITY, Capability::ImageReadWrite, ImageBasic),
+            CASE1(CAPABILITY, Capability::ImageMipmap, ImageBasic),
             // Value 16 intentionally missing.
-            CASE1(CAPABILITY, CapabilityPipes, Kernel),
-            CASE0(CAPABILITY, CapabilityGroups),
-            CASE1(CAPABILITY, CapabilityDeviceEnqueue, Kernel),
-            CASE1(CAPABILITY, CapabilityLiteralSampler, Kernel),
-            CASE1(CAPABILITY, CapabilityAtomicStorage, Shader),
-            CASE0(CAPABILITY, CapabilityInt16),
-            CASE1(CAPABILITY, CapabilityTessellationPointSize, Tessellation),
-            CASE1(CAPABILITY, CapabilityGeometryPointSize, Geometry),
-            CASE1(CAPABILITY, CapabilityImageGatherExtended, Shader),
+            CASE1(CAPABILITY, Capability::Pipes, Kernel),
+            CASE0(CAPABILITY, Capability::Groups),
+            CASE1(CAPABILITY, Capability::DeviceEnqueue, Kernel),
+            CASE1(CAPABILITY, Capability::LiteralSampler, Kernel),
+            CASE1(CAPABILITY, Capability::AtomicStorage, Shader),
+            CASE0(CAPABILITY, Capability::Int16),
+            CASE1(CAPABILITY, Capability::TessellationPointSize, Tessellation),
+            CASE1(CAPABILITY, Capability::GeometryPointSize, Geometry),
+            CASE1(CAPABILITY, Capability::ImageGatherExtended, Shader),
             // Value 26 intentionally missing.
-            CASE1(CAPABILITY, CapabilityStorageImageMultisample, Shader),
-            CASE1(CAPABILITY, CapabilityUniformBufferArrayDynamicIndexing, Shader),
-            CASE1(CAPABILITY, CapabilitySampledImageArrayDynamicIndexing, Shader),
-            CASE1(CAPABILITY, CapabilityStorageBufferArrayDynamicIndexing, Shader),
-            CASE1(CAPABILITY, CapabilityStorageImageArrayDynamicIndexing, Shader),
-            CASE1(CAPABILITY, CapabilityClipDistance, Shader),
-            CASE1(CAPABILITY, CapabilityCullDistance, Shader),
-            CASE1(CAPABILITY, CapabilityImageCubeArray, SampledCubeArray),
-            CASE1(CAPABILITY, CapabilitySampleRateShading, Shader),
-            CASE1(CAPABILITY, CapabilityImageRect, SampledRect),
-            CASE1(CAPABILITY, CapabilitySampledRect, Shader),
-            CASE1(CAPABILITY, CapabilityGenericPointer, Addresses),
-            CASE0(CAPABILITY, CapabilityInt8),
-            CASE1(CAPABILITY, CapabilityInputAttachment, Shader),
-            CASE1(CAPABILITY, CapabilitySparseResidency, Shader),
-            CASE1(CAPABILITY, CapabilityMinLod, Shader),
-            CASE1(CAPABILITY, CapabilityImage1D, Sampled1D),
-            CASE1(CAPABILITY, CapabilitySampledCubeArray, Shader),
-            CASE1(CAPABILITY, CapabilityImageBuffer, SampledBuffer),
-            CASE1(CAPABILITY, CapabilityImageMSArray, Shader),
-            CASE1(CAPABILITY, CapabilityStorageImageExtendedFormats, Shader),
-            CASE1(CAPABILITY, CapabilityImageQuery, Shader),
-            CASE1(CAPABILITY, CapabilityDerivativeControl, Shader),
-            CASE1(CAPABILITY, CapabilityInterpolationFunction, Shader),
-            CASE1(CAPABILITY, CapabilityTransformFeedback, Shader),
-            CASE1(CAPABILITY, CapabilityGeometryStreams, Geometry),
-            CASE1(CAPABILITY, CapabilityStorageImageReadWithoutFormat, Shader),
-            CASE1(CAPABILITY, CapabilityStorageImageWriteWithoutFormat, Shader),
-            CASE1(CAPABILITY, CapabilityMultiViewport, Geometry),
+            CASE1(CAPABILITY, Capability::StorageImageMultisample, Shader),
+            CASE1(CAPABILITY, Capability::UniformBufferArrayDynamicIndexing, Shader),
+            CASE1(CAPABILITY, Capability::SampledImageArrayDynamicIndexing, Shader),
+            CASE1(CAPABILITY, Capability::StorageBufferArrayDynamicIndexing, Shader),
+            CASE1(CAPABILITY, Capability::StorageImageArrayDynamicIndexing, Shader),
+            CASE1(CAPABILITY, Capability::ClipDistance, Shader),
+            CASE1(CAPABILITY, Capability::CullDistance, Shader),
+            CASE1(CAPABILITY, Capability::ImageCubeArray, SampledCubeArray),
+            CASE1(CAPABILITY, Capability::SampleRateShading, Shader),
+            CASE1(CAPABILITY, Capability::ImageRect, SampledRect),
+            CASE1(CAPABILITY, Capability::SampledRect, Shader),
+            CASE1(CAPABILITY, Capability::GenericPointer, Addresses),
+            CASE0(CAPABILITY, Capability::Int8),
+            CASE1(CAPABILITY, Capability::InputAttachment, Shader),
+            CASE1(CAPABILITY, Capability::SparseResidency, Shader),
+            CASE1(CAPABILITY, Capability::MinLod, Shader),
+            CASE1(CAPABILITY, Capability::Image1D, Sampled1D),
+            CASE1(CAPABILITY, Capability::SampledCubeArray, Shader),
+            CASE1(CAPABILITY, Capability::ImageBuffer, SampledBuffer),
+            CASE1(CAPABILITY, Capability::ImageMSArray, Shader),
+            CASE1(CAPABILITY, Capability::StorageImageExtendedFormats, Shader),
+            CASE1(CAPABILITY, Capability::ImageQuery, Shader),
+            CASE1(CAPABILITY, Capability::DerivativeControl, Shader),
+            CASE1(CAPABILITY, Capability::InterpolationFunction, Shader),
+            CASE1(CAPABILITY, Capability::TransformFeedback, Shader),
+            CASE1(CAPABILITY, Capability::GeometryStreams, Geometry),
+            CASE1(CAPABILITY, Capability::StorageImageReadWithoutFormat, Shader),
+            CASE1(CAPABILITY, Capability::StorageImageWriteWithoutFormat, Shader),
+            CASE1(CAPABILITY, Capability::MultiViewport, Geometry),
             // clang-format on
         })));
 
@@ -731,9 +744,9 @@
     CapabilityDependsOnV11, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(CAPABILITY, CapabilitySubgroupDispatch, DeviceEnqueue),
-                CASE1(CAPABILITY, CapabilityNamedBarrier, Kernel),
-                CASE1(CAPABILITY, CapabilityPipeStorage, Pipes),
+                CASE1(CAPABILITY, Capability::SubgroupDispatch, DeviceEnqueue),
+                CASE1(CAPABILITY, Capability::NamedBarrier, Kernel),
+                CASE1(CAPABILITY, Capability::PipeStorage, Pipes),
             })));
 
 #undef CASE0
diff --git a/third_party/SPIRV-Tools/test/operand_pattern_test.cpp b/third_party/SPIRV-Tools/test/operand_pattern_test.cpp
index a98a9d7..58b8a08 100644
--- a/third_party/SPIRV-Tools/test/operand_pattern_test.cpp
+++ b/third_party/SPIRV-Tools/test/operand_pattern_test.cpp
@@ -103,17 +103,18 @@
          {PREFIX1}},
         // Volatile has no operands.
         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
-         SpvMemoryAccessVolatileMask,
+         uint32_t(spv::MemoryAccessMask::Volatile),
          {PREFIX0},
          {PREFIX0}},
         // Aligned has one literal number operand.
         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
-         SpvMemoryAccessAlignedMask,
+         uint32_t(spv::MemoryAccessMask::Aligned),
          {PREFIX1},
          {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
         // Volatile with Aligned still has just one literal number operand.
         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
-         SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask,
+         uint32_t(spv::MemoryAccessMask::Volatile |
+                  spv::MemoryAccessMask::Aligned),
          {PREFIX1},
          {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
         // Newer masks are not tested
diff --git a/third_party/SPIRV-Tools/test/opt/CMakeLists.txt b/third_party/SPIRV-Tools/test/opt/CMakeLists.txt
index 15966c1..36bf04c 100644
--- a/third_party/SPIRV-Tools/test/opt/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/test/opt/CMakeLists.txt
@@ -18,6 +18,7 @@
 add_spvtools_unittest(TARGET opt
   SRCS aggressive_dead_code_elim_test.cpp
        amd_ext_to_khr.cpp
+       analyze_live_input_test.cpp
        assembly_builder_test.cpp
        block_merge_test.cpp
        ccp_test.cpp
@@ -44,6 +45,7 @@
        eliminate_dead_functions_test.cpp
        eliminate_dead_input_components_test.cpp
        eliminate_dead_member_test.cpp
+       eliminate_dead_output_stores_test.cpp
        feature_manager_test.cpp
        fix_func_call_arguments_test.cpp
        fix_storage_class_test.cpp
diff --git a/third_party/SPIRV-Tools/test/opt/aggressive_dead_code_elim_test.cpp b/third_party/SPIRV-Tools/test/opt/aggressive_dead_code_elim_test.cpp
index 89cb56f..e51098e 100644
--- a/third_party/SPIRV-Tools/test/opt/aggressive_dead_code_elim_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/aggressive_dead_code_elim_test.cpp
@@ -7677,6 +7677,106 @@
   SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
 }
 
+TEST_F(AggressiveDCETest, KeepTopLevelDebugInfo) {
+  // Don't eliminate DebugCompilationUnit, DebugSourceContinued, and
+  // DebugEntryPoint
+  const std::string text = R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_non_semantic_info"
+          %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %MainPs "MainPs" %out_var_SV_Target0
+               OpExecutionMode %MainPs OriginUpperLeft
+          %4 = OpString "foo2.frag"
+          %5 = OpString "
+struct PS_OUTPUT
+{
+    float4 vColor : SV_Target0 ;
+} ;
+
+"
+          %6 = OpString "
+PS_OUTPUT MainPs ( )
+{
+    PS_OUTPUT ps_output ;
+    ps_output . vColor = float4( 1.0, 0.0, 0.0, 0.0 );
+    return ps_output ;
+}
+
+"
+          %7 = OpString "float"
+          %8 = OpString "vColor"
+          %9 = OpString "PS_OUTPUT"
+         %10 = OpString "MainPs"
+         %11 = OpString ""
+         %12 = OpString "ps_output"
+         %13 = OpString "97a939fb"
+         %14 = OpString " foo2.frag -E MainPs -T ps_6_1 -spirv -fspv-target-env=vulkan1.2 -fspv-debug=vulkan-with-source -fcgl -Fo foo2.frag.nopt.spv -Qembed_debug"
+               OpName %out_var_SV_Target0 "out.var.SV_Target0"
+               OpName %MainPs "MainPs"
+               OpDecorate %out_var_SV_Target0 Location 0
+      %float = OpTypeFloat 32
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+    %v4float = OpTypeVector %float 4
+         %23 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_0
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+       %uint = OpTypeInt 32 0
+    %uint_32 = OpConstant %uint 32
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+       %void = OpTypeVoid
+     %uint_1 = OpConstant %uint 1
+     %uint_4 = OpConstant %uint 4
+     %uint_5 = OpConstant %uint 5
+     %uint_3 = OpConstant %uint 3
+     %uint_0 = OpConstant %uint 0
+   %uint_128 = OpConstant %uint 128
+    %uint_12 = OpConstant %uint 12
+     %uint_2 = OpConstant %uint 2
+     %uint_8 = OpConstant %uint 8
+     %uint_7 = OpConstant %uint 7
+     %uint_9 = OpConstant %uint 9
+    %uint_15 = OpConstant %uint 15
+         %42 = OpTypeFunction %void
+    %uint_10 = OpConstant %uint 10
+    %uint_53 = OpConstant %uint 53
+%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
+         %49 = OpExtInst %void %1 DebugExpression
+         %50 = OpExtInst %void %1 DebugSource %4 %5
+         %51 = OpExtInst %void %1 DebugSourceContinued %6
+; CHECK:     %51 = OpExtInst %void %1 DebugSourceContinued %6
+         %52 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %50 %uint_5
+; CHECK:     %52 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %50 %uint_5
+         %53 = OpExtInst %void %1 DebugTypeBasic %7 %uint_32 %uint_3 %uint_0
+         %54 = OpExtInst %void %1 DebugTypeVector %53 %uint_4
+         %55 = OpExtInst %void %1 DebugTypeMember %8 %54 %50 %uint_4 %uint_12 %uint_0 %uint_128 %uint_3
+         %56 = OpExtInst %void %1 DebugTypeComposite %9 %uint_1 %50 %uint_2 %uint_8 %52 %9 %uint_128 %uint_3 %55
+         %57 = OpExtInst %void %1 DebugTypeFunction %uint_3 %56
+         %58 = OpExtInst %void %1 DebugFunction %10 %57 %50 %uint_7 %uint_1 %52 %11 %uint_3 %uint_8
+         %59 = OpExtInst %void %1 DebugLexicalBlock %50 %uint_8 %uint_1 %58
+         %60 = OpExtInst %void %1 DebugLocalVariable %12 %56 %50 %uint_9 %uint_15 %59 %uint_4
+         %61 = OpExtInst %void %1 DebugEntryPoint %58 %52 %13 %14
+; CHECK:     %61 = OpExtInst %void %1 DebugEntryPoint %58 %52 %13 %14
+     %MainPs = OpFunction %void None %42
+         %62 = OpLabel
+         %63 = OpExtInst %void %1 DebugFunctionDefinition %58 %MainPs
+        %112 = OpExtInst %void %1 DebugScope %59
+        %111 = OpExtInst %void %1 DebugLine %50 %uint_10 %uint_10 %uint_5 %uint_53
+        %110 = OpExtInst %void %1 DebugValue %60 %23 %49 %int_0
+        %113 = OpExtInst %void %1 DebugNoLine
+        %114 = OpExtInst %void %1 DebugNoScope
+               OpStore %out_var_SV_Target0 %23
+         %66 = OpExtInst %void %1 DebugLine %50 %uint_12 %uint_12 %uint_1 %uint_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/analyze_live_input_test.cpp b/third_party/SPIRV-Tools/test/opt/analyze_live_input_test.cpp
new file mode 100644
index 0000000..c2a8f4c
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/opt/analyze_live_input_test.cpp
@@ -0,0 +1,910 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+// Copyright (c) 2022 LunarG Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <unordered_set>
+
+#include "gmock/gmock.h"
+#include "test/opt/pass_fixture.h"
+#include "test/opt/pass_utils.h"
+
+namespace spvtools {
+namespace opt {
+namespace {
+
+using AnalyzeLiveInputTest = PassTest<::testing::Test>;
+
+TEST_F(AnalyzeLiveInputTest, FragMultipleLocations) {
+  // Should report locations {2, 5}
+  //
+  // #version 450
+  //
+  // layout(location = 2) in Vertex
+  // {
+  //         vec4 color0;
+  //         vec4 color1;
+  //         vec4 color2[3];
+  // } iVert;
+  //
+  // layout(location = 0) out vec4 oFragColor;
+  //
+  // void main()
+  // {
+  //     oFragColor = iVert.color0 + iVert.color2[1];
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %oFragColor %iVert
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %oFragColor "oFragColor"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "color0"
+               OpMemberName %Vertex 1 "color1"
+               OpMemberName %Vertex 2 "color2"
+               OpName %iVert "iVert"
+               OpDecorate %oFragColor Location 0
+               OpDecorate %Vertex Block
+               OpDecorate %iVert Location 2
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %oFragColor = OpVariable %_ptr_Output_v4float Output
+       %uint = OpTypeInt 32 0
+     %uint_3 = OpConstant %uint 3
+%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
+     %Vertex = OpTypeStruct %v4float %v4float %_arr_v4float_uint_3
+%_ptr_Input_Vertex = OpTypePointer Input %Vertex
+      %iVert = OpVariable %_ptr_Input_Vertex Input
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+      %int_2 = OpConstant %int 2
+      %int_1 = OpConstant %int 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
+         %20 = OpLoad %v4float %19
+         %23 = OpAccessChain %_ptr_Input_v4float %iVert %int_2 %int_1
+         %24 = OpLoad %v4float %23
+         %25 = OpFAdd %v4float %20 %24
+               OpStore %oFragColor %25
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
+      text, true, &live_inputs, &live_builtins);
+
+  auto itr0 = live_inputs.find(0);
+  auto itr1 = live_inputs.find(1);
+  auto itr2 = live_inputs.find(2);
+  auto itr3 = live_inputs.find(3);
+  auto itr4 = live_inputs.find(4);
+  auto itr5 = live_inputs.find(5);
+  auto itr6 = live_inputs.find(6);
+
+  // Expect live_inputs == {2, 5}
+  EXPECT_TRUE(itr0 == live_inputs.end());
+  EXPECT_TRUE(itr1 == live_inputs.end());
+  EXPECT_TRUE(itr2 != live_inputs.end());
+  EXPECT_TRUE(itr3 == live_inputs.end());
+  EXPECT_TRUE(itr4 == live_inputs.end());
+  EXPECT_TRUE(itr5 != live_inputs.end());
+  EXPECT_TRUE(itr6 == live_inputs.end());
+}
+
+TEST_F(AnalyzeLiveInputTest, FragMatrix) {
+  // Should report locations {2, 8, 9, 10, 11}
+  //
+  // #version 450
+  //
+  // uniform ui_name {
+  //     int i;
+  // } ui_inst;
+  //
+  // layout(location = 2) in Vertex
+  // {
+  //         vec4 color0;
+  //         vec4 color1;
+  //         mat4 color2;
+  //         mat4 color3;
+  //         mat4 color4;
+  // } iVert;
+  //
+  // // Output variable for the color
+  // layout(location = 0) out vec4 oFragColor;
+  //
+  // void main()
+  // {
+  //     oFragColor = iVert.color0 + iVert.color3[ui_inst.i];
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %oFragColor %iVert %ui_inst
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %oFragColor "oFragColor"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "color0"
+               OpMemberName %Vertex 1 "color1"
+               OpMemberName %Vertex 2 "color2"
+               OpMemberName %Vertex 3 "color3"
+               OpMemberName %Vertex 4 "color4"
+               OpName %iVert "iVert"
+               OpName %ui_name "ui_name"
+               OpMemberName %ui_name 0 "i"
+               OpName %ui_inst "ui_inst"
+               OpDecorate %oFragColor Location 0
+               OpDecorate %Vertex Block
+               OpDecorate %iVert Location 2
+               OpMemberDecorate %ui_name 0 Offset 0
+               OpDecorate %ui_name Block
+               OpDecorate %ui_inst DescriptorSet 0
+               OpDecorate %ui_inst Binding 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %oFragColor = OpVariable %_ptr_Output_v4float Output
+%mat4v4float = OpTypeMatrix %v4float 4
+     %Vertex = OpTypeStruct %v4float %v4float %mat4v4float %mat4v4float %mat4v4float
+%_ptr_Input_Vertex = OpTypePointer Input %Vertex
+      %iVert = OpVariable %_ptr_Input_Vertex Input
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+      %int_3 = OpConstant %int 3
+    %ui_name = OpTypeStruct %int
+%_ptr_Uniform_ui_name = OpTypePointer Uniform %ui_name
+    %ui_inst = OpVariable %_ptr_Uniform_ui_name Uniform
+%_ptr_Uniform_int = OpTypePointer Uniform %int
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
+         %18 = OpLoad %v4float %17
+         %24 = OpAccessChain %_ptr_Uniform_int %ui_inst %int_0
+         %25 = OpLoad %int %24
+         %26 = OpAccessChain %_ptr_Input_v4float %iVert %int_3 %25
+         %27 = OpLoad %v4float %26
+         %28 = OpFAdd %v4float %18 %27
+               OpStore %oFragColor %28
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
+      text, true, &live_inputs, &live_builtins);
+
+  auto itr0 = live_inputs.find(0);
+  auto itr1 = live_inputs.find(1);
+  auto itr2 = live_inputs.find(2);
+  auto itr3 = live_inputs.find(3);
+  auto itr4 = live_inputs.find(4);
+  auto itr5 = live_inputs.find(5);
+  auto itr6 = live_inputs.find(6);
+  auto itr7 = live_inputs.find(7);
+  auto itr8 = live_inputs.find(8);
+  auto itr9 = live_inputs.find(9);
+  auto itr10 = live_inputs.find(10);
+  auto itr11 = live_inputs.find(11);
+  auto itr12 = live_inputs.find(12);
+  auto itr13 = live_inputs.find(13);
+  auto itr14 = live_inputs.find(14);
+  auto itr15 = live_inputs.find(15);
+
+  // Expect live_inputs == {2, 8, 9, 10, 11}
+  EXPECT_TRUE(itr0 == live_inputs.end());
+  EXPECT_TRUE(itr1 == live_inputs.end());
+  EXPECT_TRUE(itr2 != live_inputs.end());
+  EXPECT_TRUE(itr3 == live_inputs.end());
+  EXPECT_TRUE(itr4 == live_inputs.end());
+  EXPECT_TRUE(itr5 == live_inputs.end());
+  EXPECT_TRUE(itr6 == live_inputs.end());
+  EXPECT_TRUE(itr7 == live_inputs.end());
+  EXPECT_TRUE(itr8 != live_inputs.end());
+  EXPECT_TRUE(itr9 != live_inputs.end());
+  EXPECT_TRUE(itr10 != live_inputs.end());
+  EXPECT_TRUE(itr11 != live_inputs.end());
+  EXPECT_TRUE(itr12 == live_inputs.end());
+  EXPECT_TRUE(itr13 == live_inputs.end());
+  EXPECT_TRUE(itr14 == live_inputs.end());
+  EXPECT_TRUE(itr15 == live_inputs.end());
+}
+
+TEST_F(AnalyzeLiveInputTest, FragMemberLocs) {
+  // Should report location {1}
+  //
+  // #version 450
+  //
+  // in Vertex
+  // {
+  //     layout (location = 1) vec4 Cd;
+  //     layout (location = 0) vec2 uv;
+  // } iVert;
+  //
+  // layout (location = 0) out vec4 fragColor;
+  //
+  // void main()
+  // {
+  //     vec4 color = vec4(iVert.Cd);
+  //     fragColor = color;
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %iVert %fragColor
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %color "color"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "Cd"
+               OpMemberName %Vertex 1 "uv"
+               OpName %iVert "iVert"
+               OpName %fragColor "fragColor"
+               OpMemberDecorate %Vertex 0 Location 1
+               OpMemberDecorate %Vertex 1 Location 0
+               OpDecorate %Vertex Block
+               OpDecorate %fragColor Location 0
+               OpDecorate %_struct_27 Block
+               OpMemberDecorate %_struct_27 0 Location 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %v2float = OpTypeVector %float 2
+     %Vertex = OpTypeStruct %v4float %v2float
+%_ptr_Input_Vertex = OpTypePointer Input %Vertex
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+  %fragColor = OpVariable %_ptr_Output_v4float Output
+ %_struct_27 = OpTypeStruct %v4float
+%_ptr_Input__struct_27 = OpTypePointer Input %_struct_27
+      %iVert = OpVariable %_ptr_Input__struct_27 Input
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+      %color = OpVariable %_ptr_Function_v4float Function
+         %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
+         %18 = OpLoad %v4float %17
+         %19 = OpCompositeExtract %float %18 0
+         %20 = OpCompositeExtract %float %18 1
+         %21 = OpCompositeExtract %float %18 2
+         %22 = OpCompositeExtract %float %18 3
+         %23 = OpCompositeConstruct %v4float %19 %20 %21 %22
+               OpStore %color %23
+         %26 = OpLoad %v4float %color
+               OpStore %fragColor %26
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
+      text, true, &live_inputs, &live_builtins);
+
+  auto itr0 = live_inputs.find(0);
+  auto itr1 = live_inputs.find(1);
+
+  // Expect live_inputs == {2, 5}
+  EXPECT_TRUE(itr0 == live_inputs.end());
+  EXPECT_TRUE(itr1 != live_inputs.end());
+}
+
+TEST_F(AnalyzeLiveInputTest, ArrayedInput) {
+  // Tests handling of arrayed input seen in Tesc, Tese and Geom shaders.
+  //
+  // Should report location {1, 10}.
+  //
+  // #version 450
+  //
+  // layout (vertices = 4) out;
+  //
+  // layout (location = 1) in Vertex
+  // {
+  //                 vec4 p;
+  //                 vec3 n;
+  //                 vec4 f[100];
+  // } iVert[];
+  //
+  // layout (location = 0) out vec4 position[4];
+  //
+  // void main()
+  // {
+  //                 vec4 pos = iVert[gl_InvocationID].p *
+  //                            iVert[gl_InvocationID].f[7];
+  //                 position[gl_InvocationID] = pos;
+  // }
+  const std::string text = R"(
+               OpCapability Tessellation
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TessellationControl %main "main" %iVert %gl_InvocationID %position
+               OpExecutionMode %main OutputVertices 4
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "p"
+               OpMemberName %Vertex 1 "n"
+               OpMemberName %Vertex 2 "f"
+               OpName %iVert "iVert"
+               OpName %gl_InvocationID "gl_InvocationID"
+               OpName %position "position"
+               OpDecorate %Vertex Block
+               OpDecorate %iVert Location 1
+               OpDecorate %gl_InvocationID BuiltIn InvocationId
+               OpDecorate %position Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+    %v3float = OpTypeVector %float 3
+       %uint = OpTypeInt 32 0
+   %uint_100 = OpConstant %uint 100
+%_arr_v4float_uint_100 = OpTypeArray %v4float %uint_100
+     %Vertex = OpTypeStruct %v4float %v3float %_arr_v4float_uint_100
+    %uint_32 = OpConstant %uint 32
+%_arr_Vertex_uint_32 = OpTypeArray %Vertex %uint_32
+%_ptr_Input__arr_Vertex_uint_32 = OpTypePointer Input %_arr_Vertex_uint_32
+      %iVert = OpVariable %_ptr_Input__arr_Vertex_uint_32 Input
+        %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_InvocationID = OpVariable %_ptr_Input_int Input
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+      %int_2 = OpConstant %int 2
+      %int_7 = OpConstant %int 7
+     %uint_4 = OpConstant %uint 4
+%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
+%_ptr_Output__arr_v4float_uint_4 = OpTypePointer Output %_arr_v4float_uint_4
+   %position = OpVariable %_ptr_Output__arr_v4float_uint_4 Output
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %22 = OpLoad %int %gl_InvocationID
+         %25 = OpAccessChain %_ptr_Input_v4float %iVert %22 %int_0
+         %26 = OpLoad %v4float %25
+         %30 = OpAccessChain %_ptr_Input_v4float %iVert %22 %int_2 %int_7
+         %31 = OpLoad %v4float %30
+         %32 = OpFMul %v4float %26 %31
+         %40 = OpAccessChain %_ptr_Output_v4float %position %22
+               OpStore %40 %32
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
+      text, true, &live_inputs, &live_builtins);
+
+  auto itr0 = live_inputs.find(0);
+  auto itr1 = live_inputs.find(1);
+  auto itr2 = live_inputs.find(2);
+  auto itr3 = live_inputs.find(3);
+  auto itr4 = live_inputs.find(4);
+  auto itr5 = live_inputs.find(5);
+  auto itr6 = live_inputs.find(6);
+  auto itr7 = live_inputs.find(7);
+  auto itr8 = live_inputs.find(8);
+  auto itr9 = live_inputs.find(9);
+  auto itr10 = live_inputs.find(10);
+  auto itr11 = live_inputs.find(11);
+
+  // Expect live_inputs == {1, 10}
+  EXPECT_TRUE(itr0 == live_inputs.end());
+  EXPECT_TRUE(itr1 != live_inputs.end());
+  EXPECT_TRUE(itr2 == live_inputs.end());
+  EXPECT_TRUE(itr3 == live_inputs.end());
+  EXPECT_TRUE(itr4 == live_inputs.end());
+  EXPECT_TRUE(itr5 == live_inputs.end());
+  EXPECT_TRUE(itr6 == live_inputs.end());
+  EXPECT_TRUE(itr7 == live_inputs.end());
+  EXPECT_TRUE(itr8 == live_inputs.end());
+  EXPECT_TRUE(itr9 == live_inputs.end());
+  EXPECT_TRUE(itr10 != live_inputs.end());
+  EXPECT_TRUE(itr11 == live_inputs.end());
+}
+
+TEST_F(AnalyzeLiveInputTest, ArrayedInputMemberLocs) {
+  // Tests handling of member locs with arrayed input seen in Tesc, Tese
+  // and Geom shaders.
+  //
+  // Should report location {1, 12}.
+  //
+  // #version 450
+  //
+  // layout (vertices = 4) out;
+  //
+  // in Vertex
+  // {
+  //     layout (location = 1) vec4 p;
+  //     layout (location = 3) vec3 n;
+  //     layout (location = 5) vec4 f[100];
+  // } iVert[];
+  //
+  // layout (location = 0) out vec4 position[4];
+  //
+  // void main()
+  // {
+  //                 vec4 pos = iVert[gl_InvocationID].p *
+  //                            iVert[gl_InvocationID].f[7];
+  //                 position[gl_InvocationID] = pos;
+  // }
+  const std::string text = R"(
+               OpCapability Tessellation
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TessellationControl %main "main" %iVert %gl_InvocationID %position
+               OpExecutionMode %main OutputVertices 4
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "p"
+               OpMemberName %Vertex 1 "n"
+               OpMemberName %Vertex 2 "f"
+               OpName %iVert "iVert"
+               OpName %gl_InvocationID "gl_InvocationID"
+               OpName %position "position"
+               OpMemberDecorate %Vertex 0 Location 1
+               OpMemberDecorate %Vertex 1 Location 3
+               OpMemberDecorate %Vertex 2 Location 5
+               OpDecorate %Vertex Block
+               OpDecorate %gl_InvocationID BuiltIn InvocationId
+               OpDecorate %position Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+    %v3float = OpTypeVector %float 3
+       %uint = OpTypeInt 32 0
+   %uint_100 = OpConstant %uint 100
+%_arr_v4float_uint_100 = OpTypeArray %v4float %uint_100
+     %Vertex = OpTypeStruct %v4float %v3float %_arr_v4float_uint_100
+    %uint_32 = OpConstant %uint 32
+%_arr_Vertex_uint_32 = OpTypeArray %Vertex %uint_32
+%_ptr_Input__arr_Vertex_uint_32 = OpTypePointer Input %_arr_Vertex_uint_32
+      %iVert = OpVariable %_ptr_Input__arr_Vertex_uint_32 Input
+        %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_InvocationID = OpVariable %_ptr_Input_int Input
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+      %int_2 = OpConstant %int 2
+      %int_7 = OpConstant %int 7
+     %uint_4 = OpConstant %uint 4
+%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
+%_ptr_Output__arr_v4float_uint_4 = OpTypePointer Output %_arr_v4float_uint_4
+   %position = OpVariable %_ptr_Output__arr_v4float_uint_4 Output
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %22 = OpLoad %int %gl_InvocationID
+         %25 = OpAccessChain %_ptr_Input_v4float %iVert %22 %int_0
+         %26 = OpLoad %v4float %25
+         %30 = OpAccessChain %_ptr_Input_v4float %iVert %22 %int_2 %int_7
+         %31 = OpLoad %v4float %30
+         %32 = OpFMul %v4float %26 %31
+         %40 = OpAccessChain %_ptr_Output_v4float %position %22
+               OpStore %40 %32
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
+      text, true, &live_inputs, &live_builtins);
+
+  auto itr0 = live_inputs.find(0);
+  auto itr1 = live_inputs.find(1);
+  auto itr2 = live_inputs.find(2);
+  auto itr3 = live_inputs.find(3);
+  auto itr4 = live_inputs.find(4);
+  auto itr5 = live_inputs.find(5);
+  auto itr6 = live_inputs.find(6);
+  auto itr7 = live_inputs.find(7);
+  auto itr8 = live_inputs.find(8);
+  auto itr9 = live_inputs.find(9);
+  auto itr10 = live_inputs.find(10);
+  auto itr11 = live_inputs.find(11);
+  auto itr12 = live_inputs.find(12);
+  auto itr13 = live_inputs.find(13);
+
+  // Expect live_inputs == {1, 12}
+  EXPECT_TRUE(itr0 == live_inputs.end());
+  EXPECT_TRUE(itr1 != live_inputs.end());
+  EXPECT_TRUE(itr2 == live_inputs.end());
+  EXPECT_TRUE(itr3 == live_inputs.end());
+  EXPECT_TRUE(itr4 == live_inputs.end());
+  EXPECT_TRUE(itr5 == live_inputs.end());
+  EXPECT_TRUE(itr6 == live_inputs.end());
+  EXPECT_TRUE(itr7 == live_inputs.end());
+  EXPECT_TRUE(itr8 == live_inputs.end());
+  EXPECT_TRUE(itr9 == live_inputs.end());
+  EXPECT_TRUE(itr10 == live_inputs.end());
+  EXPECT_TRUE(itr11 == live_inputs.end());
+  EXPECT_TRUE(itr12 != live_inputs.end());
+  EXPECT_TRUE(itr13 == live_inputs.end());
+}
+
+TEST_F(AnalyzeLiveInputTest, Builtins) {
+  // Tests handling of builtin input seen in Tesc, Tese and Geom shaders.
+  //
+  // Should report builtin gl_PointSize only.
+  //
+  // #version 460
+  //
+  // layout(triangle_strip, max_vertices = 3) out;
+  // layout(triangles) in;
+  //
+  // void main()
+  // {
+  //         for (int i = 0; i < 3; i++)
+  //         {
+  //                 gl_Position = gl_in[i].gl_Position;
+  //                 gl_PointSize = gl_in[i].gl_PointSize;
+  //
+  //                 EmitVertex();
+  //         }
+  //
+  //         EndPrimitive();
+  // }
+  const std::string text = R"(
+               OpCapability Geometry
+               OpCapability GeometryPointSize
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Geometry %main "main" %_ %gl_in
+               OpExecutionMode %main Triangles
+               OpExecutionMode %main Invocations 1
+               OpExecutionMode %main OutputTriangleStrip
+               OpExecutionMode %main OutputVertices 3
+               OpSource GLSL 460
+               OpName %main "main"
+               OpName %i "i"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpMemberName %gl_PerVertex 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+               OpName %_ ""
+               OpName %gl_PerVertex_0 "gl_PerVertex"
+               OpMemberName %gl_PerVertex_0 0 "gl_Position"
+               OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+               OpName %gl_in "gl_in"
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex Block
+               OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+               OpDecorate %gl_PerVertex_0 Block
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+      %int_0 = OpConstant %int 0
+      %int_3 = OpConstant %int 3
+       %bool = OpTypeBool
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+          %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+%gl_PerVertex_0 = OpTypeStruct %v4float %float
+     %uint_3 = OpConstant %uint 3
+%_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
+%_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
+      %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %int_1 = OpConstant %int 1
+%_ptr_Input_float = OpTypePointer Input %float
+%_ptr_Output_float = OpTypePointer Output %float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+          %i = OpVariable %_ptr_Function_int Function
+               OpStore %i %int_0
+               OpBranch %10
+         %10 = OpLabel
+               OpLoopMerge %12 %13 None
+               OpBranch %14
+         %14 = OpLabel
+         %15 = OpLoad %int %i
+         %18 = OpSLessThan %bool %15 %int_3
+               OpBranchConditional %18 %11 %12
+         %11 = OpLabel
+         %32 = OpLoad %int %i
+         %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
+         %35 = OpLoad %v4float %34
+         %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %37 %35
+         %39 = OpLoad %int %i
+         %41 = OpAccessChain %_ptr_Input_float %gl_in %39 %int_1
+         %42 = OpLoad %float %41
+         %44 = OpAccessChain %_ptr_Output_float %_ %int_1
+               OpStore %44 %42
+               OpEmitVertex
+               OpBranch %13
+         %13 = OpLabel
+         %45 = OpLoad %int %i
+         %46 = OpIAdd %int %45 %int_1
+               OpStore %i %46
+               OpBranch %10
+         %12 = OpLabel
+               OpEndPrimitive
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
+      text, true, &live_inputs, &live_builtins);
+
+  auto itr0 = live_builtins.find((uint32_t)spv::BuiltIn::PointSize);
+  auto itr1 = live_builtins.find((uint32_t)spv::BuiltIn::ClipDistance);
+  auto itr2 = live_builtins.find((uint32_t)spv::BuiltIn::CullDistance);
+
+  // Expect live_builtins == { spv::BuiltIn::PointSize }
+  EXPECT_TRUE(itr0 != live_builtins.end());
+  EXPECT_TRUE(itr1 == live_builtins.end());
+  EXPECT_TRUE(itr2 == live_builtins.end());
+}
+
+TEST_F(AnalyzeLiveInputTest, ArrayedInputPatchLocs) {
+  // Tests handling of locs with arrayed input patch seen in Tese
+  //
+  // Should report location {3}.
+  //
+  // #version 450 core
+  //
+  // layout(triangles, ccw) in;
+  //
+  // layout(fractional_odd_spacing) in;
+  //
+  // layout(point_mode) in;
+  //
+  // layout(location=2) patch in float patchIn1[2];
+  //
+  // void main()
+  // {
+  //     vec4 p = gl_in[1].gl_Position;
+  //     gl_Position = p * patchIn1[1];
+  // }
+  const std::string text = R"(
+               OpCapability Tessellation
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TessellationEvaluation %main "main" %gl_in %_ %patchIn1
+               OpExecutionMode %main Triangles
+               OpExecutionMode %main SpacingFractionalOdd
+               OpExecutionMode %main VertexOrderCcw
+               OpExecutionMode %main PointMode
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %p "p"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpName %gl_in "gl_in"
+               OpName %gl_PerVertex_0 "gl_PerVertex"
+               OpMemberName %gl_PerVertex_0 0 "gl_Position"
+               OpName %_ ""
+               OpName %patchIn1 "patchIn1"
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpDecorate %gl_PerVertex Block
+               OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+               OpDecorate %gl_PerVertex_0 Block
+               OpDecorate %patchIn1 Patch
+               OpDecorate %patchIn1 Location 2
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float
+    %uint_32 = OpConstant %uint 32
+%_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
+%_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
+      %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%gl_PerVertex_0 = OpTypeStruct %v4float
+%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
+          %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
+     %uint_2 = OpConstant %uint 2
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_ptr_Input__arr_float_uint_2 = OpTypePointer Input %_arr_float_uint_2
+   %patchIn1 = OpVariable %_ptr_Input__arr_float_uint_2 Input
+%_ptr_Input_float = OpTypePointer Input %float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+          %p = OpVariable %_ptr_Function_v4float Function
+         %22 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
+         %23 = OpLoad %v4float %22
+               OpStore %p %23
+         %27 = OpLoad %v4float %p
+         %33 = OpAccessChain %_ptr_Input_float %patchIn1 %int_1
+         %34 = OpLoad %float %33
+         %35 = OpVectorTimesScalar %v4float %27 %34
+         %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %37 %35
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
+      text, true, &live_inputs, &live_builtins);
+
+  auto itr0 = live_inputs.find(0);
+  auto itr1 = live_inputs.find(1);
+  auto itr2 = live_inputs.find(2);
+  auto itr3 = live_inputs.find(3);
+
+  // Expect live_inputs == {3}
+  EXPECT_TRUE(itr0 == live_inputs.end());
+  EXPECT_TRUE(itr1 == live_inputs.end());
+  EXPECT_TRUE(itr2 == live_inputs.end());
+  EXPECT_TRUE(itr3 != live_inputs.end());
+}
+
+TEST_F(AnalyzeLiveInputTest, FragMultipleLocationsF16) {
+  // Should report locations {2, 5}
+  //
+  // #version 450
+  //
+  // layout(location = 2) in Vertex
+  // {
+  //         f16vec4 color0;
+  //         f16vec4 color1;
+  //         f16vec4 color2[3];
+  // } iVert;
+  //
+  // layout(location = 0) out f16vec4 oFragColor;
+  //
+  // void main()
+  // {
+  //     oFragColor = iVert.color0 + iVert.color2[1];
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+               OpCapability Float16
+               OpCapability StorageInputOutput16
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %oFragColor %iVert
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %oFragColor "oFragColor"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "color0"
+               OpMemberName %Vertex 1 "color1"
+               OpMemberName %Vertex 2 "color2"
+               OpName %iVert "iVert"
+               OpDecorate %oFragColor Location 0
+               OpDecorate %Vertex Block
+               OpDecorate %iVert Location 2
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %half = OpTypeFloat 16
+     %v4half = OpTypeVector %half 4
+%_ptr_Output_v4half = OpTypePointer Output %v4half
+ %oFragColor = OpVariable %_ptr_Output_v4half Output
+       %uint = OpTypeInt 32 0
+     %uint_3 = OpConstant %uint 3
+%_arr_v4half_uint_3 = OpTypeArray %v4half %uint_3
+     %Vertex = OpTypeStruct %v4half %v4half %_arr_v4half_uint_3
+%_ptr_Input_Vertex = OpTypePointer Input %Vertex
+      %iVert = OpVariable %_ptr_Input_Vertex Input
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4half = OpTypePointer Input %v4half
+      %int_2 = OpConstant %int 2
+      %int_1 = OpConstant %int 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpAccessChain %_ptr_Input_v4half %iVert %int_0
+         %20 = OpLoad %v4half %19
+         %23 = OpAccessChain %_ptr_Input_v4half %iVert %int_2 %int_1
+         %24 = OpLoad %v4half %23
+         %25 = OpFAdd %v4half %20 %24
+               OpStore %oFragColor %25
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
+      text, true, &live_inputs, &live_builtins);
+
+  auto itr0 = live_inputs.find(0);
+  auto itr1 = live_inputs.find(1);
+  auto itr2 = live_inputs.find(2);
+  auto itr3 = live_inputs.find(3);
+  auto itr4 = live_inputs.find(4);
+  auto itr5 = live_inputs.find(5);
+  auto itr6 = live_inputs.find(6);
+
+  // Expect live_inputs == {2, 5}
+  EXPECT_TRUE(itr0 == live_inputs.end());
+  EXPECT_TRUE(itr1 == live_inputs.end());
+  EXPECT_TRUE(itr2 != live_inputs.end());
+  EXPECT_TRUE(itr3 == live_inputs.end());
+  EXPECT_TRUE(itr4 == live_inputs.end());
+  EXPECT_TRUE(itr5 != live_inputs.end());
+  EXPECT_TRUE(itr6 == live_inputs.end());
+}
+
+}  // namespace
+}  // namespace opt
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/block_merge_test.cpp b/third_party/SPIRV-Tools/test/opt/block_merge_test.cpp
index 9698fed..6129bb2 100644
--- a/third_party/SPIRV-Tools/test/opt/block_merge_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/block_merge_test.cpp
@@ -1201,6 +1201,92 @@
   SinglePassRunAndMatch<BlockMergePass>(text, true);
 }
 
+TEST_F(BlockMergeTest, DontLoseCaseConstruct) {
+  const std::string text = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %func "func"
+OpExecutionMode %func LocalSize 1 1 1
+OpName %entry "entry";
+OpName %loop "loop"
+OpName %loop_merge "loop_merge"
+OpName %loop_cont "loop_cont"
+OpName %switch "switch"
+OpName %switch_merge "switch_merge"
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 0
+%void_fn = OpTypeFunction %void
+%bool_undef = OpUndef %bool
+%int_undef = OpUndef %int
+%func = OpFunction %void None %void_fn
+%entry = OpLabel
+OpBranch %loop
+%loop = OpLabel
+OpLoopMerge %loop_merge %loop_cont None
+OpBranch %switch
+%switch = OpLabel
+OpSelectionMerge %switch_merge None
+OpSwitch %int_undef %switch_merge 0 %break 1 %break
+%break = OpLabel
+OpBranch %loop_merge
+%switch_merge = OpLabel
+OpBranch %loop_cont
+%loop_cont = OpLabel
+OpBranch %loop
+%loop_merge = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  auto result = SinglePassRunAndDisassemble<opt::BlockMergePass>(
+      text, /* skip_nop = */ true, /* do_validation = */ true);
+  EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
+}
+
+TEST_F(BlockMergeTest, DontLoseDefaultCaseConstruct) {
+  const std::string text = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %func "func"
+OpExecutionMode %func LocalSize 1 1 1
+OpName %entry "entry";
+OpName %loop "loop"
+OpName %loop_merge "loop_merge"
+OpName %loop_cont "loop_cont"
+OpName %switch "switch"
+OpName %switch_merge "switch_merge"
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 0
+%void_fn = OpTypeFunction %void
+%bool_undef = OpUndef %bool
+%int_undef = OpUndef %int
+%func = OpFunction %void None %void_fn
+%entry = OpLabel
+OpBranch %loop
+%loop = OpLabel
+OpLoopMerge %loop_merge %loop_cont None
+OpBranch %switch
+%switch = OpLabel
+OpSelectionMerge %switch_merge None
+OpSwitch %int_undef %cont 0 %switch_merge 1 %switch_merge
+%cont = OpLabel
+OpBranch %loop_cont
+%switch_merge = OpLabel
+OpBranch %loop_merge
+%loop_cont = OpLabel
+OpBranch %loop
+%loop_merge = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  auto result = SinglePassRunAndDisassemble<opt::BlockMergePass>(
+      text, /* skip_nop = */ true, /* do_validation = */ true);
+  EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //    More complex control flow
diff --git a/third_party/SPIRV-Tools/test/opt/copy_prop_array_test.cpp b/third_party/SPIRV-Tools/test/opt/copy_prop_array_test.cpp
index a4599f0..d6e376e 100644
--- a/third_party/SPIRV-Tools/test/opt/copy_prop_array_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/copy_prop_array_test.cpp
@@ -1839,6 +1839,110 @@
 
   SinglePassRunAndCheck<CopyPropagateArrays>(text, text, false);
 }
+
+// Since Spir-V 1.4, resources that are used by a shader must be on the
+// OpEntryPoint instruction with the inputs and outputs. This test ensures that
+// this does not stop the pass from working.
+TEST_F(CopyPropArrayPassTest, EntryPointUser) {
+  const std::string before = R"(OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main" %g_rwTexture3d
+OpExecutionMode %main LocalSize 256 1 1
+OpSource HLSL 660
+OpName %type_3d_image "type.3d.image"
+OpName %g_rwTexture3d "g_rwTexture3d"
+OpName %main "main"
+OpDecorate %g_rwTexture3d DescriptorSet 0
+OpDecorate %g_rwTexture3d Binding 0
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%uint_1 = OpConstant %uint 1
+%uint_2 = OpConstant %uint 2
+%uint_3 = OpConstant %uint 3
+%v3uint = OpTypeVector %uint 3
+%10 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3
+%type_3d_image = OpTypeImage %uint 3D 2 0 0 2 R32ui
+%_ptr_UniformConstant_type_3d_image = OpTypePointer UniformConstant %type_3d_image
+%void = OpTypeVoid
+%13 = OpTypeFunction %void
+%_ptr_Function_type_3d_image = OpTypePointer Function %type_3d_image
+%_ptr_Image_uint = OpTypePointer Image %uint
+%g_rwTexture3d = OpVariable %_ptr_UniformConstant_type_3d_image UniformConstant
+%main = OpFunction %void None %13
+%16 = OpLabel
+%17 = OpVariable %_ptr_Function_type_3d_image Function
+%18 = OpLoad %type_3d_image %g_rwTexture3d
+OpStore %17 %18
+; CHECK: %19 = OpImageTexelPointer %_ptr_Image_uint %g_rwTexture3d %10 %uint_0
+%19 = OpImageTexelPointer %_ptr_Image_uint %17 %10 %uint_0
+%20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
+OpReturn
+OpFunctionEnd
+)";
+
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
+  SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
+}
+
+// As per SPIRV spec, struct cannot be indexed with non-constant indices
+// through OpAccessChain, only arrays.
+// The copy-propagate-array pass tries to remove superfluous copies when the
+// original array could be indexed instead of the copy.
+//
+// This test verifies we handle this case:
+//  struct SRC { int field1; ...; int fieldN }
+//  int tmp_arr[N] = { SRC.field1, ..., SRC.fieldN }
+//  return tmp_arr[index];
+//
+// In such case, we cannot optimize the access: this array was added to allow
+// dynamic indexing in the struct.
+TEST_F(CopyPropArrayPassTest, StructIndexCannotBecomeDynamic) {
+  const std::string text = R"(OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Vertex %1 "main"
+OpDecorate %2 DescriptorSet 0
+OpDecorate %2 Binding 0
+OpMemberDecorate %_struct_3 0 Offset 0
+OpDecorate %_struct_3 Block
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_struct_3 = OpTypeStruct %v4float
+%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
+%uint = OpTypeInt 32 0
+%void = OpTypeVoid
+%11 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+%13 = OpTypeFunction %v4float %_ptr_Function_uint
+%uint_1 = OpConstant %uint 1
+%_arr_v4float_uint_1 = OpTypeArray %v4float %uint_1
+%_ptr_Function__arr_v4float_uint_1 = OpTypePointer Function %_arr_v4float_uint_1
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%2 = OpVariable %_ptr_Uniform__struct_3 Uniform
+%19 = OpUndef %v4float
+%1 = OpFunction %void None %11
+%20 = OpLabel
+OpReturn
+OpFunctionEnd
+%21 = OpFunction %v4float None %13
+%22 = OpFunctionParameter %_ptr_Function_uint
+%23 = OpLabel
+%24 = OpVariable %_ptr_Function__arr_v4float_uint_1 Function
+%25 = OpAccessChain %_ptr_Uniform_v4float %2 %int_0
+%26 = OpLoad %v4float %25
+%27 = OpCompositeConstruct %_arr_v4float_uint_1 %26
+OpStore %24 %27
+%28 = OpLoad %uint %22
+%29 = OpAccessChain %_ptr_Function_v4float %24 %28
+OpReturnValue %19
+OpFunctionEnd
+)";
+
+  SinglePassRunAndCheck<CopyPropagateArrays>(text, text, false);
+}
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/dataflow.cpp b/third_party/SPIRV-Tools/test/opt/dataflow.cpp
index 4742015..51473d8 100644
--- a/third_party/SPIRV-Tools/test/opt/dataflow.cpp
+++ b/third_party/SPIRV-Tools/test/opt/dataflow.cpp
@@ -66,7 +66,7 @@
 
   VisitResult Visit(Instruction* inst) override {
     // Conditional branches can be enqueued from labels, so skip them.
-    if (inst->opcode() != SpvOpLabel)
+    if (inst->opcode() != spv::Op::OpLabel)
       return DataFlowAnalysis::VisitResult::kResultFixed;
     uint32_t id = inst->result_id();
     VisitResult ret = DataFlowAnalysis::VisitResult::kResultFixed;
diff --git a/third_party/SPIRV-Tools/test/opt/debug_info_manager_test.cpp b/third_party/SPIRV-Tools/test/opt/debug_info_manager_test.cpp
index e87d0be..9e479c0 100644
--- a/third_party/SPIRV-Tools/test/opt/debug_info_manager_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/debug_info_manager_test.cpp
@@ -155,7 +155,7 @@
   EXPECT_EQ(inlined_at->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1);
 
   const uint32_t line_number = 77U;
-  Instruction line(context.get(), SpvOpLine);
+  Instruction line(context.get(), spv::Op::OpLine);
   line.SetInOperands({
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {5U}},
       {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}},
@@ -278,7 +278,7 @@
                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
 
   const uint32_t line_number = 7U;
-  Instruction line(context.get(), SpvOpLine);
+  Instruction line(context.get(), spv::Op::OpLine);
   line.SetInOperands({
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {5U}},
       {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}},
diff --git a/third_party/SPIRV-Tools/test/opt/decoration_manager_test.cpp b/third_party/SPIRV-Tools/test/opt/decoration_manager_test.cpp
index c9fabe7..cf3516a 100644
--- a/third_party/SPIRV-Tools/test/opt/decoration_manager_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/decoration_manager_test.cpp
@@ -88,7 +88,7 @@
   std::string GetErrorMessage() const { return error_message_; }
 
   std::string ToText(const std::vector<Instruction*>& inst) {
-    std::vector<uint32_t> binary = {SpvMagicNumber, 0x10200, 0u, 2u, 0u};
+    std::vector<uint32_t> binary = {spv::MagicNumber, 0x10200, 0u, 2u, 0u};
     for (const Instruction* i : inst)
       i->ToBinaryWithoutAttachedDebugInsts(&binary);
     std::string text;
@@ -118,16 +118,17 @@
 TEST_F(DecorationManagerTest,
        ComparingDecorationsWithDiffOpcodesDecorateDecorateId) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
-  // This parameter can be interpreted both as { SpvDecorationConstant }
+  // This parameter can be interpreted both as { spv::Decoration::Constant }
   // and also as a list of IDs:  { 22 }
-  const std::vector<uint32_t> param{SpvDecorationConstant};
+  const std::vector<uint32_t> param{
+      static_cast<uint32_t>(spv::Decoration::Constant)};
   // OpDecorate %1 Constant
   Instruction inst1(
-      &ir_context, SpvOpDecorate, 0u, 0u,
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_DECORATION, param}});
   // OpDecorateId %1 %22   ; 'Constant' is decoration number 22
   Instruction inst2(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_ID, param}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
@@ -137,16 +138,17 @@
 TEST_F(DecorationManagerTest,
        ComparingDecorationsWithDiffOpcodesDecorateDecorateString) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
-  // This parameter can be interpreted both as { SpvDecorationConstant }
+  // This parameter can be interpreted both as { spv::Decoration::Constant }
   // and also as a null-terminated string with a single character with value 22.
-  const std::vector<uint32_t> param{SpvDecorationConstant};
+  const std::vector<uint32_t> param{
+      static_cast<uint32_t>(spv::Decoration::Constant)};
   // OpDecorate %1 Constant
   Instruction inst1(
-      &ir_context, SpvOpDecorate, 0u, 0u,
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_DECORATION, param}});
   // OpDecorateStringGOOGLE %1 !22
   Instruction inst2(
-      &ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_LITERAL_STRING, param}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
@@ -156,13 +158,15 @@
 TEST_F(DecorationManagerTest, ComparingDecorationsWithDiffDecorateParam) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
-  Instruction inst1(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpDecorate %1 Restrict
-  Instruction inst2(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationRestrict}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Restrict)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true));
@@ -172,11 +176,11 @@
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
   Instruction inst1(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_ID, {555}}});
   // OpDecorate %1 Restrict
   Instruction inst2(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_ID, {666}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
@@ -186,11 +190,11 @@
 TEST_F(DecorationManagerTest, ComparingDecorationsWithDiffDecorateStringParam) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
-  Instruction inst1(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+  Instruction inst1(&ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
                     {{SPV_OPERAND_TYPE_ID, {1u}},
                      {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("Hello!")}});
   // OpDecorate %1 Restrict
-  Instruction inst2(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+  Instruction inst2(&ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
                     {{SPV_OPERAND_TYPE_ID, {1u}},
                      {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("Hellx")}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
@@ -201,13 +205,15 @@
 TEST_F(DecorationManagerTest, ComparingSameDecorationsOnDiffTargetAllowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
-  Instruction inst1(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpDecorate %2 Constant
-  Instruction inst2(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {2u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {2u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_TRUE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true));
@@ -216,10 +222,10 @@
 TEST_F(DecorationManagerTest, ComparingSameDecorationIdsOnDiffTargetAllowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   Instruction inst1(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_DECORATION, {44}}});
   Instruction inst2(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {2u}}, {SPV_OPERAND_TYPE_DECORATION, {44}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
@@ -229,10 +235,10 @@
 TEST_F(DecorationManagerTest,
        ComparingSameDecorationStringsOnDiffTargetAllowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
-  Instruction inst1(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+  Instruction inst1(&ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
                     {{SPV_OPERAND_TYPE_ID, {1u}},
                      {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("hello")}});
-  Instruction inst2(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+  Instruction inst2(&ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
                     {{SPV_OPERAND_TYPE_ID, {2u}},
                      {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("hello")}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
@@ -243,13 +249,15 @@
 TEST_F(DecorationManagerTest, ComparingSameDecorationsOnDiffTargetDisallowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
-  Instruction inst1(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpDecorate %2 Constant
-  Instruction inst2(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {2u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {2u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, false));
@@ -258,15 +266,17 @@
 TEST_F(DecorationManagerTest, ComparingMemberDecorationsOnSameTypeDiffMember) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpMemberDecorate %1 0 Constant
-  Instruction inst1(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpMemberDecorate %1 1 Constant
-  Instruction inst2(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true));
@@ -276,15 +286,17 @@
        ComparingSameMemberDecorationsOnDiffTargetAllowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpMemberDecorate %1 0 Constant
-  Instruction inst1(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpMemberDecorate %2 0 Constant
-  Instruction inst2(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {2u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {2u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_TRUE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true));
@@ -294,15 +306,17 @@
        ComparingSameMemberDecorationsOnDiffTargetDisallowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpMemberDecorate %1 0 Constant
-  Instruction inst1(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpMemberDecorate %2 0 Constant
-  Instruction inst2(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {2u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {2u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, false));
@@ -486,7 +500,7 @@
   DecorationManager* decoManager = GetDecorationManager(spirv);
   EXPECT_THAT(GetErrorMessage(), "");
   decoManager->RemoveDecorationsFrom(1u, [](const Instruction& inst) {
-    return inst.opcode() == SpvOpDecorate &&
+    return inst.opcode() == spv::Op::OpDecorate &&
            inst.GetSingleWordInOperand(0u) == 3u;
   });
   auto decorations = decoManager->GetDecorationsFor(1u, false);
@@ -537,9 +551,10 @@
   DecorationManager* decoManager = GetDecorationManager(spirv);
   EXPECT_THAT(GetErrorMessage(), "");
   decoManager->RemoveDecorationsFrom(1u, [](const Instruction& inst) {
-    return inst.opcode() == SpvOpDecorate &&
+    return inst.opcode() == spv::Op::OpDecorate &&
            inst.GetSingleWordInOperand(0u) == 3u &&
-           inst.GetSingleWordInOperand(1u) == SpvDecorationBuiltIn;
+           spv::Decoration(inst.GetSingleWordInOperand(1u)) ==
+               spv::Decoration::BuiltIn;
   });
   auto decorations = decoManager->GetDecorationsFor(1u, false);
   EXPECT_THAT(GetErrorMessage(), "");
@@ -763,7 +778,7 @@
   EXPECT_EQ(GetErrorMessage(), "");
   EXPECT_TRUE(decorations.empty());
 
-  decoManager->CloneDecorations(1u, 8u, {SpvDecorationRelaxedPrecision});
+  decoManager->CloneDecorations(1u, 8u, {spv::Decoration::RelaxedPrecision});
   decorations = decoManager->GetDecorationsFor(8u, false);
   EXPECT_THAT(GetErrorMessage(), "");
 
@@ -822,7 +837,7 @@
   EXPECT_EQ(GetErrorMessage(), "");
   EXPECT_TRUE(decorations.empty());
 
-  decoManager->CloneDecorations(2u, 9u, {SpvDecorationRelaxedPrecision});
+  decoManager->CloneDecorations(2u, 9u, {spv::Decoration::RelaxedPrecision});
   decorations = decoManager->GetDecorationsFor(9u, false);
   EXPECT_THAT(GetErrorMessage(), "");
 
diff --git a/third_party/SPIRV-Tools/test/opt/def_use_test.cpp b/third_party/SPIRV-Tools/test/opt/def_use_test.cpp
index 0210095..4315012 100644
--- a/third_party/SPIRV-Tools/test/opt/def_use_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/def_use_test.cpp
@@ -50,9 +50,9 @@
 //
 // If |id| is used multiple times in a single instruction, that instruction's
 // opcode will appear a corresponding number of times.
-std::vector<SpvOp> GetUseOpcodes(const std::unique_ptr<IRContext>& context,
-                                 uint32_t id) {
-  std::vector<SpvOp> opcodes;
+std::vector<spv::Op> GetUseOpcodes(const std::unique_ptr<IRContext>& context,
+                                   uint32_t id) {
+  std::vector<spv::Op> opcodes;
   context->get_def_use_mgr()->ForEachUse(
       id, [&opcodes](Instruction* user, uint32_t) {
         opcodes.push_back(user->opcode());
@@ -99,7 +99,7 @@
     const auto expected_def = expected_defs_uses.defs[i].second;
     ASSERT_EQ(1u, actual_defs.count(id)) << "expected to def id [" << id << "]";
     auto def = actual_defs.at(id);
-    if (def->opcode() != SpvOpConstant) {
+    if (def->opcode() != spv::Op::OpConstant) {
       // Constants don't disassemble properly without a full context.
       EXPECT_EQ(expected_def, DisassembleInst(actual_defs.at(id)));
     }
@@ -116,7 +116,7 @@
   for (uint32_t id = 0; id != idBound; ++id) {
     if (mgr->GetDef(id)) {
       mgr->ForEachUser(id, [id, &userMap](Instruction* user) {
-        if (user->opcode() != SpvOpConstant) {
+        if (user->opcode() != spv::Op::OpConstant) {
           userMap[id].push_back(user);
         }
       });
@@ -1298,21 +1298,23 @@
 
   {
     EXPECT_EQ(2u, NumUses(context, 6));
-    std::vector<SpvOp> opcodes = GetUseOpcodes(context, 6u);
-    EXPECT_THAT(opcodes, UnorderedElementsAre(SpvOpSwitch, SpvOpReturnValue));
+    std::vector<spv::Op> opcodes = GetUseOpcodes(context, 6u);
+    EXPECT_THAT(opcodes, UnorderedElementsAre(spv::Op::OpSwitch,
+                                              spv::Op::OpReturnValue));
   }
   {
     EXPECT_EQ(6u, NumUses(context, 7));
-    std::vector<SpvOp> opcodes = GetUseOpcodes(context, 7u);
+    std::vector<spv::Op> opcodes = GetUseOpcodes(context, 7u);
     // OpSwitch is now a user of %7.
-    EXPECT_THAT(opcodes, UnorderedElementsAre(SpvOpSelectionMerge, SpvOpBranch,
-                                              SpvOpBranch, SpvOpBranch,
-                                              SpvOpBranch, SpvOpSwitch));
+    EXPECT_THAT(opcodes, UnorderedElementsAre(
+                             spv::Op::OpSelectionMerge, spv::Op::OpBranch,
+                             spv::Op::OpBranch, spv::Op::OpBranch,
+                             spv::Op::OpBranch, spv::Op::OpSwitch));
   }
   // Check all ids only used by OpSwitch after replacement.
   for (const auto id : {8u, 10u, 11u}) {
     EXPECT_EQ(1u, NumUses(context, id));
-    EXPECT_EQ(SpvOpSwitch, GetUseOpcodes(context, id).back());
+    EXPECT_EQ(spv::Op::OpSwitch, GetUseOpcodes(context, id).back());
   }
 }
 
@@ -1378,10 +1380,11 @@
   // Analyze the instructions.
   DefUseManager manager(context.module());
 
-  Instruction label(&context, SpvOpLabel, 0, 2, {});
+  Instruction label(&context, spv::Op::OpLabel, 0, 2, {});
   manager.AnalyzeInstDefUse(&label);
 
-  Instruction branch(&context, SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {2}}});
+  Instruction branch(&context, spv::Op::OpBranch, 0, 0,
+                     {{SPV_OPERAND_TYPE_ID, {2}}});
   manager.AnalyzeInstDefUse(&branch);
   context.module()->SetIdBound(3);
 
@@ -1409,7 +1412,7 @@
   // Analyze the instructions.
   DefUseManager manager(context->module());
 
-  Instruction newInst(context.get(), SpvOpConstantTrue, 1, 2, {});
+  Instruction newInst(context.get(), spv::Op::OpConstantTrue, 1, 2, {});
   manager.AnalyzeInstDefUse(&newInst);
 
   InstDefUse expected = {
@@ -1703,7 +1706,7 @@
   DefUseManager* def_use_mgr = context->get_def_use_mgr();
   Instruction* def = def_use_mgr->GetDef(9);
   Instruction* use = def_use_mgr->GetDef(10);
-  def->SetOpcode(SpvOpCopyObject);
+  def->SetOpcode(spv::Op::OpCopyObject);
   def->SetInOperands({{SPV_OPERAND_TYPE_ID, {25}}});
   context->UpdateDefUse(def);
 
diff --git a/third_party/SPIRV-Tools/test/opt/eliminate_dead_input_components_test.cpp b/third_party/SPIRV-Tools/test/opt/eliminate_dead_input_components_test.cpp
index b0098f7..667350d 100644
--- a/third_party/SPIRV-Tools/test/opt/eliminate_dead_input_components_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/eliminate_dead_input_components_test.cpp
@@ -85,7 +85,8 @@
 
   SetTargetEnv(SPV_ENV_VULKAN_1_3);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
+                                                          false);
 }
 
 TEST_F(ElimDeadInputComponentsTest, ElimOneConstantIndexInBounds) {
@@ -135,7 +136,8 @@
 
   SetTargetEnv(SPV_ENV_VULKAN_1_3);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
+                                                          false);
 }
 
 TEST_F(ElimDeadInputComponentsTest, ElimTwoConstantIndices) {
@@ -202,7 +204,8 @@
 
   SetTargetEnv(SPV_ENV_VULKAN_1_3);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
+                                                          false);
 }
 
 TEST_F(ElimDeadInputComponentsTest, NoElimMaxConstantIndex) {
@@ -268,7 +271,8 @@
 
   SetTargetEnv(SPV_ENV_VULKAN_1_3);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
+                                                          false);
 }
 
 TEST_F(ElimDeadInputComponentsTest, NoElimNonConstantIndex) {
@@ -350,7 +354,8 @@
 
   SetTargetEnv(SPV_ENV_VULKAN_1_3);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
+                                                          false);
 }
 
 TEST_F(ElimDeadInputComponentsTest, NoElimNonIndexedAccessChain) {
@@ -396,7 +401,289 @@
 
   SetTargetEnv(SPV_ENV_VULKAN_1_3);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
+                                                          false);
+}
+
+TEST_F(ElimDeadInputComponentsTest, ElimStructMember) {
+  // Should eliminate uv
+  //
+  // #version 450
+  //
+  // in Vertex {
+  //   vec4 Cd;
+  //   vec2 uv;
+  // } iVert;
+  //
+  // out vec4 fragColor;
+  //
+  // void main()
+  // {
+  //   vec4 color = vec4(iVert.Cd);
+  //   fragColor = color;
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %iVert %fragColor
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "Cd"
+               OpMemberName %Vertex 1 "uv"
+               OpName %iVert "iVert"
+               OpName %fragColor "fragColor"
+               OpDecorate %Vertex Block
+               OpDecorate %iVert Location 0
+               OpDecorate %fragColor Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+    %v2float = OpTypeVector %float 2
+     %Vertex = OpTypeStruct %v4float %v2float
+; CHECK: %Vertex = OpTypeStruct %v4float %v2float
+; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
+%_ptr_Input_Vertex = OpTypePointer Input %Vertex
+; CHECK: [[pty:%\w+]] = OpTypePointer Input [[sty]]
+      %iVert = OpVariable %_ptr_Input_Vertex Input
+; CHECK: %iVert = OpVariable [[pty]] Input
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+  %fragColor = OpVariable %_ptr_Output_v4float Output
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
+         %18 = OpLoad %v4float %17
+               OpStore %fragColor %18
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
+                                                          false);
+}
+
+TEST_F(ElimDeadInputComponentsTest, ElimOutputStructMember) {
+  // Should eliminate uv from Vertex and all but gl_Position from gl_PerVertex
+  //
+  // #version 450
+  //
+  // out Vertex {
+  //   vec4 Cd;
+  //   vec2 uv;
+  // } oVert;
+  //
+  // in vec3 P;
+  //
+  // void main()
+  // {
+  //   vec4 worldSpacePos = vec4(P, 1);
+  //   oVert.Cd = vec4(1, 0.5, 0, 1);
+  //   gl_Position = worldSpacePos;
+  // }
+
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %P %oVert %_
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %P "P"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "Cd"
+               OpMemberName %Vertex 1 "uv"
+               OpName %oVert "oVert"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpMemberName %gl_PerVertex 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+               OpName %_ ""
+               OpDecorate %P Location 0
+               OpDecorate %Vertex Block
+               OpDecorate %oVert Location 0
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex Block
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+    %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+          %P = OpVariable %_ptr_Input_v3float Input
+    %float_1 = OpConstant %float 1
+    %v2float = OpTypeVector %float 2
+     %Vertex = OpTypeStruct %v4float %v2float
+%_ptr_Output_Vertex = OpTypePointer Output %Vertex
+      %oVert = OpVariable %_ptr_Output_Vertex Output
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+  %float_0_5 = OpConstant %float 0.5
+    %float_0 = OpConstant %float 0
+         %27 = OpConstantComposite %v4float %float_1 %float_0_5 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+          %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+; CHECK: %Vertex = OpTypeStruct %v4float %v2float
+; CHECK: %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+; CHECK: %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
+; CHECK: [[pty:%\w+]] = OpTypePointer Output [[sty]]
+; CHECK: %oVert = OpVariable [[pty]] Output
+; CHECK: [[sty2:%\w+]] = OpTypeStruct %v4float
+; CHECK: [[pty2:%\w+]] = OpTypePointer Output [[sty2]]
+; CHECK: %_ = OpVariable [[pty2]] Output
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %13 = OpLoad %v3float %P
+         %15 = OpCompositeExtract %float %13 0
+         %16 = OpCompositeExtract %float %13 1
+         %17 = OpCompositeExtract %float %13 2
+         %18 = OpCompositeConstruct %v4float %15 %16 %17 %float_1
+         %29 = OpAccessChain %_ptr_Output_v4float %oVert %int_0
+               OpStore %29 %27
+         %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %37 %18
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, true,
+                                                          false);
+}
+
+TEST_F(ElimDeadInputComponentsTest, ElimOutputArrayMembers) {
+  // Should reduce to uv[2]
+  //
+  // #version 450
+  //
+  // layout(location = 0) out vec2 uv[8];
+  //
+  // void main()
+  // {
+  //     uv[1] = vec2(1, 0.5);
+  // }
+
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %uv
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %uv "uv"
+               OpDecorate %uv Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+       %uint = OpTypeInt 32 0
+     %uint_8 = OpConstant %uint 8
+%_arr_v2float_uint_8 = OpTypeArray %v2float %uint_8
+%_ptr_Output__arr_v2float_uint_8 = OpTypePointer Output %_arr_v2float_uint_8
+         %uv = OpVariable %_ptr_Output__arr_v2float_uint_8 Output
+;CHECK-NOT:         %uv = OpVariable %_ptr_Output__arr_v2float_uint_8 Output
+;CHECK:             %uv = OpVariable %_ptr_Output__arr_v2float_uint_2 Output
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+    %float_1 = OpConstant %float 1
+  %float_0_5 = OpConstant %float 0.5
+         %17 = OpConstantComposite %v2float %float_1 %float_0_5
+%_ptr_Output_v2float = OpTypePointer Output %v2float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpAccessChain %_ptr_Output_v2float %uv %int_1
+               OpStore %19 %17
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, true,
+                                                          false);
+}
+
+TEST_F(ElimDeadInputComponentsTest, VertexOnly) {
+  // Should NOT eliminate uv
+  //
+  // #version 450
+  //
+  // in Vertex {
+  //   vec4 Cd;
+  //   vec2 uv;
+  // } iVert;
+  //
+  // out vec4 fragColor;
+  //
+  // void main()
+  // {
+  //   vec4 color = vec4(iVert.Cd);
+  //   fragColor = color;
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %iVert %fragColor
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "Cd"
+               OpMemberName %Vertex 1 "uv"
+               OpName %iVert "iVert"
+               OpName %fragColor "fragColor"
+               OpDecorate %Vertex Block
+               OpDecorate %iVert Location 0
+               OpDecorate %fragColor Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+    %v2float = OpTypeVector %float 2
+     %Vertex = OpTypeStruct %v4float %v2float
+; CHECK: %Vertex = OpTypeStruct %v4float %v2float
+%_ptr_Input_Vertex = OpTypePointer Input %Vertex
+; CHECK: %_ptr_Input_Vertex = OpTypePointer Input %Vertex
+      %iVert = OpVariable %_ptr_Input_Vertex Input
+; CHECK: %iVert = OpVariable %_ptr_Input_Vertex Input
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+  %fragColor = OpVariable %_ptr_Output_v4float Output
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
+         %18 = OpLoad %v4float %17
+               OpStore %fragColor %18
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<EliminateDeadInputComponentsPass>(text, true, false,
+                                                          true);
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/opt/eliminate_dead_member_test.cpp b/third_party/SPIRV-Tools/test/opt/eliminate_dead_member_test.cpp
index e277999..4438f3d 100644
--- a/third_party/SPIRV-Tools/test/opt/eliminate_dead_member_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/eliminate_dead_member_test.cpp
@@ -978,6 +978,7 @@
                OpMemberDecorate %type__Globals 1 Offset 4
                OpMemberDecorate %type__Globals 2 Offset 16
                OpDecorate %type__Globals Block
+               OpDecorate %_ptr_Uniform_type__Globals ArrayStride 8
        %uint = OpTypeInt 32 0
      %uint_0 = OpConstant %uint 0
      %uint_1 = OpConstant %uint 1
diff --git a/third_party/SPIRV-Tools/test/opt/eliminate_dead_output_stores_test.cpp b/third_party/SPIRV-Tools/test/opt/eliminate_dead_output_stores_test.cpp
new file mode 100644
index 0000000..470e709
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/opt/eliminate_dead_output_stores_test.cpp
@@ -0,0 +1,952 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+// Copyright (c) 2022 LunarG Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <unordered_set>
+
+#include "gmock/gmock.h"
+#include "test/opt/pass_fixture.h"
+#include "test/opt/pass_utils.h"
+
+namespace spvtools {
+namespace opt {
+namespace {
+
+using ElimDeadOutputStoresTest = PassTest<::testing::Test>;
+
+TEST_F(ElimDeadOutputStoresTest, VertMultipleLocations) {
+  // #version 450
+  //
+  // layout(location = 2) out Vertex
+  // {
+  //         vec4 color0;
+  //         vec4 color1;
+  //         vec4 color2[3];
+  // } oVert;
+  //
+  // void main()
+  // {
+  //     oVert.color0 = vec4(0.0,0.0,0.0,0.0);
+  //     oVert.color1 = vec4(0.1,0.0,0.0,0.0);
+  //     oVert.color2[0] = vec4(0.2,0.0,0.0,0.0);
+  //     oVert.color2[1] = vec4(0.3,0.0,0.0,0.0);
+  //     oVert.color2[2] = vec4(0.4,0.0,0.0,0.0);
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %oVert
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "color0"
+               OpMemberName %Vertex 1 "color1"
+               OpMemberName %Vertex 2 "color2"
+               OpName %oVert "oVert"
+               OpDecorate %Vertex Block
+               OpDecorate %oVert Location 2
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+       %uint = OpTypeInt 32 0
+     %uint_3 = OpConstant %uint 3
+%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
+     %Vertex = OpTypeStruct %v4float %v4float %_arr_v4float_uint_3
+%_ptr_Output_Vertex = OpTypePointer Output %Vertex
+      %oVert = OpVariable %_ptr_Output_Vertex Output
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+    %float_0 = OpConstant %float 0
+         %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %int_1 = OpConstant %int 1
+%float_0_100000001 = OpConstant %float 0.100000001
+         %22 = OpConstantComposite %v4float %float_0_100000001 %float_0 %float_0 %float_0
+      %int_2 = OpConstant %int 2
+%float_0_200000003 = OpConstant %float 0.200000003
+         %26 = OpConstantComposite %v4float %float_0_200000003 %float_0 %float_0 %float_0
+%float_0_300000012 = OpConstant %float 0.300000012
+         %29 = OpConstantComposite %v4float %float_0_300000012 %float_0 %float_0 %float_0
+%float_0_400000006 = OpConstant %float 0.400000006
+         %32 = OpConstantComposite %v4float %float_0_400000006 %float_0 %float_0 %float_0
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpAccessChain %_ptr_Output_v4float %oVert %int_0
+               OpStore %19 %17
+;CHECK:            OpStore %19 %17
+         %23 = OpAccessChain %_ptr_Output_v4float %oVert %int_1
+               OpStore %23 %22
+;CHECK-NOT:        OpStore %23 %22
+         %27 = OpAccessChain %_ptr_Output_v4float %oVert %int_2 %int_0
+               OpStore %27 %26
+;CHECK-NOT:        OpStore %27 %26
+         %30 = OpAccessChain %_ptr_Output_v4float %oVert %int_2 %int_1
+               OpStore %30 %29
+;CHECK:            OpStore %30 %29
+         %33 = OpAccessChain %_ptr_Output_v4float %oVert %int_2 %int_2
+               OpStore %33 %32
+;CHECK-NOT:        OpStore %33 %32
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  live_inputs.insert(2);
+  live_inputs.insert(5);
+  SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
+                                                       &live_builtins);
+}
+
+TEST_F(ElimDeadOutputStoresTest, VertMatrix) {
+  // #version 450
+  //
+  // layout(location = 2) out Vertex
+  // {
+  //         vec4 color0;
+  //         vec4 color1;
+  //         mat4 color2;
+  //         mat4 color3;
+  //         mat4 color4;
+  // } oVert;
+  //
+  // void main()
+  // {
+  //     oVert.color0 = vec4(0.0,0.0,0.0,0.0);
+  //     oVert.color1 = vec4(0.1,0.0,0.0,0.0);
+  //     oVert.color2[2] = vec4(0.2,0.0,0.0,0.0);
+  //     oVert.color3[1] = vec4(0.3,0.0,0.0,0.0);
+  //     oVert.color4[0] = vec4(0.4,0.0,0.0,0.0);
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %oVert
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "color0"
+               OpMemberName %Vertex 1 "color1"
+               OpMemberName %Vertex 2 "color2"
+               OpMemberName %Vertex 3 "color3"
+               OpMemberName %Vertex 4 "color4"
+               OpName %oVert "oVert"
+               OpDecorate %Vertex Block
+               OpDecorate %oVert Location 2
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%mat4v4float = OpTypeMatrix %v4float 4
+     %Vertex = OpTypeStruct %v4float %v4float %mat4v4float %mat4v4float %mat4v4float
+%_ptr_Output_Vertex = OpTypePointer Output %Vertex
+      %oVert = OpVariable %_ptr_Output_Vertex Output
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+    %float_0 = OpConstant %float 0
+         %15 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %int_1 = OpConstant %int 1
+%float_0_100000001 = OpConstant %float 0.100000001
+         %20 = OpConstantComposite %v4float %float_0_100000001 %float_0 %float_0 %float_0
+      %int_2 = OpConstant %int 2
+%float_0_200000003 = OpConstant %float 0.200000003
+         %24 = OpConstantComposite %v4float %float_0_200000003 %float_0 %float_0 %float_0
+      %int_3 = OpConstant %int 3
+%float_0_300000012 = OpConstant %float 0.300000012
+         %28 = OpConstantComposite %v4float %float_0_300000012 %float_0 %float_0 %float_0
+      %int_4 = OpConstant %int 4
+%float_0_400000006 = OpConstant %float 0.400000006
+         %32 = OpConstantComposite %v4float %float_0_400000006 %float_0 %float_0 %float_0
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %17 = OpAccessChain %_ptr_Output_v4float %oVert %int_0
+               OpStore %17 %15
+; CHECK:           OpStore %17 %15
+         %21 = OpAccessChain %_ptr_Output_v4float %oVert %int_1
+               OpStore %21 %20
+; CHECK-NOT:       OpStore %21 %20
+         %25 = OpAccessChain %_ptr_Output_v4float %oVert %int_2 %int_2
+               OpStore %25 %24
+; CHECK-NOT:       OpStore %25 %24
+         %29 = OpAccessChain %_ptr_Output_v4float %oVert %int_3 %int_1
+               OpStore %29 %28
+; CHECK:           OpStore %29 %28
+         %33 = OpAccessChain %_ptr_Output_v4float %oVert %int_4 %int_0
+               OpStore %33 %32
+; CHECK-NOT:       OpStore %33 %32
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  live_inputs.insert(2);
+  live_inputs.insert(8);
+  live_inputs.insert(9);
+  live_inputs.insert(10);
+  live_inputs.insert(11);
+  SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
+                                                       &live_builtins);
+}
+
+TEST_F(ElimDeadOutputStoresTest, VertMemberLocs) {
+  // #version 450
+  //
+  // out Vertex
+  // {
+  //     layout (location = 1) vec4 Cd;
+  //     layout (location = 0) vec2 uv;
+  // } oVert;
+  //
+  // layout (location  = 0) in vec3 P;
+  //
+  // void main()
+  // {
+  //     oVert.uv = vec2(0.1, 0.7);
+  //     oVert.Cd = vec4(1, 0.5, 0, 1);
+  //     gl_Position = vec4(P, 1);
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %oVert %_ %P
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "Cd"
+               OpMemberName %Vertex 1 "uv"
+               OpName %oVert "oVert"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpMemberName %gl_PerVertex 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+               OpName %_ ""
+               OpName %P "P"
+               OpMemberDecorate %Vertex 0 Location 1
+               OpMemberDecorate %Vertex 1 Location 0
+               OpDecorate %Vertex Block
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex Block
+               OpDecorate %P Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+    %v2float = OpTypeVector %float 2
+     %Vertex = OpTypeStruct %v4float %v2float
+%_ptr_Output_Vertex = OpTypePointer Output %Vertex
+      %oVert = OpVariable %_ptr_Output_Vertex Output
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%float_0_100000001 = OpConstant %float 0.100000001
+%float_0_699999988 = OpConstant %float 0.699999988
+         %16 = OpConstantComposite %v2float %float_0_100000001 %float_0_699999988
+%_ptr_Output_v2float = OpTypePointer Output %v2float
+      %int_0 = OpConstant %int 0
+    %float_1 = OpConstant %float 1
+  %float_0_5 = OpConstant %float 0.5
+    %float_0 = OpConstant %float 0
+         %23 = OpConstantComposite %v4float %float_1 %float_0_5 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+          %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+    %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+          %P = OpVariable %_ptr_Input_v3float Input
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %18 = OpAccessChain %_ptr_Output_v2float %oVert %int_1
+               OpStore %18 %16
+; CHECK-NOT:       OpStore %18 %16
+         %25 = OpAccessChain %_ptr_Output_v4float %oVert %int_0
+               OpStore %25 %23
+; CHECK:           OpStore %25 %23
+         %35 = OpLoad %v3float %P
+         %36 = OpCompositeExtract %float %35 0
+         %37 = OpCompositeExtract %float %35 1
+         %38 = OpCompositeExtract %float %35 2
+         %39 = OpCompositeConstruct %v4float %36 %37 %38 %float_1
+         %40 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %40 %39
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  live_inputs.insert(1);
+  SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
+                                                       &live_builtins);
+}
+
+TEST_F(ElimDeadOutputStoresTest, ArrayedOutput) {
+  // Tests elimination of arrayed output as seen in Tesc shaders.
+  //
+  // #version 450
+  //
+  // layout (vertices = 4) out;
+  //
+  // layout (location = 0) in vec3 N[];
+  // layout (location = 1) in vec3 P[];
+  //
+  // layout (location = 5) out Vertex
+  // {
+  //                 vec4 c;
+  //                 vec3 n;
+  //                 vec3 f[10];
+  // } oVert[];
+  //
+  // void main()
+  // {
+  //                 oVert[gl_InvocationID].c = vec4(1, 0, 0, 1);
+  //                 oVert[gl_InvocationID].n = N[gl_InvocationID];
+  //                 oVert[gl_InvocationID].f[3] = vec3(0, 1, 0);
+  //                 vec4 worldSpacePos = vec4(P[gl_InvocationID], 1);
+  //                 gl_out[gl_InvocationID].gl_Position = worldSpacePos;
+  // }
+  const std::string text = R"(
+               OpCapability Tessellation
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TessellationControl %main "main" %oVert %gl_InvocationID %N %P %gl_out
+               OpExecutionMode %main OutputVertices 4
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "c"
+               OpMemberName %Vertex 1 "n"
+               OpMemberName %Vertex 2 "f"
+               OpName %oVert "oVert"
+               OpName %gl_InvocationID "gl_InvocationID"
+               OpName %N "N"
+               OpName %P "P"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpMemberName %gl_PerVertex 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+               OpName %gl_out "gl_out"
+               OpDecorate %Vertex Block
+               OpDecorate %oVert Location 5
+               OpDecorate %gl_InvocationID BuiltIn InvocationId
+               OpDecorate %N Location 0
+               OpDecorate %P Location 1
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex Block
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+    %v3float = OpTypeVector %float 3
+       %uint = OpTypeInt 32 0
+    %uint_10 = OpConstant %uint 10
+%_arr_v3float_uint_10 = OpTypeArray %v3float %uint_10
+     %Vertex = OpTypeStruct %v4float %v3float %_arr_v3float_uint_10
+     %uint_4 = OpConstant %uint 4
+%_arr_Vertex_uint_4 = OpTypeArray %Vertex %uint_4
+%_ptr_Output__arr_Vertex_uint_4 = OpTypePointer Output %_arr_Vertex_uint_4
+      %oVert = OpVariable %_ptr_Output__arr_Vertex_uint_4 Output
+        %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_InvocationID = OpVariable %_ptr_Input_int Input
+      %int_0 = OpConstant %int 0
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %24 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %int_1 = OpConstant %int 1
+    %uint_32 = OpConstant %uint 32
+%_arr_v3float_uint_32 = OpTypeArray %v3float %uint_32
+%_ptr_Input__arr_v3float_uint_32 = OpTypePointer Input %_arr_v3float_uint_32
+          %N = OpVariable %_ptr_Input__arr_v3float_uint_32 Input
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+%_ptr_Output_v3float = OpTypePointer Output %v3float
+      %int_2 = OpConstant %int 2
+      %int_3 = OpConstant %int 3
+         %42 = OpConstantComposite %v3float %float_0 %float_1 %float_0
+          %P = OpVariable %_ptr_Input__arr_v3float_uint_32 Input
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_arr_gl_PerVertex_uint_4 = OpTypeArray %gl_PerVertex %uint_4
+%_ptr_Output__arr_gl_PerVertex_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_uint_4
+     %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_uint_4 Output
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %20 = OpLoad %int %gl_InvocationID
+         %26 = OpAccessChain %_ptr_Output_v4float %oVert %20 %int_0
+               OpStore %26 %24
+; CHECK:           OpStore %26 %24
+         %35 = OpAccessChain %_ptr_Input_v3float %N %20
+         %36 = OpLoad %v3float %35
+         %38 = OpAccessChain %_ptr_Output_v3float %oVert %20 %int_1
+               OpStore %38 %36
+; CHECK-NOT:       OpStore %38 %36
+         %43 = OpAccessChain %_ptr_Output_v3float %oVert %20 %int_2 %int_3
+               OpStore %43 %42
+; CHECK:           OpStore %43 %42
+         %48 = OpAccessChain %_ptr_Input_v3float %P %20
+         %49 = OpLoad %v3float %48
+         %50 = OpCompositeExtract %float %49 0
+         %51 = OpCompositeExtract %float %49 1
+         %52 = OpCompositeExtract %float %49 2
+         %53 = OpCompositeConstruct %v4float %50 %51 %52 %float_1
+         %62 = OpAccessChain %_ptr_Output_v4float %gl_out %20 %int_0
+               OpStore %62 %53
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  live_inputs.insert(5);
+  live_inputs.insert(10);
+  SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
+                                                       &live_builtins);
+}
+
+TEST_F(ElimDeadOutputStoresTest, ArrayedOutputMemberLocs) {
+  // Tests elimination of member location with arrayed output as seen in
+  // Tesc shaders.
+  //
+  // #version 450
+  //
+  // layout (vertices = 4) out;
+  //
+  // layout (location = 0) in vec3 N[];
+  // layout (location = 1) in vec3 P[];
+  //
+  // out Vertex
+  // {
+  //                 layout (location = 1) vec4 c;
+  //                 layout (location = 3) vec3 n;
+  //                 layout (location = 5) vec3 f[10];
+  // } oVert[];
+  //
+  // void main()
+  // {
+  //                 oVert[gl_InvocationID].c = vec4(1, 0, 0, 1);
+  //                 oVert[gl_InvocationID].n = N[gl_InvocationID];
+  //                 oVert[gl_InvocationID].f[3] = vec3(0, 1, 0);
+  //                 vec4 worldSpacePos = vec4(P[gl_InvocationID], 1);
+  //                 gl_out[gl_InvocationID].gl_Position = worldSpacePos;
+  // }
+  const std::string text = R"(
+               OpCapability Tessellation
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TessellationControl %main "main" %oVert %gl_InvocationID %N %P %gl_out
+               OpExecutionMode %main OutputVertices 4
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "c"
+               OpMemberName %Vertex 1 "n"
+               OpMemberName %Vertex 2 "f"
+               OpName %oVert "oVert"
+               OpName %gl_InvocationID "gl_InvocationID"
+               OpName %N "N"
+               OpName %P "P"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpMemberName %gl_PerVertex 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+               OpName %gl_out "gl_out"
+               OpMemberDecorate %Vertex 0 Location 1
+               OpMemberDecorate %Vertex 1 Location 3
+               OpMemberDecorate %Vertex 2 Location 5
+               OpDecorate %Vertex Block
+               OpDecorate %gl_InvocationID BuiltIn InvocationId
+               OpDecorate %N Location 0
+               OpDecorate %P Location 1
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex Block
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+    %v3float = OpTypeVector %float 3
+       %uint = OpTypeInt 32 0
+    %uint_10 = OpConstant %uint 10
+%_arr_v3float_uint_10 = OpTypeArray %v3float %uint_10
+     %Vertex = OpTypeStruct %v4float %v3float %_arr_v3float_uint_10
+     %uint_4 = OpConstant %uint 4
+%_arr_Vertex_uint_4 = OpTypeArray %Vertex %uint_4
+%_ptr_Output__arr_Vertex_uint_4 = OpTypePointer Output %_arr_Vertex_uint_4
+      %oVert = OpVariable %_ptr_Output__arr_Vertex_uint_4 Output
+        %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_InvocationID = OpVariable %_ptr_Input_int Input
+      %int_0 = OpConstant %int 0
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %24 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %int_1 = OpConstant %int 1
+    %uint_32 = OpConstant %uint 32
+%_arr_v3float_uint_32 = OpTypeArray %v3float %uint_32
+%_ptr_Input__arr_v3float_uint_32 = OpTypePointer Input %_arr_v3float_uint_32
+          %N = OpVariable %_ptr_Input__arr_v3float_uint_32 Input
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+%_ptr_Output_v3float = OpTypePointer Output %v3float
+      %int_2 = OpConstant %int 2
+      %int_3 = OpConstant %int 3
+         %42 = OpConstantComposite %v3float %float_0 %float_1 %float_0
+          %P = OpVariable %_ptr_Input__arr_v3float_uint_32 Input
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_arr_gl_PerVertex_uint_4 = OpTypeArray %gl_PerVertex %uint_4
+%_ptr_Output__arr_gl_PerVertex_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_uint_4
+     %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_uint_4 Output
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %20 = OpLoad %int %gl_InvocationID
+         %26 = OpAccessChain %_ptr_Output_v4float %oVert %20 %int_0
+               OpStore %26 %24
+;CHECK:            OpStore %26 %24
+         %35 = OpAccessChain %_ptr_Input_v3float %N %20
+         %36 = OpLoad %v3float %35
+         %38 = OpAccessChain %_ptr_Output_v3float %oVert %20 %int_1
+               OpStore %38 %36
+;CHECK-NOT:        OpStore %38 %36
+         %43 = OpAccessChain %_ptr_Output_v3float %oVert %20 %int_2 %int_3
+               OpStore %43 %42
+;CHECK:            OpStore %43 %42
+         %48 = OpAccessChain %_ptr_Input_v3float %P %20
+         %49 = OpLoad %v3float %48
+         %50 = OpCompositeExtract %float %49 0
+         %51 = OpCompositeExtract %float %49 1
+         %52 = OpCompositeExtract %float %49 2
+         %53 = OpCompositeConstruct %v4float %50 %51 %52 %float_1
+         %62 = OpAccessChain %_ptr_Output_v4float %gl_out %20 %int_0
+               OpStore %62 %53
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  live_inputs.insert(1);
+  live_inputs.insert(8);
+  SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
+                                                       &live_builtins);
+}
+
+TEST_F(ElimDeadOutputStoresTest, ScalarBuiltins) {
+  // Tests elimination of scalar builtins as seen in vert shaders.
+  //
+  // #version 460
+  //
+  // layout (location = 0) in vec3 P;
+  //
+  // void main()
+  // {
+  //         gl_Position = vec4(P, 1.0);
+  //         gl_PointSize = 1.0;
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %_ %P
+               OpSource GLSL 460
+               OpName %main "main"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpMemberName %gl_PerVertex 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+               OpName %_ ""
+               OpName %P "P"
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex Block
+               OpDecorate %P Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+          %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+    %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+          %P = OpVariable %_ptr_Input_v3float Input
+    %float_1 = OpConstant %float 1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %int_1 = OpConstant %int 1
+%_ptr_Output_float = OpTypePointer Output %float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpLoad %v3float %P
+         %21 = OpCompositeExtract %float %19 0
+         %22 = OpCompositeExtract %float %19 1
+         %23 = OpCompositeExtract %float %19 2
+         %24 = OpCompositeConstruct %v4float %21 %22 %23 %float_1
+         %26 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %26 %24
+;CHECK:                   OpStore %26 %24
+         %29 = OpAccessChain %_ptr_Output_float %_ %int_1
+               OpStore %29 %float_1
+;CHECK-NOT:               OpStore %29 %float_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  // Omit spv::BuiltIn::PointSize
+  live_builtins.insert((uint32_t)spv::BuiltIn::ClipDistance);
+  live_builtins.insert((uint32_t)spv::BuiltIn::CullDistance);
+  SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
+                                                       &live_builtins);
+}
+
+TEST_F(ElimDeadOutputStoresTest, ArrayedBuiltins) {
+  // Tests elimination of arrayed builtins as seen in geom, tesc, and tese
+  // shaders.
+  //
+  // #version 460
+  //
+  // layout(triangle_strip, max_vertices = 3) out;
+  // layout(triangles) in;
+  //
+  // void main()
+  // {
+  //         for (int i = 0; i < 3; i++)
+  //         {
+  //                 gl_Position = gl_in[i].gl_Position;
+  //                 gl_PointSize = gl_in[i].gl_PointSize;
+  //
+  //                 EmitVertex();
+  //         }
+  //
+  //         EndPrimitive();
+  // }
+  const std::string text = R"(
+               OpCapability Geometry
+               OpCapability GeometryPointSize
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Geometry %main "main" %_ %gl_in
+               OpExecutionMode %main Triangles
+               OpExecutionMode %main Invocations 1
+               OpExecutionMode %main OutputTriangleStrip
+               OpExecutionMode %main OutputVertices 3
+               OpSource GLSL 460
+               OpName %main "main"
+               OpName %i "i"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpMemberName %gl_PerVertex 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+               OpName %_ ""
+               OpName %gl_PerVertex_0 "gl_PerVertex"
+               OpMemberName %gl_PerVertex_0 0 "gl_Position"
+               OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
+               OpName %gl_in "gl_in"
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex Block
+               OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex_0 Block
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+      %int_0 = OpConstant %int 0
+      %int_3 = OpConstant %int 3
+       %bool = OpTypeBool
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+          %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+     %uint_3 = OpConstant %uint 3
+%_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
+%_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
+      %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %int_1 = OpConstant %int 1
+%_ptr_Input_float = OpTypePointer Input %float
+%_ptr_Output_float = OpTypePointer Output %float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+          %i = OpVariable %_ptr_Function_int Function
+               OpStore %i %int_0
+               OpBranch %10
+         %10 = OpLabel
+               OpLoopMerge %12 %13 None
+               OpBranch %14
+         %14 = OpLabel
+         %15 = OpLoad %int %i
+         %18 = OpSLessThan %bool %15 %int_3
+               OpBranchConditional %18 %11 %12
+         %11 = OpLabel
+         %32 = OpLoad %int %i
+         %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
+         %35 = OpLoad %v4float %34
+         %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %37 %35
+;CHECK:                   OpStore %37 %35
+         %39 = OpLoad %int %i
+         %41 = OpAccessChain %_ptr_Input_float %gl_in %39 %int_1
+         %42 = OpLoad %float %41
+         %44 = OpAccessChain %_ptr_Output_float %_ %int_1
+               OpStore %44 %42
+;CHECK-NOT:               OpStore %44 %42
+               OpEmitVertex
+               OpBranch %13
+         %13 = OpLabel
+         %45 = OpLoad %int %i
+         %46 = OpIAdd %int %45 %int_1
+               OpStore %i %46
+               OpBranch %10
+         %12 = OpLabel
+               OpEndPrimitive
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  // Omit spv::BuiltIn::PointSize
+  live_builtins.insert((uint32_t)spv::BuiltIn::ClipDistance);
+  live_builtins.insert((uint32_t)spv::BuiltIn::CullDistance);
+  SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
+                                                       &live_builtins);
+}
+
+TEST_F(ElimDeadOutputStoresTest, ArrayedOutputPatchLocs) {
+  // Tests elimination of location with arrayed patch output as seen in
+  // Tesc shaders.
+  //
+  // #version 450 core
+  //
+  // layout(vertices = 4) out;
+  //
+  // layout(location=0) patch out float patchOut0[2];
+  // layout(location=2) patch out float patchOut1[2];
+  //
+  // void main()
+  // {
+  //     patchOut0[1] = 0.0;  // Dead loc 1
+  //     patchOut1[1] = 1.0;  // Live loc 3
+  // }
+  const std::string text = R"(
+               OpCapability Tessellation
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TessellationControl %main "main" %patchOut0 %patchOut1
+               OpExecutionMode %main OutputVertices 4
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %patchOut0 "patchOut0"
+               OpName %patchOut1 "patchOut1"
+               OpDecorate %patchOut0 Patch
+               OpDecorate %patchOut0 Location 0
+               OpDecorate %patchOut1 Patch
+               OpDecorate %patchOut1 Location 2
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_2 = OpConstant %uint 2
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2
+  %patchOut0 = OpVariable %_ptr_Output__arr_float_uint_2 Output
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+    %float_0 = OpConstant %float 0
+%_ptr_Output_float = OpTypePointer Output %float
+  %patchOut1 = OpVariable %_ptr_Output__arr_float_uint_2 Output
+    %float_1 = OpConstant %float 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %16 = OpAccessChain %_ptr_Output_float %patchOut0 %int_1
+               OpStore %16 %float_0
+;CHECK-NOT:               OpStore %16 %float_0
+         %19 = OpAccessChain %_ptr_Output_float %patchOut1 %int_1
+               OpStore %19 %float_1
+;CHECK:                   OpStore %19 %float_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  live_inputs.insert(3);
+  SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
+                                                       &live_builtins);
+}
+
+TEST_F(ElimDeadOutputStoresTest, VertMultipleLocationsF16) {
+  // #version 450
+  //
+  // layout(location = 2) out Vertex
+  // {
+  //         f16vec4 color0;
+  //         f16vec4 color1;
+  //         f16vec4 color2[3];
+  // } oVert;
+  //
+  // void main()
+  // {
+  //     oVert.color0 = f16vec4(0.0,0.0,0.0,0.0);
+  //     oVert.color1 = f16vec4(0.1,0.0,0.0,0.0);
+  //     oVert.color2[0] = f16vec4(0.2,0.0,0.0,0.0);
+  //     oVert.color2[1] = f16vec4(0.3,0.0,0.0,0.0);
+  //     oVert.color2[2] = f16vec4(0.4,0.0,0.0,0.0);
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+               OpCapability Float16
+               OpCapability StorageInputOutput16
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %oVert
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %Vertex "Vertex"
+               OpMemberName %Vertex 0 "color0"
+               OpMemberName %Vertex 1 "color1"
+               OpMemberName %Vertex 2 "color2"
+               OpName %oVert "oVert"
+               OpDecorate %Vertex Block
+               OpDecorate %oVert Location 2
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %half = OpTypeFloat 32
+    %v4half = OpTypeVector %half 4
+       %uint = OpTypeInt 32 0
+     %uint_3 = OpConstant %uint 3
+%_arr_v4half_uint_3 = OpTypeArray %v4half %uint_3
+     %Vertex = OpTypeStruct %v4half %v4half %_arr_v4half_uint_3
+%_ptr_Output_Vertex = OpTypePointer Output %Vertex
+      %oVert = OpVariable %_ptr_Output_Vertex Output
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+    %half_0 = OpConstant %half 0
+         %17 = OpConstantComposite %v4half %half_0 %half_0 %half_0 %half_0
+%_ptr_Output_v4half = OpTypePointer Output %v4half
+      %int_1 = OpConstant %int 1
+%half_0_100000001 = OpConstant %half 0.100000001
+         %22 = OpConstantComposite %v4half %half_0_100000001 %half_0 %half_0 %half_0
+      %int_2 = OpConstant %int 2
+%half_0_200000003 = OpConstant %half 0.200000003
+         %26 = OpConstantComposite %v4half %half_0_200000003 %half_0 %half_0 %half_0
+%half_0_300000012 = OpConstant %half 0.300000012
+         %29 = OpConstantComposite %v4half %half_0_300000012 %half_0 %half_0 %half_0
+%half_0_400000006 = OpConstant %half 0.400000006
+         %32 = OpConstantComposite %v4half %half_0_400000006 %half_0 %half_0 %half_0
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpAccessChain %_ptr_Output_v4half %oVert %int_0
+               OpStore %19 %17
+;CHECK:            OpStore %19 %17
+         %23 = OpAccessChain %_ptr_Output_v4half %oVert %int_1
+               OpStore %23 %22
+;CHECK-NOT:        OpStore %23 %22
+         %27 = OpAccessChain %_ptr_Output_v4half %oVert %int_2 %int_0
+               OpStore %27 %26
+;CHECK-NOT:        OpStore %27 %26
+         %30 = OpAccessChain %_ptr_Output_v4half %oVert %int_2 %int_1
+               OpStore %30 %29
+;CHECK:            OpStore %30 %29
+         %33 = OpAccessChain %_ptr_Output_v4half %oVert %int_2 %int_2
+               OpStore %33 %32
+;CHECK-NOT:        OpStore %33 %32
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_3);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  std::unordered_set<uint32_t> live_inputs;
+  std::unordered_set<uint32_t> live_builtins;
+  live_inputs.insert(2);
+  live_inputs.insert(5);
+  SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
+                                                       &live_builtins);
+}
+
+}  // namespace
+}  // namespace opt
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/feature_manager_test.cpp b/third_party/SPIRV-Tools/test/opt/feature_manager_test.cpp
index 767376c..94c7734 100644
--- a/third_party/SPIRV-Tools/test/opt/feature_manager_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/feature_manager_test.cpp
@@ -100,8 +100,10 @@
       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
   ASSERT_NE(context, nullptr);
 
-  EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityShader));
-  EXPECT_FALSE(context->get_feature_mgr()->HasCapability(SpvCapabilityKernel));
+  EXPECT_TRUE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Shader));
+  EXPECT_FALSE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Kernel));
 }
 
 TEST_F(FeatureManagerTest, ExplicitlyPresent2) {
@@ -114,8 +116,10 @@
       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
   ASSERT_NE(context, nullptr);
 
-  EXPECT_FALSE(context->get_feature_mgr()->HasCapability(SpvCapabilityShader));
-  EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityKernel));
+  EXPECT_FALSE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Shader));
+  EXPECT_TRUE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Kernel));
 }
 
 TEST_F(FeatureManagerTest, ImplicitlyPresent) {
@@ -131,10 +135,13 @@
   // Check multiple levels of indirection.  Tessellation implies Shader, which
   // implies Matrix.
   EXPECT_TRUE(
-      context->get_feature_mgr()->HasCapability(SpvCapabilityTessellation));
-  EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityShader));
-  EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityMatrix));
-  EXPECT_FALSE(context->get_feature_mgr()->HasCapability(SpvCapabilityKernel));
+      context->get_feature_mgr()->HasCapability(spv::Capability::Tessellation));
+  EXPECT_TRUE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Shader));
+  EXPECT_TRUE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Matrix));
+  EXPECT_FALSE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Kernel));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/opt/fold_spec_const_op_composite_test.cpp b/third_party/SPIRV-Tools/test/opt/fold_spec_const_op_composite_test.cpp
index 7eddf7e..e2374c5 100644
--- a/third_party/SPIRV-Tools/test/opt/fold_spec_const_op_composite_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/fold_spec_const_op_composite_test.cpp
@@ -105,6 +105,275 @@
       builder.GetCode(), builder.GetCode(), /* skip_nop = */ true);
 }
 
+// Test where OpSpecConstantOp depends on another OpSpecConstantOp with
+// CompositeExtract
+TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedCompositeExtract) {
+  AssemblyBuilder builder;
+  builder.AppendTypesConstantsGlobals({
+      // clang-format off
+    "%uint = OpTypeInt 32 0",
+    "%v3uint = OpTypeVector %uint 3",
+    "%uint_2 = OpConstant %uint 2",
+    "%uint_3 = OpConstant %uint 3",
+    // Folding target:
+    "%composite_0 = OpSpecConstantComposite %v3uint %uint_2 %uint_3 %uint_2",
+    "%op_0 = OpSpecConstantOp %uint CompositeExtract %composite_0 0",
+    "%op_1 = OpSpecConstantOp %uint CompositeExtract %composite_0 1",
+    "%op_2 = OpSpecConstantOp %uint IMul %op_0 %op_1",
+    "%composite_1 = OpSpecConstantComposite %v3uint %op_0 %op_1 %op_2",
+    "%op_3 = OpSpecConstantOp %uint CompositeExtract %composite_1 0",
+    "%op_4 = OpSpecConstantOp %uint IMul %op_2 %op_3",
+      // clang-format on
+  });
+
+  std::vector<const char*> expected = {
+      // clang-format off
+        "OpCapability Shader",
+        "OpCapability Float64",
+    "%1 = OpExtInstImport \"GLSL.std.450\"",
+        "OpMemoryModel Logical GLSL450",
+        "OpEntryPoint Vertex %main \"main\"",
+        "OpName %void \"void\"",
+        "OpName %main_func_type \"main_func_type\"",
+        "OpName %main \"main\"",
+        "OpName %main_func_entry_block \"main_func_entry_block\"",
+        "OpName %uint \"uint\"",
+        "OpName %v3uint \"v3uint\"",
+        "OpName %uint_2 \"uint_2\"",
+        "OpName %uint_3 \"uint_3\"",
+        "OpName %composite_0 \"composite_0\"",
+        "OpName %op_0 \"op_0\"",
+        "OpName %op_1 \"op_1\"",
+        "OpName %op_2 \"op_2\"",
+        "OpName %composite_1 \"composite_1\"",
+        "OpName %op_3 \"op_3\"",
+        "OpName %op_4 \"op_4\"",
+    "%void = OpTypeVoid",
+"%main_func_type = OpTypeFunction %void",
+    "%uint = OpTypeInt 32 0",
+  "%v3uint = OpTypeVector %uint 3",
+  "%uint_2 = OpConstant %uint 2",
+  "%uint_3 = OpConstant %uint 3",
+"%composite_0 = OpConstantComposite %v3uint %uint_2 %uint_3 %uint_2",
+    "%op_0 = OpConstant %uint 2",
+    "%op_1 = OpConstant %uint 3",
+    "%op_2 = OpConstant %uint 6",
+"%composite_1 = OpConstantComposite %v3uint %op_0 %op_1 %op_2",
+"%op_3 = OpConstant %uint 2",
+ "%op_4 = OpConstant %uint 12",
+    "%main = OpFunction %void None %main_func_type",
+"%main_func_entry_block = OpLabel",
+            "OpReturn",
+            "OpFunctionEnd",
+      // clang-format on
+  };
+  SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
+      builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
+}
+
+// Test where OpSpecConstantOp depends on another OpSpecConstantOp with
+// VectorShuffle
+TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedVectorShuffle) {
+  AssemblyBuilder builder;
+  builder.AppendTypesConstantsGlobals({
+      // clang-format off
+    "%uint = OpTypeInt 32 0",
+    "%v3uint = OpTypeVector %uint 3",
+    "%uint_1 = OpConstant %uint 1",
+    "%uint_2 = OpConstant %uint 2",
+    "%uint_3 = OpConstant %uint 3",
+    "%uint_4 = OpConstant %uint 4",
+    "%uint_5 = OpConstant %uint 5",
+    "%uint_6 = OpConstant %uint 6",
+    // Folding target:
+    "%composite_0 = OpSpecConstantComposite %v3uint %uint_1 %uint_2 %uint_3",
+    "%composite_1 = OpSpecConstantComposite %v3uint %uint_4 %uint_5 %uint_6",
+    "%vecshuffle = OpSpecConstantOp %v3uint VectorShuffle %composite_0 %composite_1 0 5 3",
+    "%op = OpSpecConstantOp %uint CompositeExtract %vecshuffle 1",
+      // clang-format on
+  });
+
+  std::vector<const char*> expected = {
+      // clang-format off
+        "OpCapability Shader",
+        "OpCapability Float64",
+        "%1 = OpExtInstImport \"GLSL.std.450\"",
+        "OpMemoryModel Logical GLSL450",
+        "OpEntryPoint Vertex %main \"main\"",
+        "OpName %void \"void\"",
+        "OpName %main_func_type \"main_func_type\"",
+        "OpName %main \"main\"",
+        "OpName %main_func_entry_block \"main_func_entry_block\"",
+        "OpName %uint \"uint\"",
+        "OpName %v3uint \"v3uint\"",
+        "OpName %uint_1 \"uint_1\"",
+        "OpName %uint_2 \"uint_2\"",
+        "OpName %uint_3 \"uint_3\"",
+        "OpName %uint_4 \"uint_4\"",
+        "OpName %uint_5 \"uint_5\"",
+        "OpName %uint_6 \"uint_6\"",
+        "OpName %composite_0 \"composite_0\"",
+        "OpName %composite_1 \"composite_1\"",
+        "OpName %vecshuffle \"vecshuffle\"",
+        "OpName %op \"op\"",
+    "%void = OpTypeVoid",
+"%main_func_type = OpTypeFunction %void",
+    "%uint = OpTypeInt 32 0",
+  "%v3uint = OpTypeVector %uint 3",
+  "%uint_1 = OpConstant %uint 1",
+  "%uint_2 = OpConstant %uint 2",
+  "%uint_3 = OpConstant %uint 3",
+  "%uint_4 = OpConstant %uint 4",
+  "%uint_5 = OpConstant %uint 5",
+  "%uint_6 = OpConstant %uint 6",
+"%composite_0 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3",
+"%composite_1 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6",
+"%vecshuffle = OpConstantComposite %v3uint %uint_1 %uint_6 %uint_4",
+      "%op = OpConstant %uint 6",
+    "%main = OpFunction %void None %main_func_type",
+"%main_func_entry_block = OpLabel",
+        "OpReturn",
+        "OpFunctionEnd",
+      // clang-format on
+  };
+  SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
+      builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
+}
+
+// Test CompositeExtract with matrix
+TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeExtractMaxtrix) {
+  AssemblyBuilder builder;
+  builder.AppendTypesConstantsGlobals({
+      // clang-format off
+    "%uint = OpTypeInt 32 0",
+    "%v3uint = OpTypeVector %uint 3",
+    "%mat3x3 = OpTypeMatrix %v3uint 3",
+    "%uint_1 = OpConstant %uint 1",
+    "%uint_2 = OpConstant %uint 2",
+    "%uint_3 = OpConstant %uint 3",
+    // Folding target:
+    "%a = OpSpecConstantComposite %v3uint %uint_1 %uint_1 %uint_1",
+    "%b = OpSpecConstantComposite %v3uint %uint_1 %uint_1 %uint_3",
+    "%c = OpSpecConstantComposite %v3uint %uint_1 %uint_2 %uint_1",
+    "%op = OpSpecConstantComposite %mat3x3 %a %b %c",
+    "%x = OpSpecConstantOp %uint CompositeExtract %op 2 1",
+    "%y = OpSpecConstantOp %uint CompositeExtract %op 1 2",
+      // clang-format on
+  });
+
+  std::vector<const char*> expected = {
+      // clang-format off
+        "OpCapability Shader",
+        "OpCapability Float64",
+   "%1 = OpExtInstImport \"GLSL.std.450\"",
+        "OpMemoryModel Logical GLSL450",
+        "OpEntryPoint Vertex %main \"main\"",
+        "OpName %void \"void\"",
+        "OpName %main_func_type \"main_func_type\"",
+        "OpName %main \"main\"",
+        "OpName %main_func_entry_block \"main_func_entry_block\"",
+        "OpName %uint \"uint\"",
+        "OpName %v3uint \"v3uint\"",
+        "OpName %mat3x3 \"mat3x3\"",
+        "OpName %uint_1 \"uint_1\"",
+        "OpName %uint_2 \"uint_2\"",
+        "OpName %uint_3 \"uint_3\"",
+        "OpName %a \"a\"",
+        "OpName %b \"b\"",
+        "OpName %c \"c\"",
+        "OpName %op \"op\"",
+        "OpName %x \"x\"",
+        "OpName %y \"y\"",
+    "%void = OpTypeVoid",
+"%main_func_type = OpTypeFunction %void",
+    "%uint = OpTypeInt 32 0",
+  "%v3uint = OpTypeVector %uint 3",
+  "%mat3x3 = OpTypeMatrix %v3uint 3",
+  "%uint_1 = OpConstant %uint 1",
+  "%uint_2 = OpConstant %uint 2",
+  "%uint_3 = OpConstant %uint 3",
+       "%a = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1",
+       "%b = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_3",
+       "%c = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_1",
+      "%op = OpConstantComposite %mat3x3 %a %b %c",
+       "%x = OpConstant %uint 2",
+       "%y = OpConstant %uint 3",
+    "%main = OpFunction %void None %main_func_type",
+"%main_func_entry_block = OpLabel",
+        "OpReturn",
+        "OpFunctionEnd",
+      // clang-format on
+  };
+  SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
+      builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
+}
+
+TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVector) {
+  const std::string test =
+      R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %1 "main"
+               OpExecutionMode %1 LocalSize 1 1 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+          %8 = OpConstantNull %uint
+          %9 = OpSpecConstantComposite %v3uint %uint_2 %uint_2 %uint_2
+ ; CHECK: %15 = OpConstantComposite %v3uint %uint_3 %uint_2 %uint_2
+ ; CHECK: %uint_3_0 = OpConstant %uint 3
+ ; CHECK: %17 = OpConstantComposite %v3uint %8 %uint_2 %uint_2
+ ; CHECK: %18 = OpConstantNull %uint
+         %10 = OpSpecConstantOp %v3uint CompositeInsert %uint_3 %9 0
+         %11 = OpSpecConstantOp %uint CompositeExtract %10 0
+         %12 = OpSpecConstantOp %v3uint CompositeInsert %8 %9 0
+         %13 = OpSpecConstantOp %uint CompositeExtract %12 0
+          %1 = OpFunction %void None %3
+         %14 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
+}
+
+TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertMatrix) {
+  const std::string test =
+      R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %1 "main"
+               OpExecutionMode %1 LocalSize 1 1 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v3float = OpTypeVector %float 3
+%mat3v3float = OpTypeMatrix %v3float 3
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+          %9 = OpSpecConstantComposite %v3float %float_1 %float_1 %float_1
+         %10 = OpSpecConstantComposite %v3float %float_1 %float_1 %float_1
+         %11 = OpSpecConstantComposite %v3float %float_1 %float_2 %float_1
+         %12 = OpSpecConstantComposite %mat3v3float %9 %10 %11
+ ; CHECK: %float_2_0 = OpConstant %float 2
+ ; CHECK: %18 = OpConstantComposite %v3float %float_1 %float_1 %float_2
+ ; CHECK: %19 = OpConstantComposite %mat3v3float %9 %18 %11
+ ; CHECK: %float_2_1 = OpConstant %float 2
+         %13 = OpSpecConstantOp %float CompositeExtract %12 2 1
+         %14 = OpSpecConstantOp %mat3v3float CompositeInsert %13 %12 1 2
+         %15 = OpSpecConstantOp %float CompositeExtract %14 1 2
+          %1 = OpFunction %void None %3
+         %16 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
+}
+
 // All types and some common constants that are potentially required in
 // FoldSpecConstantOpAndCompositeTest.
 std::vector<std::string> CommonTypesAndConstants() {
@@ -199,7 +468,7 @@
 struct FoldSpecConstantOpAndCompositePassTestCase {
   // Original constants with unfolded spec constants.
   std::vector<std::string> original;
-  // Expected cosntants after folding.
+  // Expected constant after folding.
   std::vector<std::string> expected;
 };
 
diff --git a/third_party/SPIRV-Tools/test/opt/fold_test.cpp b/third_party/SPIRV-Tools/test/opt/fold_test.cpp
index f6c94ca..06b91f3 100644
--- a/third_party/SPIRV-Tools/test/opt/fold_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/fold_test.cpp
@@ -88,12 +88,17 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    EXPECT_EQ(inst->opcode(), SpvOpConstant);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
-    const analysis::IntConstant* result =
-        const_mrg->GetConstantFromInst(inst)->AsIntConstant();
+    const analysis::Constant* constant = const_mrg->GetConstantFromInst(inst);
+    // We expect to see either integer types or 16-bit float types here.
+    EXPECT_TRUE((constant->AsIntConstant() != nullptr) ||
+                ((constant->AsFloatConstant() != nullptr) &&
+                 (constant->type()->AsFloat()->width() == 16)));
+    const analysis::ScalarConstant* result =
+        const_mrg->GetConstantFromInst(inst)->AsScalarConstant();
     EXPECT_NE(result, nullptr);
     if (result != nullptr) {
       EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
@@ -115,6 +120,7 @@
   static const std::string header = R"(OpCapability Shader
 OpCapability Float16
 OpCapability Float64
+OpCapability Int8
 OpCapability Int16
 OpCapability Int64
 %1 = OpExtInstImport "GLSL.std.450"
@@ -134,6 +140,9 @@
 %false = OpConstantFalse %bool
 %bool_null = OpConstantNull %bool
 %short = OpTypeInt 16 1
+%ushort = OpTypeInt 16 0
+%byte = OpTypeInt 8 1
+%ubyte = OpTypeInt 8 0
 %int = OpTypeInt 32 1
 %long = OpTypeInt 64 1
 %uint = OpTypeInt 32 0
@@ -169,6 +178,8 @@
 %short_0 = OpConstant %short 0
 %short_2 = OpConstant %short 2
 %short_3 = OpConstant %short 3
+%ubyte_1 = OpConstant %ubyte 1
+%byte_n1 = OpConstant %byte -1
 %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
 %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
 %int_0 = OpConstant %int 0
@@ -302,6 +313,8 @@
 %int_0xC05FD666 = OpConstant %int 0xC05FD666
 %int_0x66666666 = OpConstant %int 0x66666666
 %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666 = OpConstantComposite %v4int %int_0x00000000 %int_0x3FF00000 %int_0x66666666 %int_0xC05FD666
+%ushort_0xBC00 = OpConstant %ushort 0xBC00
+%short_0xBC00 = OpConstant %short 0xBC00
 )";
 
   return header;
@@ -776,7 +789,95 @@
             "%2 = OpBitcast %uint %float_1\n" +
             "OpReturn\n" +
             "OpFunctionEnd",
-        2, static_cast<uint32_t>(0x3f800000))
+        2, static_cast<uint32_t>(0x3f800000)),
+    // Test case 49: Bit-cast ushort 0xBC00 to ushort
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %ushort %ushort_0xBC00\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0xBC00),
+    // Test case 50: Bit-cast short 0xBC00 to ushort
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %ushort %short_0xBC00\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0xFFFFBC00),
+    // Test case 51: Bit-cast half 1 to ushort
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %ushort %half_1\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0x3C00),
+    // Test case 52: Bit-cast ushort 0xBC00 to short
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %short %ushort_0xBC00\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0xBC00),
+    // Test case 53: Bit-cast short 0xBC00 to short
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %short %short_0xBC00\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0xFFFFBC00),
+    // Test case 54: Bit-cast half 1 to short
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %short %half_1\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0x3C00),
+    // Test case 55: Bit-cast ushort 0xBC00 to half
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %half %ushort_0xBC00\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0xBC00),
+    // Test case 56: Bit-cast short 0xBC00 to half
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %half %short_0xBC00\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0xFFFFBC00),
+    // Test case 57: Bit-cast half 1 to half
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %half %half_1\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0x3C00),
+    // Test case 58: Bit-cast ubyte 1 to byte
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %byte %ubyte_1\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 1),
+    // Test case 59: Bit-cast byte -1 to ubyte
+    InstructionFoldingCase<uint32_t>(
+        Header() + "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpBitcast %ubyte %byte_n1\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
+        2, 0xFFFFFFFF)
 ));
 // clang-format on
 
@@ -795,15 +896,15 @@
   // Fold the instruction to test.
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
-  SpvOp original_opcode = inst->opcode();
+  spv::Op original_opcode = inst->opcode();
   bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
 
   // Make sure the instruction folded as expected.
   EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
   if (succeeded && inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
+    std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
     EXPECT_THAT(opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
@@ -892,9 +993,9 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (succeeded && inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
+    std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
     EXPECT_THAT(opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
@@ -993,15 +1094,15 @@
   // Fold the instruction to test.
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
-  SpvOp original_opcode = inst->opcode();
+  spv::Op original_opcode = inst->opcode();
   bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
 
   // Make sure the instruction folded as expected.
   EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
   if (succeeded && inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
+    std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
     EXPECT_THAT(opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
@@ -1121,9 +1222,10 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
+    std::vector<spv::Op> bool_opcodes = {spv::Op::OpConstantTrue,
+                                         spv::Op::OpConstantFalse};
     EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::BoolConstant* result =
@@ -1732,9 +1834,9 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    EXPECT_EQ(inst->opcode(), SpvOpConstant);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::FloatConstant* result =
         const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
@@ -2165,9 +2267,9 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    EXPECT_EQ(inst->opcode(), SpvOpConstant);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::FloatConstant* result =
         const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
@@ -3052,7 +3154,7 @@
   // Make sure the instruction folded as expected.
   EXPECT_NE(inst, nullptr);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpConstant);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::IntConstant* result =
         const_mrg->GetConstantFromInst(inst)->AsIntConstant();
@@ -3100,7 +3202,8 @@
   // Make sure the instruction folded as expected.
   EXPECT_NE(inst, nullptr);
   if (inst != nullptr) {
-    std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
+    std::vector<spv::Op> bool_opcodes = {spv::Op::OpConstantTrue,
+                                         spv::Op::OpConstantFalse};
     EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::BoolConstant* result =
@@ -3152,7 +3255,7 @@
   EXPECT_EQ(inst->type_id(), original_inst->type_id());
   EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
   if (succeeded) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
   } else {
     EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
@@ -4810,7 +4913,7 @@
   EXPECT_EQ(inst->type_id(), original_inst->type_id());
   EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
   if (succeeded) {
-    EXPECT_EQ(inst->opcode(), SpvOpFNegate);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpFNegate);
     EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
   } else {
     EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
@@ -7963,6 +8066,27 @@
             "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
             "OpReturn\n" +
             "OpFunctionEnd",
+        9, true),
+    // Test case 14: Shuffle with undef literal and change size of first input vector.
+    InstructionFoldingCase<bool>(
+        Header() +
+            "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
+            "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
+            "; CHECK: OpVectorShuffle\n" +
+            "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 1 4 4294967295\n" +
+            "; CHECK: OpReturn\n" +
+            "%main = OpFunction %void None %void_func\n" +
+            "%main_lab = OpLabel\n" +
+            "%2 = OpVariable %_ptr_v4double Function\n" +
+            "%3 = OpVariable %_ptr_v4double Function\n" +
+            "%4 = OpVariable %_ptr_v4double Function\n" +
+            "%5 = OpLoad %v4double %2\n" +
+            "%6 = OpLoad %v4double %3\n" +
+            "%7 = OpLoad %v4double %4\n" +
+            "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
+            "%9 = OpVectorShuffle %v4double %8 %7 0 1 2 4294967295\n" +
+            "OpReturn\n" +
+            "OpFunctionEnd",
         9, true)
 ));
 
diff --git a/third_party/SPIRV-Tools/test/opt/function_test.cpp b/third_party/SPIRV-Tools/test/opt/function_test.cpp
index af25bac..09cca33 100644
--- a/third_party/SPIRV-Tools/test/opt/function_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/function_test.cpp
@@ -248,7 +248,7 @@
   std::unordered_set<uint32_t> non_semantic_ids;
   func->ForEachInst(
       [&non_semantic_ids](const Instruction* inst) {
-        if (inst->opcode() == SpvOpExtInst) {
+        if (inst->opcode() == spv::Op::OpExtInst) {
           non_semantic_ids.insert(inst->result_id());
         }
       },
@@ -285,7 +285,7 @@
   std::unordered_set<uint32_t> non_semantic_ids;
   func->ForEachInst(
       [&non_semantic_ids](const Instruction* inst) {
-        if (inst->opcode() == SpvOpExtInst) {
+        if (inst->opcode() == spv::Op::OpExtInst) {
           non_semantic_ids.insert(inst->result_id());
         }
       },
@@ -296,6 +296,65 @@
   EXPECT_EQ(1, non_semantic_ids.count(8));
 }
 
+TEST(FunctionTest, ReorderBlocksinStructuredOrder) {
+  // The spir-v has the basic block in a random order.  We want to reorder them
+  // in structured order.
+  const std::string text = R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %100 "PSMain"
+               OpExecutionMode %PSMain OriginUpperLeft
+               OpSource HLSL 600
+        %int = OpTypeInt 32 1
+       %void = OpTypeVoid
+         %19 = OpTypeFunction %void
+       %bool = OpTypeBool
+%undef_bool = OpUndef %bool
+%undef_int = OpUndef %int
+        %100 = OpFunction %void None %19
+          %11 = OpLabel
+               OpSelectionMerge %10 None
+               OpSwitch %undef_int %3 0 %2 10 %1
+          %2 = OpLabel
+               OpReturn
+          %7 = OpLabel
+               OpBranch %8
+          %3 = OpLabel
+               OpBranch %4
+         %10 = OpLabel
+               OpReturn
+          %9 = OpLabel
+               OpBranch %10
+          %8 = OpLabel
+               OpBranch %4
+          %4 = OpLabel
+               OpLoopMerge %9 %8 None
+               OpBranchConditional %undef_bool %5 %9
+          %1 = OpLabel
+               OpReturn
+          %6 = OpLabel
+               OpBranch %7
+          %5 = OpLabel
+               OpSelectionMerge %7 None
+               OpBranchConditional %undef_bool %6 %7
+               OpFunctionEnd
+)";
+
+  std::unique_ptr<IRContext> ctx =
+      spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                            SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  ASSERT_TRUE(ctx);
+  auto* func = spvtest::GetFunction(ctx->module(), 100);
+  ASSERT_TRUE(func);
+  func->ReorderBasicBlocksInStructuredOrder();
+
+  auto first_block = func->begin();
+  auto bb = first_block;
+  for (++bb; bb != func->end(); ++bb) {
+    EXPECT_EQ(bb->id(), (bb - first_block));
+  }
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/inline_test.cpp b/third_party/SPIRV-Tools/test/opt/inline_test.cpp
index d804f7c..1e5d9f3 100644
--- a/third_party/SPIRV-Tools/test/opt/inline_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/inline_test.cpp
@@ -1,5 +1,5 @@
-// Copyright (c) 2017 Valve Corporation
-// Copyright (c) 2017 LunarG Inc.
+// Copyright (c) 2017-2022 Valve Corporation
+// Copyright (c) 2017-2022 LunarG Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -4337,6 +4337,91 @@
   SinglePassRunAndMatch<InlineExhaustivePass>(text, true);
 }
 
+TEST_F(InlineTest, CreateDebugInlinedAtFromDebugLine) {
+  const std::string text = R"(OpCapability Shader
+; CHECK: OpExtInst %void %1 DebugInlinedAt %uint_6
+OpExtension "SPV_KHR_non_semantic_info"
+%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+%3 = OpString "debuginlinedat.frag"
+%8 = OpString "int"
+%15 = OpString "int function1() {
+	return 1;
+}
+
+void main() {
+	function1();
+}
+"
+%20 = OpString "function1"
+%21 = OpString ""
+%26 = OpString "main"
+OpName %main "main"
+OpName %src_main "src.main"
+OpName %bb_entry "bb.entry"
+OpName %function1 "function1"
+OpName %bb_entry_0 "bb.entry"
+%int = OpTypeInt 32 1
+%int_1 = OpConstant %int 1
+%uint = OpTypeInt 32 0
+%uint_32 = OpConstant %uint 32
+%void = OpTypeVoid
+%uint_4 = OpConstant %uint 4
+%uint_0 = OpConstant %uint 0
+%uint_3 = OpConstant %uint 3
+%uint_1 = OpConstant %uint 1
+%uint_5 = OpConstant %uint 5
+%uint_17 = OpConstant %uint 17
+%uint_13 = OpConstant %uint 13
+%30 = OpTypeFunction %void
+%uint_7 = OpConstant %uint 7
+%uint_6 = OpConstant %uint 6
+%uint_2 = OpConstant %uint 2
+%uint_12 = OpConstant %uint 12
+%48 = OpTypeFunction %int
+%uint_9 = OpConstant %uint 9
+%10 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_4 %uint_0
+%13 = OpExtInst %void %1 DebugTypeFunction %uint_3 %10
+%16 = OpExtInst %void %1 DebugSource %3 %15
+%17 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %16 %uint_5
+%22 = OpExtInst %void %1 DebugFunction %20 %13 %16 %uint_1 %uint_1 %17 %21 %uint_3 %uint_1
+%23 = OpExtInst %void %1 DebugLexicalBlock %16 %uint_1 %uint_17 %22
+%25 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
+%27 = OpExtInst %void %1 DebugFunction %26 %25 %16 %uint_5 %uint_1 %17 %21 %uint_3 %uint_5
+%28 = OpExtInst %void %1 DebugLexicalBlock %16 %uint_5 %uint_13 %27
+%main = OpFunction %void None %30
+%31 = OpLabel
+%32 = OpFunctionCall %void %src_main
+%34 = OpExtInst %void %1 DebugLine %16 %uint_7 %uint_7 %uint_1 %uint_1
+OpReturn
+OpFunctionEnd
+%src_main = OpFunction %void None %30
+%bb_entry = OpLabel
+%37 = OpExtInst %void %1 DebugScope %27
+%38 = OpExtInst %void %1 DebugFunctionDefinition %27 %src_main
+%39 = OpExtInst %void %1 DebugScope %28
+%40 = OpExtInst %void %1 DebugLine %16 %uint_6 %uint_6 %uint_2 %uint_12
+%44 = OpFunctionCall %int %function1
+%46 = OpExtInst %void %1 DebugScope %27
+%47 = OpExtInst %void %1 DebugLine %16 %uint_7 %uint_7 %uint_1 %uint_1
+OpReturn
+OpFunctionEnd
+%function1 = OpFunction %int None %48
+%bb_entry_0 = OpLabel
+%50 = OpExtInst %void %1 DebugScope %22
+%51 = OpExtInst %void %1 DebugFunctionDefinition %22 %function1
+%52 = OpExtInst %void %1 DebugScope %23
+%53 = OpExtInst %void %1 DebugLine %16 %uint_2 %uint_2 %uint_2 %uint_9
+OpReturnValue %int_1
+OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SinglePassRunAndMatch<InlineExhaustivePass>(text, true);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //    Empty modules
@@ -4352,7 +4437,7 @@
 //    Callee function returns a value generated outside the callee,
 //      e.g. a constant value. This might exercise some logic not yet
 //      exercised by the current tests: the false branch in the "if"
-//      inside the SpvOpReturnValue case in InlinePass::GenInlineCode?
+//      inside the spv::Op::OpReturnValue case in InlinePass::GenInlineCode?
 //    SampledImage before function call, but callee is only single block.
 //      Then the SampledImage instruction is not cloned. Documents existing
 //      behaviour.
diff --git a/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp b/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp
index c8eb6c1..4f4b668 100644
--- a/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp
@@ -1,5 +1,5 @@
-// Copyright (c) 2017 Valve Corporation
-// Copyright (c) 2017 LunarG Inc.
+// Copyright (c) 2017-2022 Valve Corporation
+// Copyright (c) 2017-2022 LunarG Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -28,6 +28,297 @@
 
 using InstBindlessTest = PassTest<::testing::Test>;
 
+static const std::string kOutputDecorations = R"(
+; CHECK: OpDecorate [[output_buffer_type:%inst_bindless_OutputBuffer]] Block
+; CHECK: OpMemberDecorate [[output_buffer_type]] 0 Offset 0
+; CHECK: OpMemberDecorate [[output_buffer_type]] 1 Offset 4
+; CHECK: OpDecorate [[output_buffer_var:%\w+]] DescriptorSet 7
+; CHECK: OpDecorate [[output_buffer_var]] Binding 0
+)";
+
+static const std::string kOutputGlobals = R"(
+; CHECK: [[output_buffer_type]] = OpTypeStruct %uint %uint %_runtimearr_uint
+; CHECK: [[output_ptr_type:%\w+]] = OpTypePointer StorageBuffer [[output_buffer_type]]
+; CHECK: [[output_buffer_var]] = OpVariable [[output_ptr_type]] StorageBuffer
+)";
+
+static const std::string kStreamWrite4Begin = R"(
+; CHECK: %inst_bindless_stream_write_4 = OpFunction %void None {{%\w+}}
+; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_4:%\w+]] = OpFunctionParameter %uint
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1
+; CHECK: {{%\w+}} = OpAtomicIAdd %uint {{%\w+}} %uint_4 %uint_0 %uint_10
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_10
+; CHECK: {{%\w+}} = OpArrayLength %uint [[output_buffer_var]] 2
+; CHECK: {{%\w+}} = OpULessThanEqual %bool {{%\w+}} {{%\w+}}
+; CHECK: OpSelectionMerge {{%\w+}} None
+; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_0
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_10
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_1
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_23
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_2
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_1]]
+)";
+
+static const std::string kStreamWrite4End = R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_2]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_8
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_3]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_9
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_4]]
+; CHECK: OpBranch {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: OpReturn
+; CHECK: OpFunctionEnd
+)";
+
+// clang-format off
+static const std::string kStreamWrite4Frag = kStreamWrite4Begin + R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord
+; CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+)" + kStreamWrite4End;
+
+static const std::string kStreamWrite4Tese = kStreamWrite4Begin + R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_2
+; CHECK: {{%\w+}} = OpLoad %uint %gl_PrimitiveID
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %v3float %gl_TessCoord
+; CHECK: {{%\w+}} = OpBitcast %v3uint {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_6
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+)" + kStreamWrite4End;
+
+static const std::string kStreamWrite4Vert = kStreamWrite4Begin + R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_0
+; CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+)" + kStreamWrite4End;
+
+static const std::string kStreamWrite4Compute = kStreamWrite4Begin + R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpLoad %v3uint %gl_GlobalInvocationID
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_6
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+)" + kStreamWrite4End;
+
+static const std::string kStreamWrite4Ray = kStreamWrite4Begin + R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint %90 0
+; CHECK: {{%\w+}} = OpCompositeExtract %uint %90 1
+; CHECK: {{%\w+}} = OpCompositeExtract %uint %90 2
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_6
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+)" + kStreamWrite4End;
+// clang-format on
+
+static const std::string kStreamWrite5Begin = R"(
+; CHECK: %inst_bindless_stream_write_5 = OpFunction %void None {{%\w+}}
+; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_4:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_5:%\w+]] = OpFunctionParameter %uint
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1
+; CHECK: {{%\w+}} = OpAtomicIAdd %uint {{%\w+}} %uint_4 %uint_0 %uint_11
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_11
+; CHECK: {{%\w+}} = OpArrayLength %uint [[output_buffer_var]] 2
+; CHECK: {{%\w+}} = OpULessThanEqual %bool {{%\w+}} {{%\w+}}
+; CHECK: OpSelectionMerge {{%\w+}} None
+; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_0
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_11
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_1
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_23
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_2
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_1]]
+)";
+
+static const std::string kStreamWrite5End = R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_2]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_8
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_3]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_9
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_4]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_10
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_5]]
+; CHECK: OpBranch {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: OpReturn
+; CHECK: OpFunctionEnd
+)";
+
+// clang-format off
+static const std::string kStreamWrite5Frag = kStreamWrite5Begin + R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord
+; CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+)" + kStreamWrite4End;
+
+static const std::string kStreamWrite5Vert = kStreamWrite5Begin + R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_0
+; CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+)" + kStreamWrite5End;
+// clang-format on
+
+static const std::string kInputDecorations = R"(
+; CHECK: OpDecorate [[input_buffer_type:%inst_bindless_InputBuffer]] Block
+; CHECK: OpMemberDecorate [[input_buffer_type]] 0 Offset 0
+; CHECK: OpDecorate [[input_buffer_var:%\w+]] DescriptorSet 7
+; CHECK: OpDecorate [[input_buffer_var]] Binding 1
+)";
+
+static const std::string kInputGlobals = R"(
+; CHECK: [[input_buffer_type]] = OpTypeStruct %_runtimearr_uint
+; CHECK: [[input_ptr_type:%\w+]] = OpTypePointer StorageBuffer [[input_buffer_type]]
+; CHECK: [[input_buffer_var]] = OpVariable [[input_ptr_type]] StorageBuffer
+)";
+
+static const std::string kDirectRead2 = R"(
+; CHECK: %inst_bindless_direct_read_2 = OpFunction %uint None {{%\w+}}
+; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 [[param_1]]
+; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_2]]
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
+; CHECK: OpReturnValue {{%\w+}}
+; CHECK: OpFunctionEnd
+)";
+
+static const std::string kDirectRead3 = R"(
+ ;CHECK: %inst_bindless_direct_read_3 = OpFunction %uint None {{%\w+}}
+; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
+ ;CHECK: {{%\w+}} = OpLabel
+ ;CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 [[param_1]]
+ ;CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
+ ;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_2]]
+ ;CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
+ ;CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
+ ;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_3]]
+ ;CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
+ ;CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
+ ;CHECK: OpReturnValue {{%\w+}}
+ ;CHECK: OpFunctionEnd
+)";
+
+static const std::string kDirectRead4 = R"(
+; CHECK: %inst_bindless_direct_read_4 = OpFunction %uint None {{%\w+}}
+; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_4:%\w+]] = OpFunctionParameter %uint
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 [[param_1]]
+; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_2]]
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_3]]
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[param_4]]
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[input_buffer_var]] %uint_0 {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}}
+; CHECK: OpReturnValue {{%\w+}}
+; CHECK: OpFunctionEnd
+)";
+
 TEST_F(InstBindlessTest, NoInstrumentConstIndexInbounds) {
   // Texture2D g_tColor[128];
   //
@@ -215,27 +506,20 @@
   //   return ps_output;
   // }
 
-  const std::string entry_before =
-      R"(OpCapability Shader
+  const std::string entry = R"(
+OpCapability Shader
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
+; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
 OpExecutionMode %MainPs OriginUpperLeft
 OpSource HLSL 500
 )";
 
-  const std::string entry_after =
-      R"(OpCapability Shader
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
-OpExecutionMode %MainPs OriginUpperLeft
-OpSource HLSL 500
-)";
-
-  const std::string names_annots =
-      R"(OpName %MainPs "MainPs"
+  // clang-format off
+  const std::string names_annots = R"(
+OpName %MainPs "MainPs"
 OpName %g_tColor "g_tColor"
 OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
 OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
@@ -250,20 +534,13 @@
 OpDecorate %g_sAniso DescriptorSet 0
 OpDecorate %i_vTextureCoords Location 0
 OpDecorate %_entryPointOutput_vColor Location 0
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 )";
 
-  const std::string new_annots =
-      R"(OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_55 Block
-OpMemberDecorate %_struct_55 0 Offset 0
-OpMemberDecorate %_struct_55 1 Offset 4
-OpDecorate %57 DescriptorSet 7
-OpDecorate %57 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-)";
-
-  const std::string consts_types_vars =
-      R"(%void = OpTypeVoid
+  const std::string consts_types_vars = R"(
+%void = OpTypeVoid
 %10 = OpTypeFunction %void
 %float = OpTypeFloat 32
 %v2float = OpTypeVector %float 2
@@ -289,36 +566,20 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
+; CHECK: %bool = OpTypeBool
+; CHECK: %48 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %103 = OpConstantNull %v4float
 )";
+  // clang-format on
 
-  const std::string new_consts_types_vars =
-      R"(%uint_0 = OpConstant %uint 0
-%bool = OpTypeBool
-%48 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_55 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55
-%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_1 = OpConstant %uint 1
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_56 = OpConstant %uint 56
-%103 = OpConstantNull %v4float
-)";
-
-  const std::string func_pt1 =
-      R"(%MainPs = OpFunction %void None %10
+  const std::string main_func = R"(
+%MainPs = OpFunction %void None %10
 %29 = OpLabel
 %30 = OpLoad %v2float %i_vTextureCoords
 %31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
@@ -327,93 +588,34 @@
 %34 = OpLoad %16 %33
 %35 = OpLoad %24 %g_sAniso
 %36 = OpSampledImage %26 %34 %35
-)";
-
-  const std::string func_pt2_before =
-      R"(%37 = OpImageSampleImplicitLod %v4float %36 %30
+%37 = OpImageSampleImplicitLod %v4float %36 %30
 OpStore %_entryPointOutput_vColor %37
+; CHECK-NOT: %37 = OpImageSampleImplicitLod %v4float %36 %30
+; CHECK-NOT: OpStore %_entryPointOutput_vColor %37
+; CHECK: %40 = OpULessThan %bool %32 %uint_128
+; CHECK: OpSelectionMerge %41 None
+; CHECK: OpBranchConditional %40 %42 %43
+; CHECK: %42 = OpLabel
+; CHECK: %44 = OpLoad %16 %33
+; CHECK: %45 = OpSampledImage %26 %44 %35
+; CHECK: %46 = OpImageSampleImplicitLod %v4float %45 %30
+; CHECK: OpBranch %41
+; CHECK: %43 = OpLabel
+; CHECK: %102 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_56 %uint_0 %32 %uint_128
+; CHECK: OpBranch %41
+; CHECK: %41 = OpLabel
+; CHECK: %104 = OpPhi %v4float %46 %42 %103 %43
+; CHECK: OpStore %_entryPointOutput_vColor %104
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_pt2_after =
-      R"(%40 = OpULessThan %bool %32 %uint_128
-OpSelectionMerge %41 None
-OpBranchConditional %40 %42 %43
-%42 = OpLabel
-%44 = OpLoad %16 %33
-%45 = OpSampledImage %26 %44 %35
-%46 = OpImageSampleImplicitLod %v4float %45 %30
-OpBranch %41
-%43 = OpLabel
-%102 = OpFunctionCall %void %47 %uint_56 %uint_0 %32 %uint_128
-OpBranch %41
-%41 = OpLabel
-%104 = OpPhi %v4float %46 %42 %103 %43
-OpStore %_entryPointOutput_vColor %104
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string output_func =
-      R"(%47 = OpFunction %void None %48
-%49 = OpFunctionParameter %uint
-%50 = OpFunctionParameter %uint
-%51 = OpFunctionParameter %uint
-%52 = OpFunctionParameter %uint
-%53 = OpLabel
-%59 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0
-%62 = OpAtomicIAdd %uint %59 %uint_4 %uint_0 %uint_10
-%63 = OpIAdd %uint %62 %uint_10
-%64 = OpArrayLength %uint %57 1
-%65 = OpULessThanEqual %bool %63 %64
-OpSelectionMerge %66 None
-OpBranchConditional %65 %67 %66
-%67 = OpLabel
-%68 = OpIAdd %uint %62 %uint_0
-%70 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %68
-OpStore %70 %uint_10
-%72 = OpIAdd %uint %62 %uint_1
-%73 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %72
-OpStore %73 %uint_23
-%75 = OpIAdd %uint %62 %uint_2
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75
-OpStore %76 %49
-%78 = OpIAdd %uint %62 %uint_3
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %78
-OpStore %79 %uint_4
-%82 = OpLoad %v4float %gl_FragCoord
-%84 = OpBitcast %v4uint %82
-%85 = OpCompositeExtract %uint %84 0
-%86 = OpIAdd %uint %62 %uint_4
-%87 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %86
-OpStore %87 %85
-%88 = OpCompositeExtract %uint %84 1
-%90 = OpIAdd %uint %62 %uint_5
-%91 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %90
-OpStore %91 %88
-%93 = OpIAdd %uint %62 %uint_7
-%94 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %93
-OpStore %94 %50
-%96 = OpIAdd %uint %62 %uint_8
-%97 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %96
-OpStore %97 %51
-%99 = OpIAdd %uint %62 %uint_9
-%100 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %99
-OpStore %100 %52
-OpBranch %66
-%66 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_func = kStreamWrite4Frag;
 
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass, uint32_t, uint32_t, bool, bool>(
-      entry_before + names_annots + consts_types_vars + func_pt1 +
-          func_pt2_before,
-      entry_after + names_annots + new_annots + consts_types_vars +
-          new_consts_types_vars + func_pt1 + func_pt2_after + output_func,
-      true, true, 7u, 23u, false, false, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass, uint32_t, uint32_t, bool, bool>(
+      entry + names_annots + consts_types_vars + main_func + output_func, true,
+      7u, 23u, false, false, false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentMultipleInstructions) {
@@ -447,11 +649,14 @@
   //   return ps_output;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
+; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
 OpExecutionMode %MainPs OriginUpperLeft
 OpSource HLSL 500
 OpName %MainPs "MainPs"
@@ -470,6 +675,9 @@
 OpDecorate %g_sAniso DescriptorSet 0
 OpDecorate %i_vTextureCoords Location 0
 OpDecorate %_entryPointOutput_vColor Location 0
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 %void = OpTypeVoid
 %10 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -497,93 +705,19 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
+; CHECK: %bool = OpTypeBool
+; CHECK: %56 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %111 = OpConstantNull %v4float
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
-OpExecutionMode %MainPs OriginUpperLeft
-OpSource HLSL 500
-OpName %MainPs "MainPs"
-OpName %g_tColor "g_tColor"
-OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
-OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
-OpName %_ ""
-OpName %g_sAniso "g_sAniso"
-OpName %i_vTextureCoords "i.vTextureCoords"
-OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
-OpDecorate %g_tColor DescriptorSet 3
-OpDecorate %g_tColor Binding 0
-OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
-OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 4
-OpDecorate %PerViewConstantBuffer_t Block
-OpDecorate %g_sAniso DescriptorSet 0
-OpDecorate %i_vTextureCoords Location 0
-OpDecorate %_entryPointOutput_vColor Location 0
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_63 Block
-OpMemberDecorate %_struct_63 0 Offset 0
-OpMemberDecorate %_struct_63 1 Offset 4
-OpDecorate %65 DescriptorSet 7
-OpDecorate %65 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-%void = OpTypeVoid
-%10 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v2float = OpTypeVector %float 2
-%v4float = OpTypeVector %float 4
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%int_1 = OpConstant %int 1
-%17 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%uint = OpTypeInt 32 0
-%uint_128 = OpConstant %uint 128
-%_arr_17_uint_128 = OpTypeArray %17 %uint_128
-%_ptr_UniformConstant__arr_17_uint_128 = OpTypePointer UniformConstant %_arr_17_uint_128
-%g_tColor = OpVariable %_ptr_UniformConstant__arr_17_uint_128 UniformConstant
-%PerViewConstantBuffer_t = OpTypeStruct %uint %uint
-%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
-%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
-%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
-%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17
-%25 = OpTypeSampler
-%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25
-%g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant
-%27 = OpTypeSampledImage %17
-%_ptr_Input_v2float = OpTypePointer Input %v2float
-%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-%uint_0 = OpConstant %uint 0
-%bool = OpTypeBool
-%56 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_63 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63
-%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_1 = OpConstant %uint 1
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_58 = OpConstant %uint 58
-%111 = OpConstantNull %v4float
-%uint_64 = OpConstant %uint 64
-)";
-
-  const std::string func_before =
+  const std::string main_func =
       R"(%MainPs = OpFunction %void None %10
 %30 = OpLabel
 %31 = OpLoad %v2float %i_vTextureCoords
@@ -594,6 +728,20 @@
 %36 = OpLoad %25 %g_sAniso
 %37 = OpSampledImage %27 %35 %36
 %38 = OpImageSampleImplicitLod %v4float %37 %31
+; CHECK-NOT: %38 = OpImageSampleImplicitLod %v4float %37 %31
+; CHECK: %48 = OpULessThan %bool %33 %uint_128
+; CHECK: OpSelectionMerge %49 None
+; CHECK: OpBranchConditional %48 %50 %51
+; CHECK: %50 = OpLabel
+; CHECK: %52 = OpLoad %17 %34
+; CHECK: %53 = OpSampledImage %27 %52 %36
+; CHECK: %54 = OpImageSampleImplicitLod %v4float %53 %31
+; CHECK: OpBranch %49
+; CHECK: %51 = OpLabel
+; CHECK: %110 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_58 %uint_0 %33 %uint_128
+; CHECK: OpBranch %49
+; CHECK: %49 = OpLabel
+; CHECK: %112 = OpPhi %v4float %54 %50 %111 %51
 %39 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1
 %40 = OpLoad %uint %39
 %41 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %40
@@ -601,114 +749,33 @@
 %43 = OpSampledImage %27 %42 %36
 %44 = OpImageSampleImplicitLod %v4float %43 %31
 %45 = OpFAdd %v4float %38 %44
+; CHECK-NOT: %44 = OpImageSampleImplicitLod %v4float %43 %31
+; CHECK-NOT: %45 = OpFAdd %v4float %38 %44
+; CHECK: %113 = OpULessThan %bool %40 %uint_128
+; CHECK: OpSelectionMerge %114 None
+; CHECK: OpBranchConditional %113 %115 %116
+; CHECK: %115 = OpLabel
+; CHECK: %117 = OpLoad %17 %41
+; CHECK: %118 = OpSampledImage %27 %117 %36
+; CHECK: %119 = OpImageSampleImplicitLod %v4float %118 %31
+; CHECK: OpBranch %114
+; CHECK: %116 = OpLabel
+; CHECK: %121 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_64 %uint_0 %40 %uint_128
+; CHECK: OpBranch %114
+; CHECK: %114 = OpLabel
+; CHECK: %122 = OpPhi %v4float %119 %115 %111 %116
+; CHECK: %45 = OpFAdd %v4float %112 %122
 OpStore %_entryPointOutput_vColor %45
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%MainPs = OpFunction %void None %10
-%30 = OpLabel
-%31 = OpLoad %v2float %i_vTextureCoords
-%32 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
-%33 = OpLoad %uint %32
-%34 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %33
-%35 = OpLoad %17 %34
-%36 = OpLoad %25 %g_sAniso
-%37 = OpSampledImage %27 %35 %36
-%48 = OpULessThan %bool %33 %uint_128
-OpSelectionMerge %49 None
-OpBranchConditional %48 %50 %51
-%50 = OpLabel
-%52 = OpLoad %17 %34
-%53 = OpSampledImage %27 %52 %36
-%54 = OpImageSampleImplicitLod %v4float %53 %31
-OpBranch %49
-%51 = OpLabel
-%110 = OpFunctionCall %void %55 %uint_58 %uint_0 %33 %uint_128
-OpBranch %49
-%49 = OpLabel
-%112 = OpPhi %v4float %54 %50 %111 %51
-%39 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1
-%40 = OpLoad %uint %39
-%41 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %40
-%42 = OpLoad %17 %41
-%43 = OpSampledImage %27 %42 %36
-%113 = OpULessThan %bool %40 %uint_128
-OpSelectionMerge %114 None
-OpBranchConditional %113 %115 %116
-%115 = OpLabel
-%117 = OpLoad %17 %41
-%118 = OpSampledImage %27 %117 %36
-%119 = OpImageSampleImplicitLod %v4float %118 %31
-OpBranch %114
-%116 = OpLabel
-%121 = OpFunctionCall %void %55 %uint_64 %uint_0 %40 %uint_128
-OpBranch %114
-%114 = OpLabel
-%122 = OpPhi %v4float %119 %115 %111 %116
-%45 = OpFAdd %v4float %112 %122
-OpStore %_entryPointOutput_vColor %45
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string output_func =
-      R"(%55 = OpFunction %void None %56
-%57 = OpFunctionParameter %uint
-%58 = OpFunctionParameter %uint
-%59 = OpFunctionParameter %uint
-%60 = OpFunctionParameter %uint
-%61 = OpLabel
-%67 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0
-%70 = OpAtomicIAdd %uint %67 %uint_4 %uint_0 %uint_10
-%71 = OpIAdd %uint %70 %uint_10
-%72 = OpArrayLength %uint %65 1
-%73 = OpULessThanEqual %bool %71 %72
-OpSelectionMerge %74 None
-OpBranchConditional %73 %75 %74
-%75 = OpLabel
-%76 = OpIAdd %uint %70 %uint_0
-%78 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %76
-OpStore %78 %uint_10
-%80 = OpIAdd %uint %70 %uint_1
-%81 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %80
-OpStore %81 %uint_23
-%83 = OpIAdd %uint %70 %uint_2
-%84 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %83
-OpStore %84 %57
-%86 = OpIAdd %uint %70 %uint_3
-%87 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %86
-OpStore %87 %uint_4
-%90 = OpLoad %v4float %gl_FragCoord
-%92 = OpBitcast %v4uint %90
-%93 = OpCompositeExtract %uint %92 0
-%94 = OpIAdd %uint %70 %uint_4
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94
-OpStore %95 %93
-%96 = OpCompositeExtract %uint %92 1
-%98 = OpIAdd %uint %70 %uint_5
-%99 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %98
-OpStore %99 %96
-%101 = OpIAdd %uint %70 %uint_7
-%102 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %101
-OpStore %102 %58
-%104 = OpIAdd %uint %70 %uint_8
-%105 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %104
-OpStore %105 %59
-%107 = OpIAdd %uint %70 %uint_9
-%108 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %107
-OpStore %108 %60
-OpBranch %74
-%74 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_func = kStreamWrite4Frag;
 
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
+                                               true, 7u, 23u, false, false,
+                                               false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentOpImage) {
@@ -716,12 +783,15 @@
   // using OpImage. This test was created by editing the SPIR-V
   // from the Simple test.
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability StorageImageReadWithoutFormat
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
+; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
 OpExecutionMode %MainPs OriginUpperLeft
 OpSource HLSL 500
 OpName %MainPs "MainPs"
@@ -737,6 +807,9 @@
 OpDecorate %PerViewConstantBuffer_t Block
 OpDecorate %i_vTextureCoords Location 0
 OpDecorate %_entryPointOutput_vColor Location 0
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -760,87 +833,21 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2int Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
+; CHECK: uint_0 = OpConstant %uint 0
+; CHECK: bool = OpTypeBool
+; CHECK: %86 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %141 = OpConstantNull %v4float
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability StorageImageReadWithoutFormat
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
-OpExecutionMode %MainPs OriginUpperLeft
-OpSource HLSL 500
-OpName %MainPs "MainPs"
-OpName %g_tColor "g_tColor"
-OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
-OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
-OpName %_ ""
-OpName %i_vTextureCoords "i.vTextureCoords"
-OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
-OpDecorate %g_tColor DescriptorSet 3
-OpDecorate %g_tColor Binding 0
-OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
-OpDecorate %PerViewConstantBuffer_t Block
-OpDecorate %i_vTextureCoords Location 0
-OpDecorate %_entryPointOutput_vColor Location 0
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_51 Block
-OpMemberDecorate %_struct_51 0 Offset 0
-OpMemberDecorate %_struct_51 1 Offset 4
-OpDecorate %53 DescriptorSet 7
-OpDecorate %53 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-%void = OpTypeVoid
-%9 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%int = OpTypeInt 32 1
-%v2int = OpTypeVector %int 2
-%int_0 = OpConstant %int 0
-%15 = OpTypeImage %float 2D 0 0 0 0 Unknown
-%uint = OpTypeInt 32 0
-%uint_128 = OpConstant %uint 128
-%18 = OpTypeSampledImage %15
-%_arr_18_uint_128 = OpTypeArray %18 %uint_128
-%_ptr_UniformConstant__arr_18_uint_128 = OpTypePointer UniformConstant %_arr_18_uint_128
-%g_tColor = OpVariable %_ptr_UniformConstant__arr_18_uint_128 UniformConstant
-%PerViewConstantBuffer_t = OpTypeStruct %uint
-%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
-%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
-%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
-%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
-%_ptr_Input_v2int = OpTypePointer Input %v2int
-%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-%uint_0 = OpConstant %uint 0
-%bool = OpTypeBool
-%44 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_51 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_51 = OpTypePointer StorageBuffer %_struct_51
-%53 = OpVariable %_ptr_StorageBuffer__struct_51 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_1 = OpConstant %uint 1
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_51 = OpConstant %uint 51
-%99 = OpConstantNull %v4float
-)";
-
-  const std::string func_before =
-      R"(%MainPs = OpFunction %void None %3
+  const std::string main_func = R"(
+%MainPs = OpFunction %void None %3
 %5 = OpLabel
 %53 = OpLoad %v2int %i_vTextureCoords
 %63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
@@ -850,93 +857,32 @@
 %75 = OpImage %20 %66
 %71 = OpImageRead %v4float %75 %53
 OpStore %_entryPointOutput_vColor %71
+; CHECK-NOT: %71 = OpImageRead %v4float %75 %53
+; CHECK-NOT: OpStore %_entryPointOutput_vColor %71
+; CHECK: %78 = OpULessThan %bool %64 %uint_128
+; CHECK: OpSelectionMerge %79 None
+; CHECK: OpBranchConditional %78 %80 %81
+; CHECK: %80 = OpLabel
+; CHECK: %82 = OpLoad %39 %65
+; CHECK: %83 = OpImage %20 %82
+; CHECK: %84 = OpImageRead %v4float %83 %53
+; CHECK: OpBranch %79
+; CHECK: %81 = OpLabel
+; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %64 %uint_128
+; CHECK: OpBranch %79
+; CHECK: %79 = OpLabel
+; CHECK: %142 = OpPhi %v4float %84 %80 %141 %81
+; CHECK: OpStore %_entryPointOutput_vColor %142
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%MainPs = OpFunction %void None %9
-%26 = OpLabel
-%27 = OpLoad %v2int %i_vTextureCoords
-%28 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
-%29 = OpLoad %uint %28
-%30 = OpAccessChain %_ptr_UniformConstant_18 %g_tColor %29
-%31 = OpLoad %18 %30
-%32 = OpImage %15 %31
-%36 = OpULessThan %bool %29 %uint_128
-OpSelectionMerge %37 None
-OpBranchConditional %36 %38 %39
-%38 = OpLabel
-%40 = OpLoad %18 %30
-%41 = OpImage %15 %40
-%42 = OpImageRead %v4float %41 %27
-OpBranch %37
-%39 = OpLabel
-%98 = OpFunctionCall %void %43 %uint_51 %uint_0 %29 %uint_128
-OpBranch %37
-%37 = OpLabel
-%100 = OpPhi %v4float %42 %38 %99 %39
-OpStore %_entryPointOutput_vColor %100
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_func = kStreamWrite4Frag;
 
-  const std::string output_func =
-      R"(%43 = OpFunction %void None %44
-%45 = OpFunctionParameter %uint
-%46 = OpFunctionParameter %uint
-%47 = OpFunctionParameter %uint
-%48 = OpFunctionParameter %uint
-%49 = OpLabel
-%55 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_0
-%58 = OpAtomicIAdd %uint %55 %uint_4 %uint_0 %uint_10
-%59 = OpIAdd %uint %58 %uint_10
-%60 = OpArrayLength %uint %53 1
-%61 = OpULessThanEqual %bool %59 %60
-OpSelectionMerge %62 None
-OpBranchConditional %61 %63 %62
-%63 = OpLabel
-%64 = OpIAdd %uint %58 %uint_0
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %64
-OpStore %66 %uint_10
-%68 = OpIAdd %uint %58 %uint_1
-%69 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %68
-OpStore %69 %uint_23
-%71 = OpIAdd %uint %58 %uint_2
-%72 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %71
-OpStore %72 %45
-%74 = OpIAdd %uint %58 %uint_3
-%75 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %74
-OpStore %75 %uint_4
-%78 = OpLoad %v4float %gl_FragCoord
-%80 = OpBitcast %v4uint %78
-%81 = OpCompositeExtract %uint %80 0
-%82 = OpIAdd %uint %58 %uint_4
-%83 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %82
-OpStore %83 %81
-%84 = OpCompositeExtract %uint %80 1
-%86 = OpIAdd %uint %58 %uint_5
-%87 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %86
-OpStore %87 %84
-%89 = OpIAdd %uint %58 %uint_7
-%90 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %89
-OpStore %90 %46
-%92 = OpIAdd %uint %58 %uint_8
-%93 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %92
-OpStore %93 %47
-%95 = OpIAdd %uint %58 %uint_9
-%96 = OpAccessChain %_ptr_StorageBuffer_uint %53 %uint_1 %95
-OpStore %96 %48
-OpBranch %62
-%62 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false, false, false, false);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
+                                               true, 7u, 23u, false, false,
+                                               false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentSampledImage) {
@@ -944,11 +890,14 @@
   // using sampled image. This test was created by editing the SPIR-V
   // from the Simple test.
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
+; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
 OpExecutionMode %MainPs OriginUpperLeft
 OpSource HLSL 500
 OpName %MainPs "MainPs"
@@ -964,6 +913,8 @@
 OpDecorate %PerViewConstantBuffer_t Block
 OpDecorate %i_vTextureCoords Location 0
 OpDecorate %_entryPointOutput_vColor Location 0
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -987,86 +938,21 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
+; CHECK: uint_0 = OpConstant %uint 0
+; CHECK: bool = OpTypeBool
+; CHECK: %81 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %136 = OpConstantNull %v4float
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
-OpExecutionMode %MainPs OriginUpperLeft
-OpSource HLSL 500
-OpName %MainPs "MainPs"
-OpName %g_tColor "g_tColor"
-OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
-OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
-OpName %_ ""
-OpName %i_vTextureCoords "i.vTextureCoords"
-OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
-OpDecorate %g_tColor DescriptorSet 3
-OpDecorate %g_tColor Binding 0
-OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
-OpDecorate %PerViewConstantBuffer_t Block
-OpDecorate %i_vTextureCoords Location 0
-OpDecorate %_entryPointOutput_vColor Location 0
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_49 Block
-OpMemberDecorate %_struct_49 0 Offset 0
-OpMemberDecorate %_struct_49 1 Offset 4
-OpDecorate %51 DescriptorSet 7
-OpDecorate %51 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-%void = OpTypeVoid
-%9 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v2float = OpTypeVector %float 2
-%v4float = OpTypeVector %float 4
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%15 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%uint = OpTypeInt 32 0
-%uint_128 = OpConstant %uint 128
-%18 = OpTypeSampledImage %15
-%_arr_18_uint_128 = OpTypeArray %18 %uint_128
-%_ptr_UniformConstant__arr_18_uint_128 = OpTypePointer UniformConstant %_arr_18_uint_128
-%g_tColor = OpVariable %_ptr_UniformConstant__arr_18_uint_128 UniformConstant
-%PerViewConstantBuffer_t = OpTypeStruct %uint
-%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
-%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
-%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
-%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
-%_ptr_Input_v2float = OpTypePointer Input %v2float
-%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-%uint_0 = OpConstant %uint 0
-%bool = OpTypeBool
-%42 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_49 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_49 = OpTypePointer StorageBuffer %_struct_49
-%51 = OpVariable %_ptr_StorageBuffer__struct_49 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_1 = OpConstant %uint 1
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_49 = OpConstant %uint 49
-%97 = OpConstantNull %v4float
-)";
-
-  const std::string func_before =
-      R"(%MainPs = OpFunction %void None %3
+  const std::string main_func = R"(
+%MainPs = OpFunction %void None %3
 %5 = OpLabel
 %53 = OpLoad %v2float %i_vTextureCoords
 %63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
@@ -1075,91 +961,31 @@
 %66 = OpLoad %39 %65
 %71 = OpImageSampleImplicitLod %v4float %66 %53
 OpStore %_entryPointOutput_vColor %71
+; CHECK-NOT: %71 = OpImageSampleImplicitLod %v4float %66 %53
+; CHECK-NOT: OpStore %_entryPointOutput_vColor %71
+; CHECK: %74 = OpULessThan %bool %64 %uint_128
+; CHECK: OpSelectionMerge %75 None
+; CHECK: OpBranchConditional %74 %76 %77
+; CHECK: %76 = OpLabel
+; CHECK: %78 = OpLoad %39 %65
+; CHECK: %79 = OpImageSampleImplicitLod %v4float %78 %53
+; CHECK: OpBranch %75
+; CHECK: %77 = OpLabel
+; CHECK: %135 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_49 %uint_0 %64 %uint_128
+; CHECK: OpBranch %75
+; CHECK: %75 = OpLabel
+; CHECK: %137 = OpPhi %v4float %79 %76 %136 %77
+; CHECK: OpStore %_entryPointOutput_vColor %137
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%MainPs = OpFunction %void None %9
-%26 = OpLabel
-%27 = OpLoad %v2float %i_vTextureCoords
-%28 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
-%29 = OpLoad %uint %28
-%30 = OpAccessChain %_ptr_UniformConstant_18 %g_tColor %29
-%31 = OpLoad %18 %30
-%35 = OpULessThan %bool %29 %uint_128
-OpSelectionMerge %36 None
-OpBranchConditional %35 %37 %38
-%37 = OpLabel
-%39 = OpLoad %18 %30
-%40 = OpImageSampleImplicitLod %v4float %39 %27
-OpBranch %36
-%38 = OpLabel
-%96 = OpFunctionCall %void %41 %uint_49 %uint_0 %29 %uint_128
-OpBranch %36
-%36 = OpLabel
-%98 = OpPhi %v4float %40 %37 %97 %38
-OpStore %_entryPointOutput_vColor %98
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_func = kStreamWrite4Frag;
 
-  const std::string output_func =
-      R"(%41 = OpFunction %void None %42
-%43 = OpFunctionParameter %uint
-%44 = OpFunctionParameter %uint
-%45 = OpFunctionParameter %uint
-%46 = OpFunctionParameter %uint
-%47 = OpLabel
-%53 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_0
-%56 = OpAtomicIAdd %uint %53 %uint_4 %uint_0 %uint_10
-%57 = OpIAdd %uint %56 %uint_10
-%58 = OpArrayLength %uint %51 1
-%59 = OpULessThanEqual %bool %57 %58
-OpSelectionMerge %60 None
-OpBranchConditional %59 %61 %60
-%61 = OpLabel
-%62 = OpIAdd %uint %56 %uint_0
-%64 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %62
-OpStore %64 %uint_10
-%66 = OpIAdd %uint %56 %uint_1
-%67 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %66
-OpStore %67 %uint_23
-%69 = OpIAdd %uint %56 %uint_2
-%70 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %69
-OpStore %70 %43
-%72 = OpIAdd %uint %56 %uint_3
-%73 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %72
-OpStore %73 %uint_4
-%76 = OpLoad %v4float %gl_FragCoord
-%78 = OpBitcast %v4uint %76
-%79 = OpCompositeExtract %uint %78 0
-%80 = OpIAdd %uint %56 %uint_4
-%81 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %80
-OpStore %81 %79
-%82 = OpCompositeExtract %uint %78 1
-%84 = OpIAdd %uint %56 %uint_5
-%85 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %84
-OpStore %85 %82
-%87 = OpIAdd %uint %56 %uint_7
-%88 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %87
-OpStore %88 %44
-%90 = OpIAdd %uint %56 %uint_8
-%91 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %90
-OpStore %91 %45
-%93 = OpIAdd %uint %56 %uint_9
-%94 = OpAccessChain %_ptr_StorageBuffer_uint %51 %uint_1 %93
-OpStore %94 %46
-OpBranch %60
-%60 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false, false, false, false);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
+                                               true, 7u, 23u, false, false,
+                                               false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentImageWrite) {
@@ -1167,12 +993,15 @@
   // doing bindless image write. This test was created by editing the SPIR-V
   // from the Simple test.
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability StorageImageWriteWithoutFormat
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
+; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
 OpExecutionMode %MainPs OriginUpperLeft
 OpSource HLSL 500
 OpName %MainPs "MainPs"
@@ -1188,6 +1017,9 @@
 OpDecorate %PerViewConstantBuffer_t Block
 OpDecorate %i_vTextureCoords Location 0
 OpDecorate %_entryPointOutput_vColor Location 0
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -1212,87 +1044,20 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2int Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
+; CHECK: uint_0 = OpConstant %uint 0
+; CHECK: bool = OpTypeBool
+; CHECK: %41 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: _runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability StorageImageWriteWithoutFormat
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
-OpExecutionMode %MainPs OriginUpperLeft
-OpSource HLSL 500
-OpName %MainPs "MainPs"
-OpName %g_tColor "g_tColor"
-OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
-OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
-OpName %_ ""
-OpName %i_vTextureCoords "i.vTextureCoords"
-OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
-OpDecorate %g_tColor DescriptorSet 3
-OpDecorate %g_tColor Binding 0
-OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
-OpDecorate %PerViewConstantBuffer_t Block
-OpDecorate %i_vTextureCoords Location 0
-OpDecorate %_entryPointOutput_vColor Location 0
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_48 Block
-OpMemberDecorate %_struct_48 0 Offset 0
-OpMemberDecorate %_struct_48 1 Offset 4
-OpDecorate %50 DescriptorSet 7
-OpDecorate %50 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-%void = OpTypeVoid
-%9 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v2float = OpTypeVector %float 2
-%v4float = OpTypeVector %float 4
-%int = OpTypeInt 32 1
-%v2int = OpTypeVector %int 2
-%int_0 = OpConstant %int 0
-%16 = OpTypeImage %float 2D 0 0 0 0 Unknown
-%uint = OpTypeInt 32 0
-%uint_128 = OpConstant %uint 128
-%19 = OpConstantNull %v4float
-%_arr_16_uint_128 = OpTypeArray %16 %uint_128
-%_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128
-%g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant
-%PerViewConstantBuffer_t = OpTypeStruct %uint
-%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
-%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
-%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
-%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
-%_ptr_Input_v2int = OpTypePointer Input %v2int
-%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-%uint_0 = OpConstant %uint 0
-%bool = OpTypeBool
-%41 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_48 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_48 = OpTypePointer StorageBuffer %_struct_48
-%50 = OpVariable %_ptr_StorageBuffer__struct_48 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_1 = OpConstant %uint 1
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_51 = OpConstant %uint 51
-)";
-
-  const std::string func_before =
-      R"(%MainPs = OpFunction %void None %3
+  const std::string main_func = R"(
+%MainPs = OpFunction %void None %3
 %5 = OpLabel
 %53 = OpLoad %v2int %i_vTextureCoords
 %63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
@@ -1301,90 +1066,30 @@
 %66 = OpLoad %20 %65
 OpImageWrite %66 %53 %80
 OpStore %_entryPointOutput_vColor %80
+; CHECK-NOT: OpImageWrite %66 %53 %80
+; CHECK-NOT: OpStore %_entryPointOutput_vColor %80
+; CHECK: %35 = OpULessThan %bool %30 %uint_128
+; CHECK: OpSelectionMerge %36 None
+; CHECK: OpBranchConditional %35 %37 %38
+; CHECK: %37 = OpLabel
+; CHECK: %39 = OpLoad %16 %31
+; CHECK: OpImageWrite %39 %28 %19
+; CHECK: OpBranch %36
+; CHECK: %38 = OpLabel
+; CHECK: %95 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %30 %uint_128
+; CHECK: OpBranch %36
+; CHECK: %36 = OpLabel
+; CHECK: OpStore %_entryPointOutput_vColor %19
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%MainPs = OpFunction %void None %9
-%27 = OpLabel
-%28 = OpLoad %v2int %i_vTextureCoords
-%29 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
-%30 = OpLoad %uint %29
-%31 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %30
-%32 = OpLoad %16 %31
-%35 = OpULessThan %bool %30 %uint_128
-OpSelectionMerge %36 None
-OpBranchConditional %35 %37 %38
-%37 = OpLabel
-%39 = OpLoad %16 %31
-OpImageWrite %39 %28 %19
-OpBranch %36
-%38 = OpLabel
-%95 = OpFunctionCall %void %40 %uint_51 %uint_0 %30 %uint_128
-OpBranch %36
-%36 = OpLabel
-OpStore %_entryPointOutput_vColor %19
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string output_func =
-      R"(%40 = OpFunction %void None %41
-%42 = OpFunctionParameter %uint
-%43 = OpFunctionParameter %uint
-%44 = OpFunctionParameter %uint
-%45 = OpFunctionParameter %uint
-%46 = OpLabel
-%52 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_0
-%55 = OpAtomicIAdd %uint %52 %uint_4 %uint_0 %uint_10
-%56 = OpIAdd %uint %55 %uint_10
-%57 = OpArrayLength %uint %50 1
-%58 = OpULessThanEqual %bool %56 %57
-OpSelectionMerge %59 None
-OpBranchConditional %58 %60 %59
-%60 = OpLabel
-%61 = OpIAdd %uint %55 %uint_0
-%63 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %61
-OpStore %63 %uint_10
-%65 = OpIAdd %uint %55 %uint_1
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %65
-OpStore %66 %uint_23
-%68 = OpIAdd %uint %55 %uint_2
-%69 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %68
-OpStore %69 %42
-%71 = OpIAdd %uint %55 %uint_3
-%72 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %71
-OpStore %72 %uint_4
-%75 = OpLoad %v4float %gl_FragCoord
-%77 = OpBitcast %v4uint %75
-%78 = OpCompositeExtract %uint %77 0
-%79 = OpIAdd %uint %55 %uint_4
-%80 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %79
-OpStore %80 %78
-%81 = OpCompositeExtract %uint %77 1
-%83 = OpIAdd %uint %55 %uint_5
-%84 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %83
-OpStore %84 %81
-%86 = OpIAdd %uint %55 %uint_7
-%87 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %86
-OpStore %87 %43
-%89 = OpIAdd %uint %55 %uint_8
-%90 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %89
-OpStore %90 %44
-%92 = OpIAdd %uint %55 %uint_9
-%93 = OpAccessChain %_ptr_StorageBuffer_uint %50 %uint_1 %92
-OpStore %93 %45
-OpBranch %59
-%59 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_func = kStreamWrite4Frag;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
+                                               true, 7u, 23u, false, false,
+                                               false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentVertexSimple) {
@@ -1392,9 +1097,11 @@
   // doing bindless image write. This test was created by editing the SPIR-V
   // from the Simple test.
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability Sampled1D
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Vertex %main "main" %_ %coords2D
@@ -1413,6 +1120,10 @@
 OpMemberName %foo 0 "g_idx"
 OpName %__0 ""
 OpName %coords2D "coords2D"
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_VertexIndex BuiltIn VertexIndex
+; CHECK: OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex
 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
@@ -1455,106 +1166,20 @@
 %v2float = OpTypeVector %float 2
 %_ptr_Input_v2float = OpTypePointer Input %v2float
 %coords2D = OpVariable %_ptr_Input_v2float Input
+; CHECK: %bool = OpTypeBool
+; CHECK: %54 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %_ptr_Input_uint = OpTypePointer Input %uint
+; CHECK: %gl_VertexIndex = OpVariable %_ptr_Input_uint Input
+; CHECK: %gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
+; CHECK: %106 = OpConstantNull %v4float
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability Sampled1D
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Vertex %main "main" %_ %coords2D %gl_VertexIndex %gl_InstanceIndex
-OpSource GLSL 450
-OpName %main "main"
-OpName %lod "lod"
-OpName %coords1D "coords1D"
-OpName %gl_PerVertex "gl_PerVertex"
-OpMemberName %gl_PerVertex 0 "gl_Position"
-OpMemberName %gl_PerVertex 1 "gl_PointSize"
-OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
-OpMemberName %gl_PerVertex 3 "gl_CullDistance"
-OpName %_ ""
-OpName %texSampler1D "texSampler1D"
-OpName %foo "foo"
-OpMemberName %foo 0 "g_idx"
-OpName %__0 ""
-OpName %coords2D "coords2D"
-OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
-OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
-OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
-OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
-OpDecorate %gl_PerVertex Block
-OpDecorate %texSampler1D DescriptorSet 0
-OpDecorate %texSampler1D Binding 3
-OpMemberDecorate %foo 0 Offset 0
-OpDecorate %foo Block
-OpDecorate %__0 DescriptorSet 0
-OpDecorate %__0 Binding 5
-OpDecorate %coords2D Location 0
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_61 Block
-OpMemberDecorate %_struct_61 0 Offset 0
-OpMemberDecorate %_struct_61 1 Offset 4
-OpDecorate %63 DescriptorSet 7
-OpDecorate %63 Binding 0
-OpDecorate %gl_VertexIndex BuiltIn VertexIndex
-OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex
-%void = OpTypeVoid
-%12 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Function_float = OpTypePointer Function %float
-%float_3 = OpConstant %float 3
-%float_1_78900003 = OpConstant %float 1.78900003
-%v4float = OpTypeVector %float 4
-%uint = OpTypeInt 32 0
-%uint_1 = OpConstant %uint 1
-%_arr_float_uint_1 = OpTypeArray %float %uint_1
-%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
-%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
-%_ = OpVariable %_ptr_Output_gl_PerVertex Output
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%24 = OpTypeImage %float 1D 0 0 0 1 Unknown
-%25 = OpTypeSampledImage %24
-%uint_128 = OpConstant %uint 128
-%_arr_25_uint_128 = OpTypeArray %25 %uint_128
-%_ptr_UniformConstant__arr_25_uint_128 = OpTypePointer UniformConstant %_arr_25_uint_128
-%texSampler1D = OpVariable %_ptr_UniformConstant__arr_25_uint_128 UniformConstant
-%foo = OpTypeStruct %int
-%_ptr_Uniform_foo = OpTypePointer Uniform %foo
-%__0 = OpVariable %_ptr_Uniform_foo Uniform
-%_ptr_Uniform_int = OpTypePointer Uniform %int
-%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%v2float = OpTypeVector %float 2
-%_ptr_Input_v2float = OpTypePointer Input %v2float
-%coords2D = OpVariable %_ptr_Input_v2float Input
-%uint_0 = OpConstant %uint 0
-%bool = OpTypeBool
-%54 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_61 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_61 = OpTypePointer StorageBuffer %_struct_61
-%63 = OpVariable %_ptr_StorageBuffer__struct_61 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_uint = OpTypePointer Input %uint
-%gl_VertexIndex = OpVariable %_ptr_Input_uint Input
-%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_74 = OpConstant %uint 74
-%106 = OpConstantNull %v4float
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %lod = OpVariable %_ptr_Function_float Function
 %coords1D = OpVariable %_ptr_Function_float Function
@@ -1569,96 +1194,34 @@
 %38 = OpImageSampleExplicitLod %v4float %35 %36 Lod %37
 %40 = OpAccessChain %_ptr_Output_v4float %_ %int_0
 OpStore %40 %38
+; CHECK-NOT: %38 = OpImageSampleExplicitLod %v4float %35 %36 Lod %37
+; CHECK-NOT: %40 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+; CHECK-NOT: OpStore %40 %38
+; CHECK: %46 = OpULessThan %bool %37 %uint_128
+; CHECK: OpSelectionMerge %47 None
+; CHECK: OpBranchConditional %46 %48 %49
+; CHECK: %48 = OpLabel
+; CHECK: %50 = OpLoad %25 %38
+; CHECK: %51 = OpImageSampleExplicitLod %v4float %50 %40 Lod %41
+; CHECK: OpBranch %47
+; CHECK: %49 = OpLabel
+; CHECK: %52 = OpBitcast %uint %37
+; CHECK: %105 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_74 %uint_0 %52 %uint_128
+; CHECK: OpBranch %47
+; CHECK: %47 = OpLabel
+; CHECK: %107 = OpPhi %v4float %51 %48 %106 %49
+; CHECK: %43 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+; CHECK: OpStore %43 %107
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %12
-%35 = OpLabel
-%lod = OpVariable %_ptr_Function_float Function
-%coords1D = OpVariable %_ptr_Function_float Function
-OpStore %lod %float_3
-OpStore %coords1D %float_1_78900003
-%36 = OpAccessChain %_ptr_Uniform_int %__0 %int_0
-%37 = OpLoad %int %36
-%38 = OpAccessChain %_ptr_UniformConstant_25 %texSampler1D %37
-%39 = OpLoad %25 %38
-%40 = OpLoad %float %coords1D
-%41 = OpLoad %float %lod
-%46 = OpULessThan %bool %37 %uint_128
-OpSelectionMerge %47 None
-OpBranchConditional %46 %48 %49
-%48 = OpLabel
-%50 = OpLoad %25 %38
-%51 = OpImageSampleExplicitLod %v4float %50 %40 Lod %41
-OpBranch %47
-%49 = OpLabel
-%52 = OpBitcast %uint %37
-%105 = OpFunctionCall %void %53 %uint_74 %uint_0 %52 %uint_128
-OpBranch %47
-%47 = OpLabel
-%107 = OpPhi %v4float %51 %48 %106 %49
-%43 = OpAccessChain %_ptr_Output_v4float %_ %int_0
-OpStore %43 %107
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string output_func =
-      R"(%53 = OpFunction %void None %54
-%55 = OpFunctionParameter %uint
-%56 = OpFunctionParameter %uint
-%57 = OpFunctionParameter %uint
-%58 = OpFunctionParameter %uint
-%59 = OpLabel
-%65 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_0
-%68 = OpAtomicIAdd %uint %65 %uint_4 %uint_0 %uint_10
-%69 = OpIAdd %uint %68 %uint_10
-%70 = OpArrayLength %uint %63 1
-%71 = OpULessThanEqual %bool %69 %70
-OpSelectionMerge %72 None
-OpBranchConditional %71 %73 %72
-%73 = OpLabel
-%74 = OpIAdd %uint %68 %uint_0
-%75 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %74
-OpStore %75 %uint_10
-%77 = OpIAdd %uint %68 %uint_1
-%78 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %77
-OpStore %78 %uint_23
-%80 = OpIAdd %uint %68 %uint_2
-%81 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %80
-OpStore %81 %55
-%83 = OpIAdd %uint %68 %uint_3
-%84 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %83
-OpStore %84 %uint_0
-%87 = OpLoad %uint %gl_VertexIndex
-%88 = OpIAdd %uint %68 %uint_4
-%89 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %88
-OpStore %89 %87
-%91 = OpLoad %uint %gl_InstanceIndex
-%93 = OpIAdd %uint %68 %uint_5
-%94 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %93
-OpStore %94 %91
-%96 = OpIAdd %uint %68 %uint_7
-%97 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %96
-OpStore %97 %56
-%99 = OpIAdd %uint %68 %uint_8
-%100 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %99
-OpStore %100 %57
-%102 = OpIAdd %uint %68 %uint_9
-%103 = OpAccessChain %_ptr_StorageBuffer_uint %63 %uint_1 %102
-OpStore %103 %58
-OpBranch %72
-%72 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_func = kStreamWrite4Vert;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
+                                               true, 7u, 23u, false, false,
+                                               false, false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentTeseSimple) {
@@ -1680,13 +1243,13 @@
   //   gl_Position = adds[uniform_index_buffer.index].val;
   // }
   //
-  // clang-format on
 
-  const std::string defs_before =
-      R"(OpCapability Tessellation
+  const std::string defs = R"(
+OpCapability Tessellation
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint TessellationEvaluation %main "main" %_
+; CHECK: OpEntryPoint TessellationEvaluation %main "main" %_ %gl_PrimitiveID %gl_TessCoord
 OpExecutionMode %main Triangles
 OpExecutionMode %main SpacingEqual
 OpExecutionMode %main VertexOrderCw
@@ -1718,6 +1281,10 @@
 OpDecorate %ufoo Block
 OpDecorate %uniform_index_buffer DescriptorSet 0
 OpDecorate %uniform_index_buffer Binding 0
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
+; CHECK: OpDecorate %gl_TessCoord BuiltIn TessCoord
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -1741,211 +1308,68 @@
 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
 %_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
 %_ptr_Output_v4float = OpTypePointer Output %v4float
+; CHECK: %bool = OpTypeBool
+; CHECK: %40 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %_ptr_Input_uint = OpTypePointer Input %uint
+; CHECK: %gl_PrimitiveID = OpVariable %_ptr_Input_uint Input
+; CHECK: %v3float = OpTypeVector %float 3
+; CHECK: %_ptr_Input_v3float = OpTypePointer Input %v3float
+; CHECK: %gl_TessCoord = OpVariable %_ptr_Input_v3float Input
+; CHECK: %v3uint = OpTypeVector %uint 3
+; CHECK: %101 = OpConstantNull %v4float
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Tessellation
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint TessellationEvaluation %main "main" %_ %gl_PrimitiveID %gl_TessCoord
-OpExecutionMode %main Triangles
-OpExecutionMode %main SpacingEqual
-OpExecutionMode %main VertexOrderCw
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpName %main "main"
-OpName %gl_PerVertex "gl_PerVertex"
-OpMemberName %gl_PerVertex 0 "gl_Position"
-OpMemberName %gl_PerVertex 1 "gl_PointSize"
-OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
-OpMemberName %gl_PerVertex 3 "gl_CullDistance"
-OpName %_ ""
-OpName %bfoo "bfoo"
-OpMemberName %bfoo 0 "val"
-OpName %adds "adds"
-OpName %ufoo "ufoo"
-OpMemberName %ufoo 0 "index"
-OpName %uniform_index_buffer "uniform_index_buffer"
-OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
-OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
-OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
-OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
-OpDecorate %gl_PerVertex Block
-OpMemberDecorate %bfoo 0 Offset 0
-OpDecorate %bfoo Block
-OpDecorate %adds DescriptorSet 0
-OpDecorate %adds Binding 1
-OpMemberDecorate %ufoo 0 Offset 0
-OpDecorate %ufoo Block
-OpDecorate %uniform_index_buffer DescriptorSet 0
-OpDecorate %uniform_index_buffer Binding 0
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_47 Block
-OpMemberDecorate %_struct_47 0 Offset 0
-OpMemberDecorate %_struct_47 1 Offset 4
-OpDecorate %49 DescriptorSet 7
-OpDecorate %49 Binding 0
-OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
-OpDecorate %gl_TessCoord BuiltIn TessCoord
-%void = OpTypeVoid
-%10 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%uint = OpTypeInt 32 0
-%uint_1 = OpConstant %uint 1
-%_arr_float_uint_1 = OpTypeArray %float %uint_1
-%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
-%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
-%_ = OpVariable %_ptr_Output_gl_PerVertex Output
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%bfoo = OpTypeStruct %v4float
-%uint_11 = OpConstant %uint 11
-%_arr_bfoo_uint_11 = OpTypeArray %bfoo %uint_11
-%_ptr_StorageBuffer__arr_bfoo_uint_11 = OpTypePointer StorageBuffer %_arr_bfoo_uint_11
-%adds = OpVariable %_ptr_StorageBuffer__arr_bfoo_uint_11 StorageBuffer
-%ufoo = OpTypeStruct %uint
-%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo
-%uniform_index_buffer = OpVariable %_ptr_Uniform_ufoo Uniform
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%uint_0 = OpConstant %uint 0
-%bool = OpTypeBool
-%40 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_47 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_47 = OpTypePointer StorageBuffer %_struct_47
-%49 = OpVariable %_ptr_StorageBuffer__struct_47 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_uint = OpTypePointer Input %uint
-%gl_PrimitiveID = OpVariable %_ptr_Input_uint Input
-%v3float = OpTypeVector %float 3
-%_ptr_Input_v3float = OpTypePointer Input %v3float
-%gl_TessCoord = OpVariable %_ptr_Input_v3float Input
-%v3uint = OpTypeVector %uint 3
-%uint_5 = OpConstant %uint 5
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_63 = OpConstant %uint 63
-%101 = OpConstantNull %v4float
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %25 = OpAccessChain %_ptr_Uniform_uint %uniform_index_buffer %int_0
 %26 = OpLoad %uint %25
 %28 = OpAccessChain %_ptr_StorageBuffer_v4float %adds %26 %int_0
 %29 = OpLoad %v4float %28
+; CHECK-NOT: %29 = OpLoad %v4float %28
+; CHECK: %34 = OpULessThan %bool %28 %uint_11
+; CHECK: OpSelectionMerge %35 None
+; CHECK: OpBranchConditional %34 %36 %37
+; CHECK: %36 = OpLabel
+; CHECK: %38 = OpLoad %v4float %29
+; CHECK: OpBranch %35
+; CHECK: %37 = OpLabel
+; CHECK: %100 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_63 %uint_0 %28 %uint_11
+; CHECK: OpBranch %35
+; CHECK: %35 = OpLabel
+; CHECK: %102 = OpPhi %v4float %38 %36 %101 %37
 %31 = OpAccessChain %_ptr_Output_v4float %_ %int_0
 OpStore %31 %29
+; CHECK-NOT: OpStore %31 %29
+; CHECK: OpStore %31 %102
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %10
-%26 = OpLabel
-%27 = OpAccessChain %_ptr_Uniform_uint %uniform_index_buffer %int_0
-%28 = OpLoad %uint %27
-%29 = OpAccessChain %_ptr_StorageBuffer_v4float %adds %28 %int_0
-%34 = OpULessThan %bool %28 %uint_11
-OpSelectionMerge %35 None
-OpBranchConditional %34 %36 %37
-%36 = OpLabel
-%38 = OpLoad %v4float %29
-OpBranch %35
-%37 = OpLabel
-%100 = OpFunctionCall %void %39 %uint_63 %uint_0 %28 %uint_11
-OpBranch %35
-%35 = OpLabel
-%102 = OpPhi %v4float %38 %36 %101 %37
-%31 = OpAccessChain %_ptr_Output_v4float %_ %int_0
-OpStore %31 %102
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string output_func =
-      R"(%39 = OpFunction %void None %40
-%41 = OpFunctionParameter %uint
-%42 = OpFunctionParameter %uint
-%43 = OpFunctionParameter %uint
-%44 = OpFunctionParameter %uint
-%45 = OpLabel
-%51 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_0
-%54 = OpAtomicIAdd %uint %51 %uint_4 %uint_0 %uint_10
-%55 = OpIAdd %uint %54 %uint_10
-%56 = OpArrayLength %uint %49 1
-%57 = OpULessThanEqual %bool %55 %56
-OpSelectionMerge %58 None
-OpBranchConditional %57 %59 %58
-%59 = OpLabel
-%60 = OpIAdd %uint %54 %uint_0
-%61 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %60
-OpStore %61 %uint_10
-%63 = OpIAdd %uint %54 %uint_1
-%64 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %63
-OpStore %64 %uint_23
-%66 = OpIAdd %uint %54 %uint_2
-%67 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %66
-OpStore %67 %41
-%69 = OpIAdd %uint %54 %uint_3
-%70 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %69
-OpStore %70 %uint_2
-%73 = OpLoad %uint %gl_PrimitiveID
-%74 = OpIAdd %uint %54 %uint_4
-%75 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %74
-OpStore %75 %73
-%79 = OpLoad %v3float %gl_TessCoord
-%81 = OpBitcast %v3uint %79
-%82 = OpCompositeExtract %uint %81 0
-%83 = OpCompositeExtract %uint %81 1
-%85 = OpIAdd %uint %54 %uint_5
-%86 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %85
-OpStore %86 %82
-%88 = OpIAdd %uint %54 %uint_6
-%89 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %88
-OpStore %89 %83
-%91 = OpIAdd %uint %54 %uint_7
-%92 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %91
-OpStore %92 %42
-%94 = OpIAdd %uint %54 %uint_8
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %94
-OpStore %95 %43
-%97 = OpIAdd %uint %54 %uint_9
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %97
-OpStore %98 %44
-OpBranch %58
-%58 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_func = kStreamWrite4Tese;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, false, false, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + output_func,
+                                               true, 7u, 23u, false, false,
+                                               false, false, false);
 }
 
 TEST_F(InstBindlessTest, MultipleDebugFunctions) {
   // Same source as Simple, but compiled -g and not optimized, especially not
   // inlined. The OpSource has had the source extracted for the sake of brevity.
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %2 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
+; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
 OpExecutionMode %MainPs OriginUpperLeft
 %1 = OpString "foo5.frag"
 OpSource HLSL 500 %1
@@ -1974,6 +1398,9 @@
 OpDecorate %g_sAniso Binding 1
 OpDecorate %i_vTextureCoords Location 0
 OpDecorate %_entryPointOutput_vColor Location 0
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 %void = OpTypeVoid
 %4 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -2007,109 +1434,20 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
+; CHECK: %bool = OpTypeBool
+; CHECK: %70 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %125 = OpConstantNull %v4float
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
-OpExecutionMode %MainPs OriginUpperLeft
-%5 = OpString "foo5.frag"
-OpSource HLSL 500 %5
-OpName %MainPs "MainPs"
-OpName %PS_INPUT "PS_INPUT"
-OpMemberName %PS_INPUT 0 "vTextureCoords"
-OpName %PS_OUTPUT "PS_OUTPUT"
-OpMemberName %PS_OUTPUT 0 "vColor"
-OpName %_MainPs_struct_PS_INPUT_vf21_ "@MainPs(struct-PS_INPUT-vf21;"
-OpName %i "i"
-OpName %ps_output "ps_output"
-OpName %g_tColor "g_tColor"
-OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
-OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
-OpName %_ ""
-OpName %g_sAniso "g_sAniso"
-OpName %i_0 "i"
-OpName %i_vTextureCoords "i.vTextureCoords"
-OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
-OpName %param "param"
-OpDecorate %g_tColor DescriptorSet 0
-OpDecorate %g_tColor Binding 0
-OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
-OpDecorate %PerViewConstantBuffer_t Block
-OpDecorate %g_sAniso DescriptorSet 0
-OpDecorate %g_sAniso Binding 1
-OpDecorate %i_vTextureCoords Location 0
-OpDecorate %_entryPointOutput_vColor Location 0
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_77 Block
-OpMemberDecorate %_struct_77 0 Offset 0
-OpMemberDecorate %_struct_77 1 Offset 4
-OpDecorate %79 DescriptorSet 7
-OpDecorate %79 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-%void = OpTypeVoid
-%18 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v2float = OpTypeVector %float 2
-%PS_INPUT = OpTypeStruct %v2float
-%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
-%v4float = OpTypeVector %float 4
-%PS_OUTPUT = OpTypeStruct %v4float
-%23 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
-%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%27 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%uint = OpTypeInt 32 0
-%uint_128 = OpConstant %uint 128
-%_arr_27_uint_128 = OpTypeArray %27 %uint_128
-%_ptr_UniformConstant__arr_27_uint_128 = OpTypePointer UniformConstant %_arr_27_uint_128
-%g_tColor = OpVariable %_ptr_UniformConstant__arr_27_uint_128 UniformConstant
-%PerViewConstantBuffer_t = OpTypeStruct %uint
-%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
-%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
-%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
-%_ptr_UniformConstant_27 = OpTypePointer UniformConstant %27
-%35 = OpTypeSampler
-%_ptr_UniformConstant_35 = OpTypePointer UniformConstant %35
-%g_sAniso = OpVariable %_ptr_UniformConstant_35 UniformConstant
-%37 = OpTypeSampledImage %27
-%_ptr_Function_v2float = OpTypePointer Function %v2float
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v2float = OpTypePointer Input %v2float
-%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-%uint_0 = OpConstant %uint 0
-%bool = OpTypeBool
-%70 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_77 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_77 = OpTypePointer StorageBuffer %_struct_77
-%79 = OpVariable %_ptr_StorageBuffer__struct_77 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_1 = OpConstant %uint 1
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_109 = OpConstant %uint 109
-%125 = OpConstantNull %v4float
-)";
-
-  const std::string func1_before =
-      R"(%MainPs = OpFunction %void None %4
+  const std::string func1 = R"(
+%MainPs = OpFunction %void None %4
 %6 = OpLabel
 %i_0 = OpVariable %_ptr_Function_PS_INPUT Function
 %param = OpVariable %_ptr_Function_PS_INPUT Function
@@ -2126,26 +1464,8 @@
 OpFunctionEnd
 )";
 
-  const std::string func1_after =
-      R"(%MainPs = OpFunction %void None %18
-%42 = OpLabel
-%i_0 = OpVariable %_ptr_Function_PS_INPUT Function
-%param = OpVariable %_ptr_Function_PS_INPUT Function
-OpLine %5 21 0
-%43 = OpLoad %v2float %i_vTextureCoords
-%44 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0
-OpStore %44 %43
-%45 = OpLoad %PS_INPUT %i_0
-OpStore %param %45
-%46 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param
-%47 = OpCompositeExtract %v4float %46 0
-OpStore %_entryPointOutput_vColor %47
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string func2_before =
-      R"(%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %13
+  const std::string func2 = R"(
+%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %13
 %i = OpFunctionParameter %_ptr_Function_PS_INPUT
 %16 = OpLabel
 %ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function
@@ -2159,6 +1479,24 @@
 %43 = OpAccessChain %_ptr_Function_v2float %i %int_0
 %44 = OpLoad %v2float %43
 %45 = OpImageSampleImplicitLod %v4float %41 %44
+; CHECK-NOT: %45 = OpImageSampleImplicitLod %v4float %41 %44
+; CHECK: OpNoLine
+; CHECK: %62 = OpULessThan %bool %50 %uint_128
+; CHECK: OpSelectionMerge %63 None
+; CHECK: OpBranchConditional %62 %64 %65
+; CHECK: %64 = OpLabel
+; CHECK: %66 = OpLoad %27 %51
+; CHECK: %67 = OpSampledImage %37 %66 %53
+; CHECK: OpLine %5 24 0
+; CHECK: %68 = OpImageSampleImplicitLod %v4float %67 %56
+; CHECK: OpNoLine
+; CHECK: OpBranch %63
+; CHECK: %65 = OpLabel
+; CHECK: %124 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_109 %uint_0 %50 %uint_128
+; CHECK: OpBranch %63
+; CHECK: %63 = OpLabel
+; CHECK: %126 = OpPhi %v4float %68 %64 %125 %65
+; CHECK: OpLine %5 24 0
 %47 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0
 OpStore %47 %45
 OpLine %1 25 0
@@ -2167,102 +1505,12 @@
 OpFunctionEnd
 )";
 
-  const std::string func2_after =
-      R"(%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %23
-%i = OpFunctionParameter %_ptr_Function_PS_INPUT
-%48 = OpLabel
-%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function
-OpLine %5 24 0
-%49 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
-%50 = OpLoad %uint %49
-%51 = OpAccessChain %_ptr_UniformConstant_27 %g_tColor %50
-%52 = OpLoad %27 %51
-%53 = OpLoad %35 %g_sAniso
-%54 = OpSampledImage %37 %52 %53
-%55 = OpAccessChain %_ptr_Function_v2float %i %int_0
-%56 = OpLoad %v2float %55
-OpNoLine
-%62 = OpULessThan %bool %50 %uint_128
-OpSelectionMerge %63 None
-OpBranchConditional %62 %64 %65
-%64 = OpLabel
-%66 = OpLoad %27 %51
-%67 = OpSampledImage %37 %66 %53
-OpLine %5 24 0
-%68 = OpImageSampleImplicitLod %v4float %67 %56
-OpNoLine
-OpBranch %63
-%65 = OpLabel
-%124 = OpFunctionCall %void %69 %uint_109 %uint_0 %50 %uint_128
-OpBranch %63
-%63 = OpLabel
-%126 = OpPhi %v4float %68 %64 %125 %65
-OpLine %5 24 0
-%58 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0
-OpStore %58 %126
-OpLine %5 25 0
-%59 = OpLoad %PS_OUTPUT %ps_output
-OpReturnValue %59
-OpFunctionEnd
-)";
-
-  const std::string output_func =
-      R"(%69 = OpFunction %void None %70
-%71 = OpFunctionParameter %uint
-%72 = OpFunctionParameter %uint
-%73 = OpFunctionParameter %uint
-%74 = OpFunctionParameter %uint
-%75 = OpLabel
-%81 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_0
-%84 = OpAtomicIAdd %uint %81 %uint_4 %uint_0 %uint_10
-%85 = OpIAdd %uint %84 %uint_10
-%86 = OpArrayLength %uint %79 1
-%87 = OpULessThanEqual %bool %85 %86
-OpSelectionMerge %88 None
-OpBranchConditional %87 %89 %88
-%89 = OpLabel
-%90 = OpIAdd %uint %84 %uint_0
-%92 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %90
-OpStore %92 %uint_10
-%94 = OpIAdd %uint %84 %uint_1
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %94
-OpStore %95 %uint_23
-%97 = OpIAdd %uint %84 %uint_2
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %97
-OpStore %98 %71
-%100 = OpIAdd %uint %84 %uint_3
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %100
-OpStore %101 %uint_4
-%104 = OpLoad %v4float %gl_FragCoord
-%106 = OpBitcast %v4uint %104
-%107 = OpCompositeExtract %uint %106 0
-%108 = OpIAdd %uint %84 %uint_4
-%109 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %108
-OpStore %109 %107
-%110 = OpCompositeExtract %uint %106 1
-%112 = OpIAdd %uint %84 %uint_5
-%113 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %112
-OpStore %113 %110
-%115 = OpIAdd %uint %84 %uint_7
-%116 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %115
-OpStore %116 %72
-%118 = OpIAdd %uint %84 %uint_8
-%119 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %118
-OpStore %119 %73
-%121 = OpIAdd %uint %84 %uint_9
-%122 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %121
-OpStore %122 %74
-OpBranch %88
-%88 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_func = kStreamWrite4Frag;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func1_before + func2_before,
-      defs_after + func1_after + func2_after + output_func, true, true, 7u, 23u,
-      false, false, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(
+      defs + func1 + func2 + output_func, true, 7u, 23u, false, false, false,
+      false, false);
 }
 
 TEST_F(InstBindlessTest, RuntimeArray) {
@@ -2270,13 +1518,16 @@
   // with runtime descriptor array. This test was created by editing the
   // SPIR-V from the Simple test.
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability RuntimeDescriptorArray
 OpExtension "SPV_EXT_descriptor_indexing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
+; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
 OpExecutionMode %MainPs OriginUpperLeft
 OpSource HLSL 500
 OpName %MainPs "MainPs"
@@ -2295,6 +1546,9 @@
 OpDecorate %g_sAniso Binding 0
 OpDecorate %i_vTextureCoords Location 0
 OpDecorate %_entryPointOutput_vColor Location 0
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -2321,102 +1575,23 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
+; CHECK: %41 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %65 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %116 = OpConstantNull %v4float
+; CHECK: %119 = OpTypeFunction %uint %uint %uint %uint %uint
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability RuntimeDescriptorArray
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
-OpExecutionMode %MainPs OriginUpperLeft
-OpSource HLSL 500
-OpName %MainPs "MainPs"
-OpName %g_tColor "g_tColor"
-OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
-OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
-OpName %_ ""
-OpName %g_sAniso "g_sAniso"
-OpName %i_vTextureCoords "i.vTextureCoords"
-OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
-OpDecorate %g_tColor DescriptorSet 1
-OpDecorate %g_tColor Binding 2
-OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
-OpDecorate %PerViewConstantBuffer_t Block
-OpDecorate %g_sAniso DescriptorSet 1
-OpDecorate %g_sAniso Binding 0
-OpDecorate %i_vTextureCoords Location 0
-OpDecorate %_entryPointOutput_vColor Location 0
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_46 Block
-OpMemberDecorate %_struct_46 0 Offset 0
-OpDecorate %48 DescriptorSet 7
-OpDecorate %48 Binding 1
-OpDecorate %_struct_71 Block
-OpMemberDecorate %_struct_71 0 Offset 0
-OpMemberDecorate %_struct_71 1 Offset 4
-OpDecorate %73 DescriptorSet 7
-OpDecorate %73 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-%void = OpTypeVoid
-%10 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v2float = OpTypeVector %float 2
-%v4float = OpTypeVector %float 4
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%16 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%uint = OpTypeInt 32 0
-%uint_1 = OpConstant %uint 1
-%_runtimearr_16 = OpTypeRuntimeArray %16
-%_ptr_UniformConstant__runtimearr_16 = OpTypePointer UniformConstant %_runtimearr_16
-%g_tColor = OpVariable %_ptr_UniformConstant__runtimearr_16 UniformConstant
-%PerViewConstantBuffer_t = OpTypeStruct %uint
-%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
-%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
-%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint
-%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
-%24 = OpTypeSampler
-%_ptr_UniformConstant_24 = OpTypePointer UniformConstant %24
-%g_sAniso = OpVariable %_ptr_UniformConstant_24 UniformConstant
-%26 = OpTypeSampledImage %16
-%_ptr_Input_v2float = OpTypePointer Input %v2float
-%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-%uint_0 = OpConstant %uint 0
-%uint_2 = OpConstant %uint 2
-%41 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_46 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_46 = OpTypePointer StorageBuffer %_struct_46
-%48 = OpVariable %_ptr_StorageBuffer__struct_46 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%65 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_71 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_71 = OpTypePointer StorageBuffer %_struct_71
-%73 = OpVariable %_ptr_StorageBuffer__struct_71 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_59 = OpConstant %uint 59
-%116 = OpConstantNull %v4float
-%119 = OpTypeFunction %uint %uint %uint %uint %uint
-)";
-
-  const std::string func_before =
-      R"(%MainPs = OpFunction %void None %3
+  const std::string main_func = R"(
+%MainPs = OpFunction %void None %3
 %5 = OpLabel
 %53 = OpLoad %v2float %i_vTextureCoords
 %63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
@@ -2427,138 +1602,46 @@
 %68 = OpSampledImage %39 %66 %67
 %71 = OpImageSampleImplicitLod %v4float %68 %53
 OpStore %_entryPointOutput_vColor %71
+; CHECK-NOT: %71 = OpImageSampleImplicitLod %v4float %68 %53
+; CHECK-NOT: OpStore %_entryPointOutput_vColor %71
+; CHECK: %55 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_2 %uint_2
+; CHECK: %57 = OpULessThan %bool %32 %55
+; CHECK: OpSelectionMerge %58 None
+; CHECK: OpBranchConditional %57 %59 %60
+; CHECK: %59 = OpLabel
+; CHECK: %61 = OpLoad %16 %33
+; CHECK: %62 = OpSampledImage %26 %61 %35
+; CHECK: %136 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_1 %uint_2 %32
+; CHECK: %137 = OpULessThan %bool %uint_0 %136
+; CHECK: OpSelectionMerge %138 None
+; CHECK: OpBranchConditional %137 %139 %140
+; CHECK: %139 = OpLabel
+; CHECK: %141 = OpLoad %16 %33
+; CHECK: %142 = OpSampledImage %26 %141 %35
+; CHECK: %143 = OpImageSampleImplicitLod %v4float %142 %30
+; CHECK: OpBranch %138
+; CHECK: %140 = OpLabel
+; CHECK: %144 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_59 %uint_1 %32 %uint_0
+; CHECK: OpBranch %138
+; CHECK: %138 = OpLabel
+; CHECK: %145 = OpPhi %v4float %143 %139 %116 %140
+; CHECK: OpBranch %58
+; CHECK: %60 = OpLabel
+; CHECK: %115 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_59 %uint_0 %32 %55
+; CHECK: OpBranch %58
+; CHECK: %58 = OpLabel
+; CHECK: %117 = OpPhi %v4float %145 %138 %116 %60
+; CHECK: OpStore %_entryPointOutput_vColor %117
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%MainPs = OpFunction %void None %10
-%29 = OpLabel
-%30 = OpLoad %v2float %i_vTextureCoords
-%31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0
-%32 = OpLoad %uint %31
-%33 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %32
-%34 = OpLoad %16 %33
-%35 = OpLoad %24 %g_sAniso
-%36 = OpSampledImage %26 %34 %35
-%55 = OpFunctionCall %uint %40 %uint_2 %uint_2
-%57 = OpULessThan %bool %32 %55
-OpSelectionMerge %58 None
-OpBranchConditional %57 %59 %60
-%59 = OpLabel
-%61 = OpLoad %16 %33
-%62 = OpSampledImage %26 %61 %35
-%136 = OpFunctionCall %uint %118 %uint_0 %uint_1 %uint_2 %32
-%137 = OpULessThan %bool %uint_0 %136
-OpSelectionMerge %138 None
-OpBranchConditional %137 %139 %140
-%139 = OpLabel
-%141 = OpLoad %16 %33
-%142 = OpSampledImage %26 %141 %35
-%143 = OpImageSampleImplicitLod %v4float %142 %30
-OpBranch %138
-%140 = OpLabel
-%144 = OpFunctionCall %void %64 %uint_59 %uint_1 %32 %uint_0
-OpBranch %138
-%138 = OpLabel
-%145 = OpPhi %v4float %143 %139 %116 %140
-OpBranch %58
-%60 = OpLabel
-%115 = OpFunctionCall %void %64 %uint_59 %uint_0 %32 %55
-OpBranch %58
-%58 = OpLabel
-%117 = OpPhi %v4float %145 %138 %116 %60
-OpStore %_entryPointOutput_vColor %117
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%40 = OpFunction %uint None %41
-%42 = OpFunctionParameter %uint
-%43 = OpFunctionParameter %uint
-%44 = OpLabel
-%50 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %42
-%51 = OpLoad %uint %50
-%52 = OpIAdd %uint %51 %43
-%53 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %52
-%54 = OpLoad %uint %53
-OpReturnValue %54
-OpFunctionEnd
-%64 = OpFunction %void None %65
-%66 = OpFunctionParameter %uint
-%67 = OpFunctionParameter %uint
-%68 = OpFunctionParameter %uint
-%69 = OpFunctionParameter %uint
-%70 = OpLabel
-%74 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_0
-%77 = OpAtomicIAdd %uint %74 %uint_4 %uint_0 %uint_10
-%78 = OpIAdd %uint %77 %uint_10
-%79 = OpArrayLength %uint %73 1
-%80 = OpULessThanEqual %bool %78 %79
-OpSelectionMerge %81 None
-OpBranchConditional %80 %82 %81
-%82 = OpLabel
-%83 = OpIAdd %uint %77 %uint_0
-%84 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %83
-OpStore %84 %uint_10
-%86 = OpIAdd %uint %77 %uint_1
-%87 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %86
-OpStore %87 %uint_23
-%88 = OpIAdd %uint %77 %uint_2
-%89 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %88
-OpStore %89 %66
-%91 = OpIAdd %uint %77 %uint_3
-%92 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %91
-OpStore %92 %uint_4
-%95 = OpLoad %v4float %gl_FragCoord
-%97 = OpBitcast %v4uint %95
-%98 = OpCompositeExtract %uint %97 0
-%99 = OpIAdd %uint %77 %uint_4
-%100 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %99
-OpStore %100 %98
-%101 = OpCompositeExtract %uint %97 1
-%103 = OpIAdd %uint %77 %uint_5
-%104 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %103
-OpStore %104 %101
-%106 = OpIAdd %uint %77 %uint_7
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %106
-OpStore %107 %67
-%109 = OpIAdd %uint %77 %uint_8
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %109
-OpStore %110 %68
-%112 = OpIAdd %uint %77 %uint_9
-%113 = OpAccessChain %_ptr_StorageBuffer_uint %73 %uint_1 %112
-OpStore %113 %69
-OpBranch %81
-%81 = OpLabel
-OpReturn
-OpFunctionEnd
-%118 = OpFunction %uint None %119
-%120 = OpFunctionParameter %uint
-%121 = OpFunctionParameter %uint
-%122 = OpFunctionParameter %uint
-%123 = OpFunctionParameter %uint
-%124 = OpLabel
-%125 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %120
-%126 = OpLoad %uint %125
-%127 = OpIAdd %uint %126 %121
-%128 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %127
-%129 = OpLoad %uint %128
-%130 = OpIAdd %uint %129 %122
-%131 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %130
-%132 = OpLoad %uint %131
-%133 = OpIAdd %uint %132 %123
-%134 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0 %133
-%135 = OpLoad %uint %134
-OpReturnValue %135
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptor) {
@@ -2569,11 +1652,14 @@
   // does not have the extension enabled because it does not contain a
   // runtime array. This is the same shader as NoInstrumentNonBindless.
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
+; CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
 OpExecutionMode %MainPs OriginUpperLeft
 OpSource HLSL 500
 OpName %MainPs "MainPs"
@@ -2587,6 +1673,9 @@
 OpDecorate %g_sAniso Binding 0
 OpDecorate %i_vTextureCoords Location 0
 OpDecorate %_entryPointOutput_vColor Location 0
+; check: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; check: OpDecorate %gl_FragCoord BuiltIn FragCoord
 %void = OpTypeVoid
 %8 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -2603,86 +1692,23 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
+; CHECK: %uint = OpTypeInt 32 0
+; CHECK: %28 = OpTypeFunction %uint %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %61 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %113 = OpConstantNull %v4float
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord
-OpExecutionMode %MainPs OriginUpperLeft
-OpSource HLSL 500
-OpName %MainPs "MainPs"
-OpName %g_tColor "g_tColor"
-OpName %g_sAniso "g_sAniso"
-OpName %i_vTextureCoords "i.vTextureCoords"
-OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
-OpDecorate %g_tColor DescriptorSet 0
-OpDecorate %g_tColor Binding 0
-OpDecorate %g_sAniso DescriptorSet 0
-OpDecorate %g_sAniso Binding 0
-OpDecorate %i_vTextureCoords Location 0
-OpDecorate %_entryPointOutput_vColor Location 0
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_35 Block
-OpMemberDecorate %_struct_35 0 Offset 0
-OpDecorate %37 DescriptorSet 7
-OpDecorate %37 Binding 1
-OpDecorate %_struct_67 Block
-OpMemberDecorate %_struct_67 0 Offset 0
-OpMemberDecorate %_struct_67 1 Offset 4
-OpDecorate %69 DescriptorSet 7
-OpDecorate %69 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-%void = OpTypeVoid
-%8 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v2float = OpTypeVector %float 2
-%v4float = OpTypeVector %float 4
-%12 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
-%g_tColor = OpVariable %_ptr_UniformConstant_12 UniformConstant
-%14 = OpTypeSampler
-%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
-%g_sAniso = OpVariable %_ptr_UniformConstant_14 UniformConstant
-%16 = OpTypeSampledImage %12
-%_ptr_Input_v2float = OpTypePointer Input %v2float
-%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-%uint = OpTypeInt 32 0
-%uint_0 = OpConstant %uint 0
-%28 = OpTypeFunction %uint %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_35 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_35 = OpTypePointer StorageBuffer %_struct_35
-%37 = OpVariable %_ptr_StorageBuffer__struct_35 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%uint_1 = OpConstant %uint 1
-%61 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_67 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_67 = OpTypePointer StorageBuffer %_struct_67
-%69 = OpVariable %_ptr_StorageBuffer__struct_67 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_39 = OpConstant %uint 39
-%113 = OpConstantNull %v4float
-)";
-
-  const std::string func_before =
-      R"(%MainPs = OpFunction %void None %8
+  const std::string main_func = R"(
+%MainPs = OpFunction %void None %8
 %19 = OpLabel
 %20 = OpLoad %v2float %i_vTextureCoords
 %21 = OpLoad %12 %g_tColor
@@ -2690,111 +1716,33 @@
 %23 = OpSampledImage %16 %21 %22
 %24 = OpImageSampleImplicitLod %v4float %23 %20
 OpStore %_entryPointOutput_vColor %24
+; CHECK-NOT: %24 = OpImageSampleImplicitLod %v4float %23 %20
+; CHECK-NOT: OpStore %_entryPointOutput_vColor %24
+; CHECK: %50 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %52 = OpULessThan %bool %uint_0 %50
+; CHECK: OpSelectionMerge %54 None
+; CHECK: OpBranchConditional %52 %55 %56
+; CHECK: %55 = OpLabel
+; CHECK: %57 = OpLoad %12 %g_tColor
+; CHECK: %58 = OpSampledImage %16 %57 %22
+; CHECK: %59 = OpImageSampleImplicitLod %v4float %58 %20
+; CHECK: OpBranch %54
+; CHECK: %56 = OpLabel
+; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_39 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %54
+; CHECK: %54 = OpLabel
+; CHECK: %114 = OpPhi %v4float %59 %55 %113 %56
+; CHECK: OpStore %_entryPointOutput_vColor %114
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%MainPs = OpFunction %void None %8
-%19 = OpLabel
-%20 = OpLoad %v2float %i_vTextureCoords
-%21 = OpLoad %12 %g_tColor
-%22 = OpLoad %14 %g_sAniso
-%23 = OpSampledImage %16 %21 %22
-%50 = OpFunctionCall %uint %27 %uint_0 %uint_0 %uint_0 %uint_0
-%52 = OpULessThan %bool %uint_0 %50
-OpSelectionMerge %54 None
-OpBranchConditional %52 %55 %56
-%55 = OpLabel
-%57 = OpLoad %12 %g_tColor
-%58 = OpSampledImage %16 %57 %22
-%59 = OpImageSampleImplicitLod %v4float %58 %20
-OpBranch %54
-%56 = OpLabel
-%112 = OpFunctionCall %void %60 %uint_39 %uint_1 %uint_0 %uint_0
-OpBranch %54
-%54 = OpLabel
-%114 = OpPhi %v4float %59 %55 %113 %56
-OpStore %_entryPointOutput_vColor %114
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%27 = OpFunction %uint None %28
-%29 = OpFunctionParameter %uint
-%30 = OpFunctionParameter %uint
-%31 = OpFunctionParameter %uint
-%32 = OpFunctionParameter %uint
-%33 = OpLabel
-%39 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %29
-%40 = OpLoad %uint %39
-%41 = OpIAdd %uint %40 %30
-%42 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %41
-%43 = OpLoad %uint %42
-%44 = OpIAdd %uint %43 %31
-%45 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %44
-%46 = OpLoad %uint %45
-%47 = OpIAdd %uint %46 %32
-%48 = OpAccessChain %_ptr_StorageBuffer_uint %37 %uint_0 %47
-%49 = OpLoad %uint %48
-OpReturnValue %49
-OpFunctionEnd
-%60 = OpFunction %void None %61
-%62 = OpFunctionParameter %uint
-%63 = OpFunctionParameter %uint
-%64 = OpFunctionParameter %uint
-%65 = OpFunctionParameter %uint
-%66 = OpLabel
-%70 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_0
-%73 = OpAtomicIAdd %uint %70 %uint_4 %uint_0 %uint_10
-%74 = OpIAdd %uint %73 %uint_10
-%75 = OpArrayLength %uint %69 1
-%76 = OpULessThanEqual %bool %74 %75
-OpSelectionMerge %77 None
-OpBranchConditional %76 %78 %77
-%78 = OpLabel
-%79 = OpIAdd %uint %73 %uint_0
-%80 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %79
-OpStore %80 %uint_10
-%82 = OpIAdd %uint %73 %uint_1
-%83 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %82
-OpStore %83 %uint_23
-%85 = OpIAdd %uint %73 %uint_2
-%86 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %85
-OpStore %86 %62
-%88 = OpIAdd %uint %73 %uint_3
-%89 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %88
-OpStore %89 %uint_4
-%92 = OpLoad %v4float %gl_FragCoord
-%94 = OpBitcast %v4uint %92
-%95 = OpCompositeExtract %uint %94 0
-%96 = OpIAdd %uint %73 %uint_4
-%97 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %96
-OpStore %97 %95
-%98 = OpCompositeExtract %uint %94 1
-%100 = OpIAdd %uint %73 %uint_5
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %100
-OpStore %101 %98
-%103 = OpIAdd %uint %73 %uint_7
-%104 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %103
-OpStore %104 %63
-%106 = OpIAdd %uint %73 %uint_8
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %106
-OpStore %107 %64
-%109 = OpIAdd %uint %73 %uint_9
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_1 %109
-OpStore %110 %65
-OpBranch %77
-%77 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead4 + kStreamWrite4Frag;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest, SPV14AddToEntryPoint) {
@@ -2927,15 +1875,18 @@
   //     b = uniformBuffer[nu_ii].a;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability ShaderNonUniform
 OpCapability RuntimeDescriptorArray
 OpCapability UniformBufferArrayNonUniformIndexing
 OpExtension "SPV_EXT_descriptor_indexing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %b %nu_ii
+; CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
@@ -2955,6 +1906,12 @@
 OpDecorate %nu_ii NonUniform
 OpDecorate %16 NonUniform
 OpDecorate %20 NonUniform
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + R"(
+; CHECK: OpDecorate %130 NonUniform
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
+; CHECK: OpDecorate %127 NonUniform
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -2969,229 +1926,69 @@
 %nu_ii = OpVariable %_ptr_Input_int Input
 %int_0 = OpConstant %int 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %uint = OpTypeInt 32 0
+; CHECK: %26 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %49 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v4float = OpTypeVector %float 4
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %101 = OpConstantNull %float
+; CHECK: %105 = OpTypeFunction %uint %uint %uint %uint %uint
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability ShaderNonUniform
-OpCapability RuntimeDescriptorArray
-OpCapability UniformBufferArrayNonUniformIndexing
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpName %main "main"
-OpName %b "b"
-OpName %uname "uname"
-OpMemberName %uname 0 "a"
-OpName %uniformBuffer "uniformBuffer"
-OpName %nu_ii "nu_ii"
-OpDecorate %b Location 0
-OpMemberDecorate %uname 0 Offset 0
-OpDecorate %uname Block
-OpDecorate %uniformBuffer DescriptorSet 0
-OpDecorate %uniformBuffer Binding 3
-OpDecorate %nu_ii Flat
-OpDecorate %nu_ii Location 0
-OpDecorate %nu_ii NonUniform
-OpDecorate %7 NonUniform
-OpDecorate %102 NonUniform
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_31 Block
-OpMemberDecorate %_struct_31 0 Offset 0
-OpDecorate %33 DescriptorSet 7
-OpDecorate %33 Binding 1
-OpDecorate %130 NonUniform
-OpDecorate %_struct_55 Block
-OpMemberDecorate %_struct_55 0 Offset 0
-OpMemberDecorate %_struct_55 1 Offset 4
-OpDecorate %57 DescriptorSet 7
-OpDecorate %57 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-OpDecorate %127 NonUniform
-%void = OpTypeVoid
-%10 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Output_float = OpTypePointer Output %float
-%b = OpVariable %_ptr_Output_float Output
-%uname = OpTypeStruct %float
-%_runtimearr_uname = OpTypeRuntimeArray %uname
-%_ptr_Uniform__runtimearr_uname = OpTypePointer Uniform %_runtimearr_uname
-%uniformBuffer = OpVariable %_ptr_Uniform__runtimearr_uname Uniform
-%int = OpTypeInt 32 1
-%_ptr_Input_int = OpTypePointer Input %int
-%nu_ii = OpVariable %_ptr_Input_int Input
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint = OpTypeInt 32 0
-%uint_0 = OpConstant %uint 0
-%uint_1 = OpConstant %uint 1
-%uint_3 = OpConstant %uint 3
-%26 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_31 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31
-%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%49 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_55 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55
-%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%v4float = OpTypeVector %float 4
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_45 = OpConstant %uint 45
-%101 = OpConstantNull %float
-%105 = OpTypeFunction %uint %uint %uint %uint %uint
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %16 = OpLoad %int %nu_ii
 %19 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %16 %int_0
 %20 = OpLoad %float %19
 OpStore %b %20
+; CHECK-NOT: %20 = OpLoad %float %19
+; CHECK-NOT: OpStore %b %20
+; CHECK: %40 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_3
+; CHECK: %42 = OpULessThan %bool %7 %40
+; CHECK: OpSelectionMerge %43 None
+; CHECK: OpBranchConditional %42 %44 %45
+; CHECK: %44 = OpLabel
+; CHECK: %103 = OpBitcast %uint %7
+; CHECK: %122 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %103
+; CHECK: %123 = OpULessThan %bool %uint_0 %122
+; CHECK: OpSelectionMerge %124 None
+; CHECK: OpBranchConditional %123 %125 %126
+; CHECK: %125 = OpLabel
+; CHECK: %127 = OpLoad %float %20
+; CHECK: OpBranch %124
+; CHECK: %126 = OpLabel
+; CHECK: %128 = OpBitcast %uint %7
+; CHECK: %129 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_1 %128 %uint_0
+; CHECK: OpBranch %124
+; CHECK: %124 = OpLabel
+; CHECK: %130 = OpPhi %float %127 %125 %101 %126
+; CHECK: OpBranch %43
+; CHECK: %45 = OpLabel
+; CHECK: %47 = OpBitcast %uint %7
+; CHECK: %100 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 %47 %40
+; CHECK: OpBranch %43
+; CHECK: %43 = OpLabel
+; CHECK: %102 = OpPhi %float %130 %124 %101 %45
+; CHECK: OpStore %b %102
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %10
-%19 = OpLabel
-%7 = OpLoad %int %nu_ii
-%20 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %7 %int_0
-%40 = OpFunctionCall %uint %25 %uint_1 %uint_3
-%42 = OpULessThan %bool %7 %40
-OpSelectionMerge %43 None
-OpBranchConditional %42 %44 %45
-%44 = OpLabel
-%103 = OpBitcast %uint %7
-%122 = OpFunctionCall %uint %104 %uint_0 %uint_0 %uint_3 %103
-%123 = OpULessThan %bool %uint_0 %122
-OpSelectionMerge %124 None
-OpBranchConditional %123 %125 %126
-%125 = OpLabel
-%127 = OpLoad %float %20
-OpBranch %124
-%126 = OpLabel
-%128 = OpBitcast %uint %7
-%129 = OpFunctionCall %void %48 %uint_45 %uint_1 %128 %uint_0
-OpBranch %124
-%124 = OpLabel
-%130 = OpPhi %float %127 %125 %101 %126
-OpBranch %43
-%45 = OpLabel
-%47 = OpBitcast %uint %7
-%100 = OpFunctionCall %void %48 %uint_45 %uint_0 %47 %40
-OpBranch %43
-%43 = OpLabel
-%102 = OpPhi %float %130 %124 %101 %45
-OpStore %b %102
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%25 = OpFunction %uint None %26
-%27 = OpFunctionParameter %uint
-%28 = OpFunctionParameter %uint
-%29 = OpLabel
-%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27
-%36 = OpLoad %uint %35
-%37 = OpIAdd %uint %36 %28
-%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37
-%39 = OpLoad %uint %38
-OpReturnValue %39
-OpFunctionEnd
-%48 = OpFunction %void None %49
-%50 = OpFunctionParameter %uint
-%51 = OpFunctionParameter %uint
-%52 = OpFunctionParameter %uint
-%53 = OpFunctionParameter %uint
-%54 = OpLabel
-%58 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0
-%61 = OpAtomicIAdd %uint %58 %uint_4 %uint_0 %uint_10
-%62 = OpIAdd %uint %61 %uint_10
-%63 = OpArrayLength %uint %57 1
-%64 = OpULessThanEqual %bool %62 %63
-OpSelectionMerge %65 None
-OpBranchConditional %64 %66 %65
-%66 = OpLabel
-%67 = OpIAdd %uint %61 %uint_0
-%68 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %67
-OpStore %68 %uint_10
-%70 = OpIAdd %uint %61 %uint_1
-%71 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %70
-OpStore %71 %uint_23
-%73 = OpIAdd %uint %61 %uint_2
-%74 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %73
-OpStore %74 %50
-%75 = OpIAdd %uint %61 %uint_3
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75
-OpStore %76 %uint_4
-%80 = OpLoad %v4float %gl_FragCoord
-%82 = OpBitcast %v4uint %80
-%83 = OpCompositeExtract %uint %82 0
-%84 = OpIAdd %uint %61 %uint_4
-%85 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %84
-OpStore %85 %83
-%86 = OpCompositeExtract %uint %82 1
-%88 = OpIAdd %uint %61 %uint_5
-%89 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %88
-OpStore %89 %86
-%91 = OpIAdd %uint %61 %uint_7
-%92 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %91
-OpStore %92 %51
-%94 = OpIAdd %uint %61 %uint_8
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %94
-OpStore %95 %52
-%97 = OpIAdd %uint %61 %uint_9
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %97
-OpStore %98 %53
-OpBranch %65
-%65 = OpLabel
-OpReturn
-OpFunctionEnd
-%104 = OpFunction %uint None %105
-%106 = OpFunctionParameter %uint
-%107 = OpFunctionParameter %uint
-%108 = OpFunctionParameter %uint
-%109 = OpFunctionParameter %uint
-%110 = OpLabel
-%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %106
-%112 = OpLoad %uint %111
-%113 = OpIAdd %uint %112 %107
-%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113
-%115 = OpLoad %uint %114
-%116 = OpIAdd %uint %115 %108
-%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116
-%118 = OpLoad %uint %117
-%119 = OpIAdd %uint %118 %109
-%120 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %119
-%121 = OpLoad %uint %120
-OpReturnValue %121
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArrayDeprecated) {
@@ -3208,15 +2005,18 @@
   //     b = storageBuffer[nu_ii].b;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability ShaderNonUniform
 OpCapability RuntimeDescriptorArray
 OpCapability StorageBufferArrayNonUniformIndexing
 OpExtension "SPV_EXT_descriptor_indexing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %b %nu_ii
+; CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
@@ -3236,6 +2036,12 @@
 OpDecorate %nu_ii NonUniform
 OpDecorate %16 NonUniform
 OpDecorate %20 NonUniform
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + R"(
+; CHECK: OpDecorate %130 NonUniform
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
+; CHECK: OpDecorate %127 NonUniform
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -3250,243 +2056,86 @@
 %nu_ii = OpVariable %_ptr_Input_int Input
 %int_0 = OpConstant %int 0
 %_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+; CHECK: %uint = OpTypeInt 32 0
+; CHECK: %26 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %49 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v4float = OpTypeVector %float 4
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %101 = OpConstantNull %float
+; CHECK: %105 = OpTypeFunction %uint %uint %uint %uint %uint
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability ShaderNonUniform
-OpCapability RuntimeDescriptorArray
-OpCapability StorageBufferArrayNonUniformIndexing
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpName %main "main"
-OpName %b "b"
-OpName %bname "bname"
-OpMemberName %bname 0 "a"
-OpName %storageBuffer "storageBuffer"
-OpName %nu_ii "nu_ii"
-OpDecorate %b Location 0
-OpMemberDecorate %bname 0 Offset 0
-OpDecorate %bname Block
-OpDecorate %storageBuffer DescriptorSet 0
-OpDecorate %storageBuffer Binding 3
-OpDecorate %nu_ii Flat
-OpDecorate %nu_ii Location 0
-OpDecorate %nu_ii NonUniform
-OpDecorate %7 NonUniform
-OpDecorate %102 NonUniform
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_31 Block
-OpMemberDecorate %_struct_31 0 Offset 0
-OpDecorate %33 DescriptorSet 7
-OpDecorate %33 Binding 1
-OpDecorate %130 NonUniform
-OpDecorate %_struct_55 Block
-OpMemberDecorate %_struct_55 0 Offset 0
-OpMemberDecorate %_struct_55 1 Offset 4
-OpDecorate %57 DescriptorSet 7
-OpDecorate %57 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-OpDecorate %127 NonUniform
-%void = OpTypeVoid
-%10 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Output_float = OpTypePointer Output %float
-%b = OpVariable %_ptr_Output_float Output
-%bname = OpTypeStruct %float
-%_runtimearr_bname = OpTypeRuntimeArray %bname
-%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname
-%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer
-%int = OpTypeInt 32 1
-%_ptr_Input_int = OpTypePointer Input %int
-%nu_ii = OpVariable %_ptr_Input_int Input
-%int_0 = OpConstant %int 0
-%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
-%uint = OpTypeInt 32 0
-%uint_0 = OpConstant %uint 0
-%uint_1 = OpConstant %uint 1
-%uint_3 = OpConstant %uint 3
-%26 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_31 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31
-%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%49 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_55 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55
-%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%v4float = OpTypeVector %float 4
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_45 = OpConstant %uint 45
-%101 = OpConstantNull %float
-%105 = OpTypeFunction %uint %uint %uint %uint %uint
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %16 = OpLoad %int %nu_ii
 %19 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %16 %int_0
 %20 = OpLoad %float %19
 OpStore %b %20
+; CHECK-NOT: %20 = OpLoad %float %19
+; CHECK-NOT: OpStore %b %20
+; CHECK: %40 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_3
+; CHECK: %42 = OpULessThan %bool %7 %40
+; CHECK: OpSelectionMerge %43 None
+; CHECK: OpBranchConditional %42 %44 %45
+; CHECK: %44 = OpLabel
+; CHECK: %103 = OpBitcast %uint %7
+; CHECK: %122 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %103
+; CHECK: %123 = OpULessThan %bool %uint_0 %122
+; CHECK: OpSelectionMerge %124 None
+; CHECK: OpBranchConditional %123 %125 %126
+; CHECK: %125 = OpLabel
+; CHECK: %127 = OpLoad %float %20
+; CHECK: OpBranch %124
+; CHECK: %126 = OpLabel
+; CHECK: %128 = OpBitcast %uint %7
+; CHECK: %129 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_1 %128 %uint_0
+; CHECK: OpBranch %124
+; CHECK: %124 = OpLabel
+; CHECK: %130 = OpPhi %float %127 %125 %101 %126
+; CHECK: OpBranch %43
+; CHECK: %45 = OpLabel
+; CHECK: %47 = OpBitcast %uint %7
+; CHECK: %100 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 %47 %40
+; CHECK: OpBranch %43
+; CHECK: %43 = OpLabel
+; CHECK: %102 = OpPhi %float %130 %124 %101 %45
+; CHECK: OpStore %b %102
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %10
-%19 = OpLabel
-%7 = OpLoad %int %nu_ii
-%20 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %7 %int_0
-%40 = OpFunctionCall %uint %25 %uint_1 %uint_3
-%42 = OpULessThan %bool %7 %40
-OpSelectionMerge %43 None
-OpBranchConditional %42 %44 %45
-%44 = OpLabel
-%103 = OpBitcast %uint %7
-%122 = OpFunctionCall %uint %104 %uint_0 %uint_0 %uint_3 %103
-%123 = OpULessThan %bool %uint_0 %122
-OpSelectionMerge %124 None
-OpBranchConditional %123 %125 %126
-%125 = OpLabel
-%127 = OpLoad %float %20
-OpBranch %124
-%126 = OpLabel
-%128 = OpBitcast %uint %7
-%129 = OpFunctionCall %void %48 %uint_45 %uint_1 %128 %uint_0
-OpBranch %124
-%124 = OpLabel
-%130 = OpPhi %float %127 %125 %101 %126
-OpBranch %43
-%45 = OpLabel
-%47 = OpBitcast %uint %7
-%100 = OpFunctionCall %void %48 %uint_45 %uint_0 %47 %40
-OpBranch %43
-%43 = OpLabel
-%102 = OpPhi %float %130 %124 %101 %45
-OpStore %b %102
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%25 = OpFunction %uint None %26
-%27 = OpFunctionParameter %uint
-%28 = OpFunctionParameter %uint
-%29 = OpLabel
-%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27
-%36 = OpLoad %uint %35
-%37 = OpIAdd %uint %36 %28
-%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37
-%39 = OpLoad %uint %38
-OpReturnValue %39
-OpFunctionEnd
-%48 = OpFunction %void None %49
-%50 = OpFunctionParameter %uint
-%51 = OpFunctionParameter %uint
-%52 = OpFunctionParameter %uint
-%53 = OpFunctionParameter %uint
-%54 = OpLabel
-%58 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0
-%61 = OpAtomicIAdd %uint %58 %uint_4 %uint_0 %uint_10
-%62 = OpIAdd %uint %61 %uint_10
-%63 = OpArrayLength %uint %57 1
-%64 = OpULessThanEqual %bool %62 %63
-OpSelectionMerge %65 None
-OpBranchConditional %64 %66 %65
-%66 = OpLabel
-%67 = OpIAdd %uint %61 %uint_0
-%68 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %67
-OpStore %68 %uint_10
-%70 = OpIAdd %uint %61 %uint_1
-%71 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %70
-OpStore %71 %uint_23
-%73 = OpIAdd %uint %61 %uint_2
-%74 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %73
-OpStore %74 %50
-%75 = OpIAdd %uint %61 %uint_3
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75
-OpStore %76 %uint_4
-%80 = OpLoad %v4float %gl_FragCoord
-%82 = OpBitcast %v4uint %80
-%83 = OpCompositeExtract %uint %82 0
-%84 = OpIAdd %uint %61 %uint_4
-%85 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %84
-OpStore %85 %83
-%86 = OpCompositeExtract %uint %82 1
-%88 = OpIAdd %uint %61 %uint_5
-%89 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %88
-OpStore %89 %86
-%91 = OpIAdd %uint %61 %uint_7
-%92 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %91
-OpStore %92 %51
-%94 = OpIAdd %uint %61 %uint_8
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %94
-OpStore %95 %52
-%97 = OpIAdd %uint %61 %uint_9
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %97
-OpStore %98 %53
-OpBranch %65
-%65 = OpLabel
-OpReturn
-OpFunctionEnd
-%104 = OpFunction %uint None %105
-%106 = OpFunctionParameter %uint
-%107 = OpFunctionParameter %uint
-%108 = OpFunctionParameter %uint
-%109 = OpFunctionParameter %uint
-%110 = OpLabel
-%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %106
-%112 = OpLoad %uint %111
-%113 = OpIAdd %uint %112 %107
-%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113
-%115 = OpLoad %uint %114
-%116 = OpIAdd %uint %115 %108
-%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116
-%118 = OpLoad %uint %117
-%119 = OpIAdd %uint %118 %109
-%120 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %119
-%121 = OpLoad %uint %120
-OpReturnValue %121
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArray) {
   // Same as Deprecated but declaring as StorageBuffer Block
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability ShaderNonUniform
 OpCapability RuntimeDescriptorArray
 OpCapability StorageBufferArrayNonUniformIndexing
 OpExtension "SPV_EXT_descriptor_indexing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %b %nu_ii
+; CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
@@ -3506,6 +2155,12 @@
 OpDecorate %nu_ii NonUniform
 OpDecorate %16 NonUniform
 OpDecorate %20 NonUniform
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + R"(
+; CHECK: OpDecorate %130 NonUniform
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
+; CHECK: OpDecorate %127 NonUniform
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -3520,229 +2175,69 @@
 %nu_ii = OpVariable %_ptr_Input_int Input
 %int_0 = OpConstant %int 0
 %_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+; CHECK: %uint = OpTypeInt 32 0
+; CHECK: %26 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %49 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v4float = OpTypeVector %float 4
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %101 = OpConstantNull %float
+; CHECK: %105 = OpTypeFunction %uint %uint %uint %uint %uint
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability ShaderNonUniform
-OpCapability RuntimeDescriptorArray
-OpCapability StorageBufferArrayNonUniformIndexing
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpName %main "main"
-OpName %b "b"
-OpName %bname "bname"
-OpMemberName %bname 0 "a"
-OpName %storageBuffer "storageBuffer"
-OpName %nu_ii "nu_ii"
-OpDecorate %b Location 0
-OpMemberDecorate %bname 0 Offset 0
-OpDecorate %bname Block
-OpDecorate %storageBuffer DescriptorSet 0
-OpDecorate %storageBuffer Binding 3
-OpDecorate %nu_ii Flat
-OpDecorate %nu_ii Location 0
-OpDecorate %nu_ii NonUniform
-OpDecorate %7 NonUniform
-OpDecorate %102 NonUniform
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_31 Block
-OpMemberDecorate %_struct_31 0 Offset 0
-OpDecorate %33 DescriptorSet 7
-OpDecorate %33 Binding 1
-OpDecorate %130 NonUniform
-OpDecorate %_struct_55 Block
-OpMemberDecorate %_struct_55 0 Offset 0
-OpMemberDecorate %_struct_55 1 Offset 4
-OpDecorate %57 DescriptorSet 7
-OpDecorate %57 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-OpDecorate %127 NonUniform
-%void = OpTypeVoid
-%10 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Output_float = OpTypePointer Output %float
-%b = OpVariable %_ptr_Output_float Output
-%bname = OpTypeStruct %float
-%_runtimearr_bname = OpTypeRuntimeArray %bname
-%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname
-%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer
-%int = OpTypeInt 32 1
-%_ptr_Input_int = OpTypePointer Input %int
-%nu_ii = OpVariable %_ptr_Input_int Input
-%int_0 = OpConstant %int 0
-%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
-%uint = OpTypeInt 32 0
-%uint_0 = OpConstant %uint 0
-%uint_1 = OpConstant %uint 1
-%uint_3 = OpConstant %uint 3
-%26 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_31 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31
-%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%49 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_55 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_55 = OpTypePointer StorageBuffer %_struct_55
-%57 = OpVariable %_ptr_StorageBuffer__struct_55 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%v4float = OpTypeVector %float 4
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_45 = OpConstant %uint 45
-%101 = OpConstantNull %float
-%105 = OpTypeFunction %uint %uint %uint %uint %uint
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %16 = OpLoad %int %nu_ii
 %19 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %16 %int_0
 %20 = OpLoad %float %19
 OpStore %b %20
+; CHECK-NOT: %20 = OpLoad %float %19
+; CHECK-NOT: OpStore %b %20
+; CHECK: %40 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_3
+; CHECK: %42 = OpULessThan %bool %7 %40
+; CHECK: OpSelectionMerge %43 None
+; CHECK: OpBranchConditional %42 %44 %45
+; CHECK: %44 = OpLabel
+; CHECK: %103 = OpBitcast %uint %7
+; CHECK: %122 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %103
+; CHECK: %123 = OpULessThan %bool %uint_0 %122
+; CHECK: OpSelectionMerge %124 None
+; CHECK: OpBranchConditional %123 %125 %126
+; CHECK: %125 = OpLabel
+; CHECK: %127 = OpLoad %float %20
+; CHECK: OpBranch %124
+; CHECK: %126 = OpLabel
+; CHECK: %128 = OpBitcast %uint %7
+; CHECK: %129 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_1 %128 %uint_0
+; CHECK: OpBranch %124
+; CHECK: %124 = OpLabel
+; CHECK: %130 = OpPhi %float %127 %125 %101 %126
+; CHECK: OpBranch %43
+; CHECK: %45 = OpLabel
+; CHECK: %47 = OpBitcast %uint %7
+; CHECK: %100 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 %47 %40
+; CHECK: OpBranch %43
+; CHECK: %43 = OpLabel
+; CHECK: %102 = OpPhi %float %130 %124 %101 %45
+; CHECK: OpStore %b %102
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %10
-%19 = OpLabel
-%7 = OpLoad %int %nu_ii
-%20 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %7 %int_0
-%40 = OpFunctionCall %uint %25 %uint_1 %uint_3
-%42 = OpULessThan %bool %7 %40
-OpSelectionMerge %43 None
-OpBranchConditional %42 %44 %45
-%44 = OpLabel
-%103 = OpBitcast %uint %7
-%122 = OpFunctionCall %uint %104 %uint_0 %uint_0 %uint_3 %103
-%123 = OpULessThan %bool %uint_0 %122
-OpSelectionMerge %124 None
-OpBranchConditional %123 %125 %126
-%125 = OpLabel
-%127 = OpLoad %float %20
-OpBranch %124
-%126 = OpLabel
-%128 = OpBitcast %uint %7
-%129 = OpFunctionCall %void %48 %uint_45 %uint_1 %128 %uint_0
-OpBranch %124
-%124 = OpLabel
-%130 = OpPhi %float %127 %125 %101 %126
-OpBranch %43
-%45 = OpLabel
-%47 = OpBitcast %uint %7
-%100 = OpFunctionCall %void %48 %uint_45 %uint_0 %47 %40
-OpBranch %43
-%43 = OpLabel
-%102 = OpPhi %float %130 %124 %101 %45
-OpStore %b %102
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%25 = OpFunction %uint None %26
-%27 = OpFunctionParameter %uint
-%28 = OpFunctionParameter %uint
-%29 = OpLabel
-%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27
-%36 = OpLoad %uint %35
-%37 = OpIAdd %uint %36 %28
-%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37
-%39 = OpLoad %uint %38
-OpReturnValue %39
-OpFunctionEnd
-%48 = OpFunction %void None %49
-%50 = OpFunctionParameter %uint
-%51 = OpFunctionParameter %uint
-%52 = OpFunctionParameter %uint
-%53 = OpFunctionParameter %uint
-%54 = OpLabel
-%58 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_0
-%61 = OpAtomicIAdd %uint %58 %uint_4 %uint_0 %uint_10
-%62 = OpIAdd %uint %61 %uint_10
-%63 = OpArrayLength %uint %57 1
-%64 = OpULessThanEqual %bool %62 %63
-OpSelectionMerge %65 None
-OpBranchConditional %64 %66 %65
-%66 = OpLabel
-%67 = OpIAdd %uint %61 %uint_0
-%68 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %67
-OpStore %68 %uint_10
-%70 = OpIAdd %uint %61 %uint_1
-%71 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %70
-OpStore %71 %uint_23
-%73 = OpIAdd %uint %61 %uint_2
-%74 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %73
-OpStore %74 %50
-%75 = OpIAdd %uint %61 %uint_3
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %75
-OpStore %76 %uint_4
-%80 = OpLoad %v4float %gl_FragCoord
-%82 = OpBitcast %v4uint %80
-%83 = OpCompositeExtract %uint %82 0
-%84 = OpIAdd %uint %61 %uint_4
-%85 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %84
-OpStore %85 %83
-%86 = OpCompositeExtract %uint %82 1
-%88 = OpIAdd %uint %61 %uint_5
-%89 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %88
-OpStore %89 %86
-%91 = OpIAdd %uint %61 %uint_7
-%92 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %91
-OpStore %92 %51
-%94 = OpIAdd %uint %61 %uint_8
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %94
-OpStore %95 %52
-%97 = OpIAdd %uint %61 %uint_9
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %57 %uint_1 %97
-OpStore %98 %53
-OpBranch %65
-%65 = OpLabel
-OpReturn
-OpFunctionEnd
-%104 = OpFunction %uint None %105
-%106 = OpFunctionParameter %uint
-%107 = OpFunctionParameter %uint
-%108 = OpFunctionParameter %uint
-%109 = OpFunctionParameter %uint
-%110 = OpLabel
-%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %106
-%112 = OpLoad %uint %111
-%113 = OpIAdd %uint %112 %107
-%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113
-%115 = OpLoad %uint %114
-%116 = OpIAdd %uint %115 %108
-%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116
-%118 = OpLoad %uint %117
-%119 = OpIAdd %uint %118 %109
-%120 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %119
-%121 = OpLoad %uint %120
-OpReturnValue %121
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest, InstInitLoadUBOScalar) {
@@ -3757,12 +2252,15 @@
   //     b = uniformBuffer.a;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpExtension "SPV_EXT_descriptor_indexing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %b
+; CHECK: OpEntryPoint Fragment %main "main" %b %gl_FragCoord
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
@@ -3776,6 +2274,9 @@
 OpDecorate %uname Block
 OpDecorate %uniformBuffer DescriptorSet 0
 OpDecorate %uniformBuffer Binding 3
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -3787,187 +2288,55 @@
 %int = OpTypeInt 32 1
 %int_0 = OpConstant %int 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %int = OpTypeInt 32 1
+; CHECK: %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %uint = OpTypeInt 32 0
+; CHECK: %21 = OpTypeFunction %uint %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %52 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v4float = OpTypeVector %float 4
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %104 = OpConstantNull %float
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %b %gl_FragCoord
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpName %main "main"
-OpName %b "b"
-OpName %uname "uname"
-OpMemberName %uname 0 "a"
-OpName %uniformBuffer "uniformBuffer"
-OpDecorate %b Location 0
-OpMemberDecorate %uname 0 Offset 0
-OpDecorate %uname Block
-OpDecorate %uniformBuffer DescriptorSet 0
-OpDecorate %uniformBuffer Binding 3
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_28 Block
-OpMemberDecorate %_struct_28 0 Offset 0
-OpDecorate %30 DescriptorSet 7
-OpDecorate %30 Binding 1
-OpDecorate %_struct_58 Block
-OpMemberDecorate %_struct_58 0 Offset 0
-OpMemberDecorate %_struct_58 1 Offset 4
-OpDecorate %60 DescriptorSet 7
-OpDecorate %60 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-%void = OpTypeVoid
-%7 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Output_float = OpTypePointer Output %float
-%b = OpVariable %_ptr_Output_float Output
-%uname = OpTypeStruct %float
-%_ptr_Uniform_uname = OpTypePointer Uniform %uname
-%uniformBuffer = OpVariable %_ptr_Uniform_uname Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint = OpTypeInt 32 0
-%uint_0 = OpConstant %uint 0
-%uint_3 = OpConstant %uint 3
-%21 = OpTypeFunction %uint %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_28 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_28 = OpTypePointer StorageBuffer %_struct_28
-%30 = OpVariable %_ptr_StorageBuffer__struct_28 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%uint_1 = OpConstant %uint 1
-%52 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_58 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_58 = OpTypePointer StorageBuffer %_struct_58
-%60 = OpVariable %_ptr_StorageBuffer__struct_58 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%v4float = OpTypeVector %float 4
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_32 = OpConstant %uint 32
-%104 = OpConstantNull %float
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %15 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %int_0
 %16 = OpLoad %float %15
 OpStore %b %16
+; CHECK-NOT: %16 = OpLoad %float %15
+; CHECK-NOT: OpStore %b %16
+; CHECK: %43 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %uint_0
+; CHECK: %45 = OpULessThan %bool %uint_0 %43
+; CHECK: OpSelectionMerge %47 None
+; CHECK: OpBranchConditional %45 %48 %49
+; CHECK: %48 = OpLabel
+; CHECK: %50 = OpLoad %float %15
+; CHECK: OpBranch %47
+; CHECK: %49 = OpLabel
+; CHECK: %103 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_32 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %47
+; CHECK: %47 = OpLabel
+; CHECK: %105 = OpPhi %float %50 %48 %104 %49
+; CHECK: OpStore %b %105
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %7
-%14 = OpLabel
-%15 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %int_0
-%43 = OpFunctionCall %uint %20 %uint_0 %uint_0 %uint_3 %uint_0
-%45 = OpULessThan %bool %uint_0 %43
-OpSelectionMerge %47 None
-OpBranchConditional %45 %48 %49
-%48 = OpLabel
-%50 = OpLoad %float %15
-OpBranch %47
-%49 = OpLabel
-%103 = OpFunctionCall %void %51 %uint_32 %uint_1 %uint_0 %uint_0
-OpBranch %47
-%47 = OpLabel
-%105 = OpPhi %float %50 %48 %104 %49
-OpStore %b %105
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%20 = OpFunction %uint None %21
-%22 = OpFunctionParameter %uint
-%23 = OpFunctionParameter %uint
-%24 = OpFunctionParameter %uint
-%25 = OpFunctionParameter %uint
-%26 = OpLabel
-%32 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %22
-%33 = OpLoad %uint %32
-%34 = OpIAdd %uint %33 %23
-%35 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %34
-%36 = OpLoad %uint %35
-%37 = OpIAdd %uint %36 %24
-%38 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %37
-%39 = OpLoad %uint %38
-%40 = OpIAdd %uint %39 %25
-%41 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0 %40
-%42 = OpLoad %uint %41
-OpReturnValue %42
-OpFunctionEnd
-%51 = OpFunction %void None %52
-%53 = OpFunctionParameter %uint
-%54 = OpFunctionParameter %uint
-%55 = OpFunctionParameter %uint
-%56 = OpFunctionParameter %uint
-%57 = OpLabel
-%61 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_0
-%64 = OpAtomicIAdd %uint %61 %uint_4 %uint_0 %uint_10
-%65 = OpIAdd %uint %64 %uint_10
-%66 = OpArrayLength %uint %60 1
-%67 = OpULessThanEqual %bool %65 %66
-OpSelectionMerge %68 None
-OpBranchConditional %67 %69 %68
-%69 = OpLabel
-%70 = OpIAdd %uint %64 %uint_0
-%71 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %70
-OpStore %71 %uint_10
-%73 = OpIAdd %uint %64 %uint_1
-%74 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %73
-OpStore %74 %uint_23
-%76 = OpIAdd %uint %64 %uint_2
-%77 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %76
-OpStore %77 %53
-%78 = OpIAdd %uint %64 %uint_3
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %78
-OpStore %79 %uint_4
-%83 = OpLoad %v4float %gl_FragCoord
-%85 = OpBitcast %v4uint %83
-%86 = OpCompositeExtract %uint %85 0
-%87 = OpIAdd %uint %64 %uint_4
-%88 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %87
-OpStore %88 %86
-%89 = OpCompositeExtract %uint %85 1
-%91 = OpIAdd %uint %64 %uint_5
-%92 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %91
-OpStore %92 %89
-%94 = OpIAdd %uint %64 %uint_7
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %94
-OpStore %95 %54
-%97 = OpIAdd %uint %64 %uint_8
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %97
-OpStore %98 %55
-%100 = OpIAdd %uint %64 %uint_9
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %100
-OpStore %101 %56
-OpBranch %68
-%68 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead4 + kStreamWrite4Frag;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsInitStoreUnsizedSSBOArray) {
@@ -3984,15 +2353,17 @@
   //     storageBuffer[nu_ii].b = b;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(OpCapability Shader
 OpCapability ShaderNonUniform
 OpCapability RuntimeDescriptorArray
 OpCapability StorageBufferArrayNonUniformIndexing
 OpExtension "SPV_EXT_descriptor_indexing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %nu_ii %b
+; CHECK: OpEntryPoint Fragment %main "main" %nu_ii %b %gl_FragCoord
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
@@ -4011,6 +2382,9 @@
 OpDecorate %nu_ii NonUniform
 OpDecorate %14 NonUniform
 OpDecorate %b Location 1
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -4025,223 +2399,62 @@
 %_ptr_Input_float = OpTypePointer Input %float
 %b = OpVariable %_ptr_Input_float Input
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %uint = OpTypeInt 32 0
+; CHECK: %26 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %48 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %102 = OpTypeFunction %uint %uint %uint %uint %uint
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability ShaderNonUniform
-OpCapability RuntimeDescriptorArray
-OpCapability StorageBufferArrayNonUniformIndexing
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %nu_ii %b %gl_FragCoord
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpName %main "main"
-OpName %bname "bname"
-OpMemberName %bname 0 "b"
-OpName %storageBuffer "storageBuffer"
-OpName %nu_ii "nu_ii"
-OpName %b "b"
-OpMemberDecorate %bname 0 Offset 0
-OpDecorate %bname BufferBlock
-OpDecorate %storageBuffer DescriptorSet 0
-OpDecorate %storageBuffer Binding 4
-OpDecorate %nu_ii Flat
-OpDecorate %nu_ii Location 0
-OpDecorate %nu_ii NonUniform
-OpDecorate %7 NonUniform
-OpDecorate %b Location 1
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_31 Block
-OpMemberDecorate %_struct_31 0 Offset 0
-OpDecorate %33 DescriptorSet 7
-OpDecorate %33 Binding 1
-OpDecorate %_struct_54 Block
-OpMemberDecorate %_struct_54 0 Offset 0
-OpMemberDecorate %_struct_54 1 Offset 4
-OpDecorate %56 DescriptorSet 7
-OpDecorate %56 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-%void = OpTypeVoid
-%9 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%bname = OpTypeStruct %float
-%_runtimearr_bname = OpTypeRuntimeArray %bname
-%_ptr_Uniform__runtimearr_bname = OpTypePointer Uniform %_runtimearr_bname
-%storageBuffer = OpVariable %_ptr_Uniform__runtimearr_bname Uniform
-%int = OpTypeInt 32 1
-%_ptr_Input_int = OpTypePointer Input %int
-%nu_ii = OpVariable %_ptr_Input_int Input
-%int_0 = OpConstant %int 0
-%_ptr_Input_float = OpTypePointer Input %float
-%b = OpVariable %_ptr_Input_float Input
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint = OpTypeInt 32 0
-%uint_0 = OpConstant %uint 0
-%uint_1 = OpConstant %uint 1
-%uint_4 = OpConstant %uint 4
-%26 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_31 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_31 = OpTypePointer StorageBuffer %_struct_31
-%33 = OpVariable %_ptr_StorageBuffer__struct_31 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%48 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_54 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_54 = OpTypePointer StorageBuffer %_struct_54
-%56 = OpVariable %_ptr_StorageBuffer__struct_54 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%v4float = OpTypeVector %float 4
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_45 = OpConstant %uint 45
-%102 = OpTypeFunction %uint %uint %uint %uint %uint
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %14 = OpLoad %int %nu_ii
 %18 = OpLoad %float %b
 %20 = OpAccessChain %_ptr_Uniform_float %storageBuffer %14 %int_0
 OpStore %20 %18
+; CHECK-NOT: OpStore %20 %18
+; CHECK: %40 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_4
+; CHECK: %42 = OpULessThan %bool %7 %40
+; CHECK: OpSelectionMerge %43 None
+; CHECK: OpBranchConditional %42 %44 %45
+; CHECK: %44 = OpLabel
+; CHECK: %100 = OpBitcast %uint %7
+; CHECK: %119 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_4 %100
+; CHECK: %120 = OpULessThan %bool %uint_0 %119
+; CHECK: OpSelectionMerge %121 None
+; CHECK: OpBranchConditional %120 %122 %123
+; CHECK: %122 = OpLabel
+; CHECK: OpStore %20 %19
+; CHECK: OpBranch %121
+; CHECK: %123 = OpLabel
+; CHECK: %124 = OpBitcast %uint %7
+; CHECK: %125 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_1 %124 %uint_0
+; CHECK: OpBranch %121
+; CHECK: %121 = OpLabel
+; CHECK: OpBranch %43
+; CHECK: %45 = OpLabel
+; CHECK: %46 = OpBitcast %uint %7
+; CHECK: %99 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 %46 %40
+; CHECK: OpBranch %43
+; CHECK: %43 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %9
-%18 = OpLabel
-%7 = OpLoad %int %nu_ii
-%19 = OpLoad %float %b
-%20 = OpAccessChain %_ptr_Uniform_float %storageBuffer %7 %int_0
-%40 = OpFunctionCall %uint %25 %uint_1 %uint_4
-%42 = OpULessThan %bool %7 %40
-OpSelectionMerge %43 None
-OpBranchConditional %42 %44 %45
-%44 = OpLabel
-%100 = OpBitcast %uint %7
-%119 = OpFunctionCall %uint %101 %uint_0 %uint_0 %uint_4 %100
-%120 = OpULessThan %bool %uint_0 %119
-OpSelectionMerge %121 None
-OpBranchConditional %120 %122 %123
-%122 = OpLabel
-OpStore %20 %19
-OpBranch %121
-%123 = OpLabel
-%124 = OpBitcast %uint %7
-%125 = OpFunctionCall %void %47 %uint_45 %uint_1 %124 %uint_0
-OpBranch %121
-%121 = OpLabel
-OpBranch %43
-%45 = OpLabel
-%46 = OpBitcast %uint %7
-%99 = OpFunctionCall %void %47 %uint_45 %uint_0 %46 %40
-OpBranch %43
-%43 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%25 = OpFunction %uint None %26
-%27 = OpFunctionParameter %uint
-%28 = OpFunctionParameter %uint
-%29 = OpLabel
-%35 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %27
-%36 = OpLoad %uint %35
-%37 = OpIAdd %uint %36 %28
-%38 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %37
-%39 = OpLoad %uint %38
-OpReturnValue %39
-OpFunctionEnd
-%47 = OpFunction %void None %48
-%49 = OpFunctionParameter %uint
-%50 = OpFunctionParameter %uint
-%51 = OpFunctionParameter %uint
-%52 = OpFunctionParameter %uint
-%53 = OpLabel
-%57 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_0
-%59 = OpAtomicIAdd %uint %57 %uint_4 %uint_0 %uint_10
-%60 = OpIAdd %uint %59 %uint_10
-%61 = OpArrayLength %uint %56 1
-%62 = OpULessThanEqual %bool %60 %61
-OpSelectionMerge %63 None
-OpBranchConditional %62 %64 %63
-%64 = OpLabel
-%65 = OpIAdd %uint %59 %uint_0
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %65
-OpStore %66 %uint_10
-%68 = OpIAdd %uint %59 %uint_1
-%69 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %68
-OpStore %69 %uint_23
-%71 = OpIAdd %uint %59 %uint_2
-%72 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %71
-OpStore %72 %49
-%74 = OpIAdd %uint %59 %uint_3
-%75 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %74
-OpStore %75 %uint_4
-%79 = OpLoad %v4float %gl_FragCoord
-%81 = OpBitcast %v4uint %79
-%82 = OpCompositeExtract %uint %81 0
-%83 = OpIAdd %uint %59 %uint_4
-%84 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %83
-OpStore %84 %82
-%85 = OpCompositeExtract %uint %81 1
-%87 = OpIAdd %uint %59 %uint_5
-%88 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %87
-OpStore %88 %85
-%90 = OpIAdd %uint %59 %uint_7
-%91 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %90
-OpStore %91 %50
-%93 = OpIAdd %uint %59 %uint_8
-%94 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %93
-OpStore %94 %51
-%96 = OpIAdd %uint %59 %uint_9
-%97 = OpAccessChain %_ptr_StorageBuffer_uint %56 %uint_1 %96
-OpStore %97 %52
-OpBranch %63
-%63 = OpLabel
-OpReturn
-OpFunctionEnd
-%101 = OpFunction %uint None %102
-%103 = OpFunctionParameter %uint
-%104 = OpFunctionParameter %uint
-%105 = OpFunctionParameter %uint
-%106 = OpFunctionParameter %uint
-%107 = OpLabel
-%108 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %103
-%109 = OpLoad %uint %108
-%110 = OpIAdd %uint %109 %104
-%111 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %110
-%112 = OpLoad %uint %111
-%113 = OpIAdd %uint %112 %105
-%114 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %113
-%115 = OpLoad %uint %114
-%116 = OpIAdd %uint %115 %106
-%117 = OpAccessChain %_ptr_StorageBuffer_uint %33 %uint_0 %116
-%118 = OpLoad %uint %117
-OpReturnValue %118
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Frag + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsInitLoadSizedUBOArray) {
@@ -4258,14 +2471,17 @@
   //     b = uniformBuffer[nu_ii].a;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability ShaderNonUniform
 OpCapability UniformBufferArrayNonUniformIndexing
 OpExtension "SPV_EXT_descriptor_indexing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %b %nu_ii
+; CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
@@ -4285,6 +2501,11 @@
 OpDecorate %nu_ii NonUniform
 OpDecorate %18 NonUniform
 OpDecorate %22 NonUniform
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
+)" + kInputDecorations + R"(
+; CHECK: OpDecorate %117 NonUniform
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %float = OpTypeFloat 32
@@ -4301,216 +2522,65 @@
 %nu_ii = OpVariable %_ptr_Input_int Input
 %int_0 = OpConstant %int 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
-)";
+; CHECK: %bool = OpTypeBool
+; CHECK: %32 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %v4float = OpTypeVector %float 4
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %88 = OpConstantNull %float
+; CHECK: %92 = OpTypeFunction %uint %uint %uint %uint %uint
+)" + kInputGlobals;
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability ShaderNonUniform
-OpCapability UniformBufferArrayNonUniformIndexing
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpName %main "main"
-OpName %b "b"
-OpName %uname "uname"
-OpMemberName %uname 0 "a"
-OpName %uniformBuffer "uniformBuffer"
-OpName %nu_ii "nu_ii"
-OpDecorate %b Location 0
-OpMemberDecorate %uname 0 Offset 0
-OpDecorate %uname Block
-OpDecorate %uniformBuffer DescriptorSet 0
-OpDecorate %uniformBuffer Binding 3
-OpDecorate %nu_ii Flat
-OpDecorate %nu_ii Location 0
-OpDecorate %nu_ii NonUniform
-OpDecorate %7 NonUniform
-OpDecorate %89 NonUniform
-OpDecorate %120 NonUniform
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_39 Block
-OpMemberDecorate %_struct_39 0 Offset 0
-OpMemberDecorate %_struct_39 1 Offset 4
-OpDecorate %41 DescriptorSet 7
-OpDecorate %41 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-OpDecorate %_struct_98 Block
-OpMemberDecorate %_struct_98 0 Offset 0
-OpDecorate %100 DescriptorSet 7
-OpDecorate %100 Binding 1
-OpDecorate %117 NonUniform
-%void = OpTypeVoid
-%10 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Output_float = OpTypePointer Output %float
-%b = OpVariable %_ptr_Output_float Output
-%uname = OpTypeStruct %float
-%uint = OpTypeInt 32 0
-%uint_128 = OpConstant %uint 128
-%_arr_uname_uint_128 = OpTypeArray %uname %uint_128
-%_ptr_Uniform__arr_uname_uint_128 = OpTypePointer Uniform %_arr_uname_uint_128
-%uniformBuffer = OpVariable %_ptr_Uniform__arr_uname_uint_128 Uniform
-%int = OpTypeInt 32 1
-%_ptr_Input_int = OpTypePointer Input %int
-%nu_ii = OpVariable %_ptr_Input_int Input
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint_0 = OpConstant %uint 0
-%bool = OpTypeBool
-%32 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_39 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
-%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_1 = OpConstant %uint 1
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%v4float = OpTypeVector %float 4
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_46 = OpConstant %uint 46
-%88 = OpConstantNull %float
-%92 = OpTypeFunction %uint %uint %uint %uint %uint
-%_struct_98 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_98 = OpTypePointer StorageBuffer %_struct_98
-%100 = OpVariable %_ptr_StorageBuffer__struct_98 StorageBuffer
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %18 = OpLoad %int %nu_ii
 %21 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %18 %int_0
 %22 = OpLoad %float %21
 OpStore %b %22
+; CHECK-NOT: %22 = OpLoad %float %21
+; CHECK-NOT: OpStore %b %22
+; CHECK: %25 = OpULessThan %bool %7 %uint_128
+; CHECK: OpSelectionMerge %26 None
+; CHECK: OpBranchConditional %25 %27 %28
+; CHECK: %27 = OpLabel
+; CHECK: %90 = OpBitcast %uint %7
+; CHECK: %112 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 %90
+; CHECK: %113 = OpULessThan %bool %uint_0 %112
+; CHECK: OpSelectionMerge %114 None
+; CHECK: OpBranchConditional %113 %115 %116
+; CHECK: %115 = OpLabel
+; CHECK: %117 = OpLoad %float %22
+; CHECK: OpBranch %114
+; CHECK: %116 = OpLabel
+; CHECK: %118 = OpBitcast %uint %7
+; CHECK: %119 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_46 %uint_1 %118 %uint_0
+; CHECK: OpBranch %114
+; CHECK: %114 = OpLabel
+; CHECK: %120 = OpPhi %float %117 %115 %88 %116
+; CHECK: OpBranch %26
+; CHECK: %28 = OpLabel
+; CHECK: %30 = OpBitcast %uint %7
+; CHECK: %87 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_46 %uint_0 %30 %uint_128
+; CHECK: OpBranch %26
+; CHECK: %26 = OpLabel
+; CHECK: %89 = OpPhi %float %120 %114 %88 %28
+; CHECK: OpStore %b %89
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %10
-%21 = OpLabel
-%7 = OpLoad %int %nu_ii
-%22 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %7 %int_0
-%25 = OpULessThan %bool %7 %uint_128
-OpSelectionMerge %26 None
-OpBranchConditional %25 %27 %28
-%27 = OpLabel
-%90 = OpBitcast %uint %7
-%112 = OpFunctionCall %uint %91 %uint_0 %uint_0 %uint_3 %90
-%113 = OpULessThan %bool %uint_0 %112
-OpSelectionMerge %114 None
-OpBranchConditional %113 %115 %116
-%115 = OpLabel
-%117 = OpLoad %float %22
-OpBranch %114
-%116 = OpLabel
-%118 = OpBitcast %uint %7
-%119 = OpFunctionCall %void %31 %uint_46 %uint_1 %118 %uint_0
-OpBranch %114
-%114 = OpLabel
-%120 = OpPhi %float %117 %115 %88 %116
-OpBranch %26
-%28 = OpLabel
-%30 = OpBitcast %uint %7
-%87 = OpFunctionCall %void %31 %uint_46 %uint_0 %30 %uint_128
-OpBranch %26
-%26 = OpLabel
-%89 = OpPhi %float %120 %114 %88 %28
-OpStore %b %89
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%31 = OpFunction %void None %32
-%33 = OpFunctionParameter %uint
-%34 = OpFunctionParameter %uint
-%35 = OpFunctionParameter %uint
-%36 = OpFunctionParameter %uint
-%37 = OpLabel
-%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0
-%46 = OpAtomicIAdd %uint %43 %uint_4 %uint_0 %uint_10
-%47 = OpIAdd %uint %46 %uint_10
-%48 = OpArrayLength %uint %41 1
-%49 = OpULessThanEqual %bool %47 %48
-OpSelectionMerge %50 None
-OpBranchConditional %49 %51 %50
-%51 = OpLabel
-%52 = OpIAdd %uint %46 %uint_0
-%54 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %52
-OpStore %54 %uint_10
-%56 = OpIAdd %uint %46 %uint_1
-%57 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %56
-OpStore %57 %uint_23
-%59 = OpIAdd %uint %46 %uint_2
-%60 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %59
-OpStore %60 %33
-%62 = OpIAdd %uint %46 %uint_3
-%63 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %62
-OpStore %63 %uint_4
-%67 = OpLoad %v4float %gl_FragCoord
-%69 = OpBitcast %v4uint %67
-%70 = OpCompositeExtract %uint %69 0
-%71 = OpIAdd %uint %46 %uint_4
-%72 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %71
-OpStore %72 %70
-%73 = OpCompositeExtract %uint %69 1
-%75 = OpIAdd %uint %46 %uint_5
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %75
-OpStore %76 %73
-%78 = OpIAdd %uint %46 %uint_7
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %78
-OpStore %79 %34
-%81 = OpIAdd %uint %46 %uint_8
-%82 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %81
-OpStore %82 %35
-%84 = OpIAdd %uint %46 %uint_9
-%85 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_1 %84
-OpStore %85 %36
-OpBranch %50
-%50 = OpLabel
-OpReturn
-OpFunctionEnd
-%91 = OpFunction %uint None %92
-%93 = OpFunctionParameter %uint
-%94 = OpFunctionParameter %uint
-%95 = OpFunctionParameter %uint
-%96 = OpFunctionParameter %uint
-%97 = OpLabel
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %93
-%102 = OpLoad %uint %101
-%103 = OpIAdd %uint %102 %94
-%104 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %103
-%105 = OpLoad %uint %104
-%106 = OpIAdd %uint %105 %95
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %106
-%108 = OpLoad %uint %107
-%109 = OpIAdd %uint %108 %96
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %100 %uint_0 %109
-%111 = OpLoad %uint %110
-OpReturnValue %111
-OpFunctionEnd
-)";
+  const std::string new_funcs = kStreamWrite4Frag + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -4532,13 +2602,16 @@
   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  // clang-format off
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability RuntimeDescriptorArray
 OpExtension "SPV_EXT_descriptor_indexing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %main "main"
+; CHECK: OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
 OpExecutionMode %main LocalSize 1 1 1
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
@@ -4556,6 +2629,9 @@
 OpDecorate %images DescriptorSet 0
 OpDecorate %images Binding 1
 OpDecorate %images NonWritable
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
@@ -4577,100 +2653,24 @@
 %v4float = OpTypeVector %float 4
 %uint_0 = OpConstant %uint 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %34 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v3uint = OpTypeVector %uint 3
+; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+; CHECK: %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+; CHECK: %112 = OpConstantNull %v4float
+; CHECK: %115 = OpTypeFunction %uint %uint %uint %uint %uint
+; CHECK: %140 = OpConstantNull %uint
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability RuntimeDescriptorArray
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
-OpExecutionMode %main LocalSize 1 1 1
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpName %main "main"
-OpName %Input "Input"
-OpMemberName %Input 0 "index"
-OpMemberName %Input 1 "red"
-OpName %sbo "sbo"
-OpName %images "images"
-OpMemberDecorate %Input 0 Offset 0
-OpMemberDecorate %Input 1 Offset 4
-OpDecorate %Input BufferBlock
-OpDecorate %sbo DescriptorSet 0
-OpDecorate %sbo Binding 0
-OpDecorate %images DescriptorSet 0
-OpDecorate %images Binding 1
-OpDecorate %images NonWritable
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_39 Block
-OpMemberDecorate %_struct_39 0 Offset 0
-OpDecorate %41 DescriptorSet 7
-OpDecorate %41 Binding 1
-OpDecorate %_struct_63 Block
-OpMemberDecorate %_struct_63 0 Offset 0
-OpMemberDecorate %_struct_63 1 Offset 4
-OpDecorate %65 DescriptorSet 7
-OpDecorate %65 Binding 0
-OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
-%void = OpTypeVoid
-%7 = OpTypeFunction %void
-%uint = OpTypeInt 32 0
-%float = OpTypeFloat 32
-%Input = OpTypeStruct %uint %float
-%_ptr_Uniform_Input = OpTypePointer Uniform %Input
-%sbo = OpVariable %_ptr_Uniform_Input Uniform
-%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
-%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
-%_runtimearr_13 = OpTypeRuntimeArray %13
-%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
-%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
-%v2int = OpTypeVector %int 2
-%20 = OpConstantComposite %v2int %int_0 %int_0
-%v4float = OpTypeVector %float 4
-%uint_0 = OpConstant %uint 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint_1 = OpConstant %uint 1
-%34 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_39 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
-%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%57 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_63 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63
-%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_5 = OpConstant %uint 5
-%uint_3 = OpConstant %uint 3
-%v3uint = OpTypeVector %uint 3
-%_ptr_Input_v3uint = OpTypePointer Input %v3uint
-%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_50 = OpConstant %uint 50
-%112 = OpConstantNull %v4float
-%115 = OpTypeFunction %uint %uint %uint %uint %uint
-%uint_47 = OpConstant %uint 47
-%140 = OpConstantNull %uint
-%uint_53 = OpConstant %uint 53
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
 %20 = OpLoad %uint %19
@@ -4680,159 +2680,70 @@
 %29 = OpCompositeExtract %float %27 0
 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
 OpStore %31 %29
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string func_after =
-      R"(%main = OpFunction %void None %7
-%24 = OpLabel
-%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
-%132 = OpFunctionCall %uint %114 %uint_0 %uint_0 %uint_0 %uint_0
-%133 = OpULessThan %bool %uint_0 %132
-OpSelectionMerge %134 None
-OpBranchConditional %133 %135 %136
-%135 = OpLabel
-%137 = OpLoad %uint %25
-OpBranch %134
-%136 = OpLabel
-%139 = OpFunctionCall %void %56 %uint_47 %uint_1 %uint_0 %uint_0
-OpBranch %134
-%134 = OpLabel
-%141 = OpPhi %uint %137 %135 %140 %136
-%27 = OpAccessChain %_ptr_UniformConstant_13 %images %141
-%28 = OpLoad %13 %27
-%48 = OpFunctionCall %uint %33 %uint_1 %uint_1
-%50 = OpULessThan %bool %141 %48
-OpSelectionMerge %51 None
-OpBranchConditional %50 %52 %53
-%52 = OpLabel
-%54 = OpLoad %13 %27
-%142 = OpFunctionCall %uint %114 %uint_0 %uint_0 %uint_1 %141
-%143 = OpULessThan %bool %uint_0 %142
-OpSelectionMerge %144 None
-OpBranchConditional %143 %145 %146
-%145 = OpLabel
-%147 = OpLoad %13 %27
-%148 = OpImageRead %v4float %147 %20
-OpBranch %144
-%146 = OpLabel
-%149 = OpFunctionCall %void %56 %uint_50 %uint_1 %141 %uint_0
-OpBranch %144
-%144 = OpLabel
-%150 = OpPhi %v4float %148 %145 %112 %146
-OpBranch %51
-%53 = OpLabel
-%111 = OpFunctionCall %void %56 %uint_50 %uint_0 %141 %48
-OpBranch %51
-%51 = OpLabel
-%113 = OpPhi %v4float %150 %144 %112 %53
-%30 = OpCompositeExtract %float %113 0
-%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
-%151 = OpFunctionCall %uint %114 %uint_0 %uint_0 %uint_0 %uint_0
-%152 = OpULessThan %bool %uint_0 %151
-OpSelectionMerge %153 None
-OpBranchConditional %152 %154 %155
-%154 = OpLabel
-OpStore %31 %30
-OpBranch %153
-%155 = OpLabel
-%157 = OpFunctionCall %void %56 %uint_53 %uint_1 %uint_0 %uint_0
-OpBranch %153
-%153 = OpLabel
+; CHECK-NOT: OpStore %31 %29
+; CHECK: %132 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %133 = OpULessThan %bool %uint_0 %132
+; CHECK: OpSelectionMerge %134 None
+; CHECK: OpBranchConditional %133 %135 %136
+; CHECK: %135 = OpLabel
+; CHECK: %137 = OpLoad %uint %25
+; CHECK: OpBranch %134
+; CHECK: %136 = OpLabel
+; CHECK: %139 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_47 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %134
+; CHECK: %134 = OpLabel
+; CHECK: %141 = OpPhi %uint %137 %135 %140 %136
+; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %141
+; CHECK: %28 = OpLoad %13 %27
+; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
+; CHECK: %50 = OpULessThan %bool %141 %48
+; CHECK: OpSelectionMerge %51 None
+; CHECK: OpBranchConditional %50 %52 %53
+; CHECK: %52 = OpLabel
+; CHECK: %54 = OpLoad %13 %27
+; CHECK: %142 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %141
+; CHECK: %143 = OpULessThan %bool %uint_0 %142
+; CHECK: OpSelectionMerge %144 None
+; CHECK: OpBranchConditional %143 %145 %146
+; CHECK: %145 = OpLabel
+; CHECK: %147 = OpLoad %13 %27
+; CHECK: %148 = OpImageRead %v4float %147 %20
+; CHECK: OpBranch %144
+; CHECK: %146 = OpLabel
+; CHECK: %149 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_50 %uint_1 %141 %uint_0
+; CHECK: OpBranch %144
+; CHECK: %144 = OpLabel
+; CHECK: %150 = OpPhi %v4float %148 %145 %112 %146
+; CHECK: OpBranch %51
+; CHECK: %53 = OpLabel
+; CHECK: %111 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_50 %uint_0 %141 %48
+; CHECK: OpBranch %51
+; CHECK: %51 = OpLabel
+; CHECK: %113 = OpPhi %v4float %150 %144 %112 %53
+; CHECK: %30 = OpCompositeExtract %float %113 0
+; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
+; CHECK: %151 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %152 = OpULessThan %bool %uint_0 %151
+; CHECK: OpSelectionMerge %153 None
+; CHECK: OpBranchConditional %152 %154 %155
+; CHECK: %154 = OpLabel
+; CHECK: OpStore %31 %30
+; CHECK: OpBranch %153
+; CHECK: %155 = OpLabel
+; CHECK: %157 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_53 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %153
+; CHECK: %153 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
   const std::string new_funcs =
-      R"(%33 = OpFunction %uint None %34
-%35 = OpFunctionParameter %uint
-%36 = OpFunctionParameter %uint
-%37 = OpLabel
-%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35
-%44 = OpLoad %uint %43
-%45 = OpIAdd %uint %44 %36
-%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45
-%47 = OpLoad %uint %46
-OpReturnValue %47
-OpFunctionEnd
-%56 = OpFunction %void None %57
-%58 = OpFunctionParameter %uint
-%59 = OpFunctionParameter %uint
-%60 = OpFunctionParameter %uint
-%61 = OpFunctionParameter %uint
-%62 = OpLabel
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0
-%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10
-%70 = OpIAdd %uint %69 %uint_10
-%71 = OpArrayLength %uint %65 1
-%72 = OpULessThanEqual %bool %70 %71
-OpSelectionMerge %73 None
-OpBranchConditional %72 %74 %73
-%74 = OpLabel
-%75 = OpIAdd %uint %69 %uint_0
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75
-OpStore %76 %uint_10
-%78 = OpIAdd %uint %69 %uint_1
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78
-OpStore %79 %uint_23
-%81 = OpIAdd %uint %69 %uint_2
-%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81
-OpStore %82 %58
-%85 = OpIAdd %uint %69 %uint_3
-%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85
-OpStore %86 %uint_5
-%90 = OpLoad %v3uint %gl_GlobalInvocationID
-%91 = OpCompositeExtract %uint %90 0
-%92 = OpCompositeExtract %uint %90 1
-%93 = OpCompositeExtract %uint %90 2
-%94 = OpIAdd %uint %69 %uint_4
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94
-OpStore %95 %91
-%96 = OpIAdd %uint %69 %uint_5
-%97 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %96
-OpStore %97 %92
-%99 = OpIAdd %uint %69 %uint_6
-%100 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %99
-OpStore %100 %93
-%102 = OpIAdd %uint %69 %uint_7
-%103 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %102
-OpStore %103 %59
-%105 = OpIAdd %uint %69 %uint_8
-%106 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %105
-OpStore %106 %60
-%108 = OpIAdd %uint %69 %uint_9
-%109 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %108
-OpStore %109 %61
-OpBranch %73
-%73 = OpLabel
-OpReturn
-OpFunctionEnd
-%114 = OpFunction %uint None %115
-%116 = OpFunctionParameter %uint
-%117 = OpFunctionParameter %uint
-%118 = OpFunctionParameter %uint
-%119 = OpFunctionParameter %uint
-%120 = OpLabel
-%121 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %116
-%122 = OpLoad %uint %121
-%123 = OpIAdd %uint %122 %117
-%124 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %123
-%125 = OpLoad %uint %124
-%126 = OpIAdd %uint %125 %118
-%127 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %126
-%128 = OpLoad %uint %127
-%129 = OpIAdd %uint %128 %119
-%130 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %129
-%131 = OpLoad %uint %130
-OpReturnValue %131
-OpFunctionEnd
-)";
+      kDirectRead2 + kStreamWrite4Compute + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -4853,14 +2764,17 @@
   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability RuntimeDescriptorArray
+  // clang-format off
+  const std::string defs = R"(
+OpCapability RuntimeDescriptorArray
 OpCapability RayTracingNV
 OpExtension "SPV_EXT_descriptor_indexing"
 OpExtension "SPV_NV_ray_tracing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint RayGenerationNV %main "main"
+; CHECK: OpEntryPoint RayGenerationNV %main "main" %89
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -4878,51 +2792,11 @@
 OpDecorate %images DescriptorSet 0
 OpDecorate %images Binding 1
 OpDecorate %images NonWritable
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
 %void = OpTypeVoid
-)";
-
-  const std::string defs_after =
-      R"(OpCapability RuntimeDescriptorArray
-OpCapability RayTracingNV
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_NV_ray_tracing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint RayGenerationNV %main "main" %89
-OpSource GLSL 460
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpSourceExtension "GL_NV_ray_tracing"
-OpName %main "main"
-OpName %StorageBuffer "StorageBuffer"
-OpMemberName %StorageBuffer 0 "index"
-OpMemberName %StorageBuffer 1 "red"
-OpName %sbo "sbo"
-OpName %images "images"
-OpMemberDecorate %StorageBuffer 0 Offset 0
-OpMemberDecorate %StorageBuffer 1 Offset 4
-OpDecorate %StorageBuffer BufferBlock
-OpDecorate %sbo DescriptorSet 0
-OpDecorate %sbo Binding 0
-OpDecorate %images DescriptorSet 0
-OpDecorate %images Binding 1
-OpDecorate %images NonWritable
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_39 Block
-OpMemberDecorate %_struct_39 0 Offset 0
-OpDecorate %41 DescriptorSet 7
-OpDecorate %41 Binding 1
-OpDecorate %_struct_63 Block
-OpMemberDecorate %_struct_63 0 Offset 0
-OpMemberDecorate %_struct_63 1 Offset 4
-OpDecorate %65 DescriptorSet 7
-OpDecorate %65 Binding 0
-OpDecorate %89 BuiltIn LaunchIdNV
-%void = OpTypeVoid
-)";
-
-  const std::string func_before =
-      R"(%3 = OpTypeFunction %void
+%3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
 %float = OpTypeFloat 32
 %StorageBuffer = OpTypeStruct %uint %float
@@ -4942,6 +2816,23 @@
 %v4float = OpTypeVector %float 4
 %uint_0 = OpConstant %uint 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %34 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v3uint = OpTypeVector %uint 3
+; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
+; CHECK: %113 = OpConstantNull %v4float
+; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
+; CHECK: %141 = OpConstantNull %uint
+)";
+  // clang-format on
+
+  const std::string main_func = R"(
 %main = OpFunction %void None %3
 %5 = OpLabel
 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
@@ -4952,211 +2843,69 @@
 %29 = OpCompositeExtract %float %27 0
 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
 OpStore %31 %29
+; CHECK-NOT: OpStore %31 %29
+; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %134 = OpULessThan %bool %uint_0 %133
+; CHECK: OpSelectionMerge %135 None
+; CHECK: OpBranchConditional %134 %136 %137
+; CHECK: %136 = OpLabel
+; CHECK: %138 = OpLoad %uint %25
+; CHECK: OpBranch %135
+; CHECK: %137 = OpLabel
+; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %135
+; CHECK: %135 = OpLabel
+; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
+; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
+; CHECK: %28 = OpLoad %13 %27
+; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
+; CHECK: %50 = OpULessThan %bool %142 %48
+; CHECK: OpSelectionMerge %51 None
+; CHECK: OpBranchConditional %50 %52 %53
+; CHECK: %52 = OpLabel
+; CHECK: %54 = OpLoad %13 %27
+; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
+; CHECK: %144 = OpULessThan %bool %uint_0 %143
+; CHECK: OpSelectionMerge %145 None
+; CHECK: OpBranchConditional %144 %146 %147
+; CHECK: %146 = OpLabel
+; CHECK: %148 = OpLoad %13 %27
+; CHECK: %149 = OpImageRead %v4float %148 %20
+; CHECK: OpBranch %145
+; CHECK: %147 = OpLabel
+; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
+; CHECK: OpBranch %145
+; CHECK: %145 = OpLabel
+; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
+; CHECK: OpBranch %51
+; CHECK: %53 = OpLabel
+; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: OpBranch %51
+; CHECK: %51 = OpLabel
+; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
+; CHECK: %30 = OpCompositeExtract %float %114 0
+; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
+; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %153 = OpULessThan %bool %uint_0 %152
+; CHECK: OpSelectionMerge %154 None
+; CHECK: OpBranchConditional %153 %155 %156
+; CHECK: %155 = OpLabel
+; CHECK: OpStore %31 %30
+; CHECK: OpBranch %154
+; CHECK: %156 = OpLabel
+; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %154
+; CHECK: %154 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%7 = OpTypeFunction %void
-%uint = OpTypeInt 32 0
-%float = OpTypeFloat 32
-%StorageBuffer = OpTypeStruct %uint %float
-%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
-%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
-%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
-%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
-%_runtimearr_13 = OpTypeRuntimeArray %13
-%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
-%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
-%v2int = OpTypeVector %int 2
-%20 = OpConstantComposite %v2int %int_0 %int_0
-%v4float = OpTypeVector %float 4
-%uint_0 = OpConstant %uint 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint_1 = OpConstant %uint 1
-%34 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_39 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
-%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%57 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_63 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63
-%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_5313 = OpConstant %uint 5313
-%uint_3 = OpConstant %uint 3
-%v3uint = OpTypeVector %uint 3
-%_ptr_Input_v3uint = OpTypePointer Input %v3uint
-%89 = OpVariable %_ptr_Input_v3uint Input
-%uint_5 = OpConstant %uint 5
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_51 = OpConstant %uint 51
-%113 = OpConstantNull %v4float
-%116 = OpTypeFunction %uint %uint %uint %uint %uint
-%uint_48 = OpConstant %uint 48
-%141 = OpConstantNull %uint
-%uint_54 = OpConstant %uint 54
-%main = OpFunction %void None %7
-%24 = OpLabel
-%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
-%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%134 = OpULessThan %bool %uint_0 %133
-OpSelectionMerge %135 None
-OpBranchConditional %134 %136 %137
-%136 = OpLabel
-%138 = OpLoad %uint %25
-OpBranch %135
-%137 = OpLabel
-%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0
-OpBranch %135
-%135 = OpLabel
-%142 = OpPhi %uint %138 %136 %141 %137
-%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
-%28 = OpLoad %13 %27
-%48 = OpFunctionCall %uint %33 %uint_1 %uint_1
-%50 = OpULessThan %bool %142 %48
-OpSelectionMerge %51 None
-OpBranchConditional %50 %52 %53
-%52 = OpLabel
-%54 = OpLoad %13 %27
-%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142
-%144 = OpULessThan %bool %uint_0 %143
-OpSelectionMerge %145 None
-OpBranchConditional %144 %146 %147
-%146 = OpLabel
-%148 = OpLoad %13 %27
-%149 = OpImageRead %v4float %148 %20
-OpBranch %145
-%147 = OpLabel
-%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0
-OpBranch %145
-%145 = OpLabel
-%151 = OpPhi %v4float %149 %146 %113 %147
-OpBranch %51
-%53 = OpLabel
-%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48
-OpBranch %51
-%51 = OpLabel
-%114 = OpPhi %v4float %151 %145 %113 %53
-%30 = OpCompositeExtract %float %114 0
-%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
-%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%153 = OpULessThan %bool %uint_0 %152
-OpSelectionMerge %154 None
-OpBranchConditional %153 %155 %156
-%155 = OpLabel
-OpStore %31 %30
-OpBranch %154
-%156 = OpLabel
-%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0
-OpBranch %154
-%154 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%33 = OpFunction %uint None %34
-%35 = OpFunctionParameter %uint
-%36 = OpFunctionParameter %uint
-%37 = OpLabel
-%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35
-%44 = OpLoad %uint %43
-%45 = OpIAdd %uint %44 %36
-%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45
-%47 = OpLoad %uint %46
-OpReturnValue %47
-OpFunctionEnd
-%56 = OpFunction %void None %57
-%58 = OpFunctionParameter %uint
-%59 = OpFunctionParameter %uint
-%60 = OpFunctionParameter %uint
-%61 = OpFunctionParameter %uint
-%62 = OpLabel
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0
-%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10
-%70 = OpIAdd %uint %69 %uint_10
-%71 = OpArrayLength %uint %65 1
-%72 = OpULessThanEqual %bool %70 %71
-OpSelectionMerge %73 None
-OpBranchConditional %72 %74 %73
-%74 = OpLabel
-%75 = OpIAdd %uint %69 %uint_0
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75
-OpStore %76 %uint_10
-%78 = OpIAdd %uint %69 %uint_1
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78
-OpStore %79 %uint_23
-%81 = OpIAdd %uint %69 %uint_2
-%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81
-OpStore %82 %58
-%85 = OpIAdd %uint %69 %uint_3
-%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85
-OpStore %86 %uint_5313
-%90 = OpLoad %v3uint %89
-%91 = OpCompositeExtract %uint %90 0
-%92 = OpCompositeExtract %uint %90 1
-%93 = OpCompositeExtract %uint %90 2
-%94 = OpIAdd %uint %69 %uint_4
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94
-OpStore %95 %91
-%97 = OpIAdd %uint %69 %uint_5
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97
-OpStore %98 %92
-%100 = OpIAdd %uint %69 %uint_6
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100
-OpStore %101 %93
-%103 = OpIAdd %uint %69 %uint_7
-%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103
-OpStore %104 %59
-%106 = OpIAdd %uint %69 %uint_8
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106
-OpStore %107 %60
-%109 = OpIAdd %uint %69 %uint_9
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109
-OpStore %110 %61
-OpBranch %73
-%73 = OpLabel
-OpReturn
-OpFunctionEnd
-%115 = OpFunction %uint None %116
-%117 = OpFunctionParameter %uint
-%118 = OpFunctionParameter %uint
-%119 = OpFunctionParameter %uint
-%120 = OpFunctionParameter %uint
-%121 = OpLabel
-%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117
-%123 = OpLoad %uint %122
-%124 = OpIAdd %uint %123 %118
-%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124
-%126 = OpLoad %uint %125
-%127 = OpIAdd %uint %126 %119
-%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127
-%129 = OpLoad %uint %128
-%130 = OpIAdd %uint %129 %120
-%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130
-%132 = OpLoad %uint %131
-OpReturnValue %132
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -5177,14 +2926,17 @@
   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability RuntimeDescriptorArray
+  // clang-format off
+  const std::string defs = R"(
+OpCapability RuntimeDescriptorArray
 OpCapability RayTracingNV
 OpExtension "SPV_EXT_descriptor_indexing"
 OpExtension "SPV_NV_ray_tracing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint IntersectionNV %main "main"
+; CHECK: OpEntryPoint IntersectionNV %main "main" %89
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -5202,51 +2954,11 @@
 OpDecorate %images DescriptorSet 0
 OpDecorate %images Binding 1
 OpDecorate %images NonWritable
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
 %void = OpTypeVoid
-)";
-
-  const std::string defs_after =
-      R"(OpCapability RuntimeDescriptorArray
-OpCapability RayTracingNV
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_NV_ray_tracing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint IntersectionNV %main "main" %89
-OpSource GLSL 460
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpSourceExtension "GL_NV_ray_tracing"
-OpName %main "main"
-OpName %StorageBuffer "StorageBuffer"
-OpMemberName %StorageBuffer 0 "index"
-OpMemberName %StorageBuffer 1 "red"
-OpName %sbo "sbo"
-OpName %images "images"
-OpMemberDecorate %StorageBuffer 0 Offset 0
-OpMemberDecorate %StorageBuffer 1 Offset 4
-OpDecorate %StorageBuffer BufferBlock
-OpDecorate %sbo DescriptorSet 0
-OpDecorate %sbo Binding 0
-OpDecorate %images DescriptorSet 0
-OpDecorate %images Binding 1
-OpDecorate %images NonWritable
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_39 Block
-OpMemberDecorate %_struct_39 0 Offset 0
-OpDecorate %41 DescriptorSet 7
-OpDecorate %41 Binding 1
-OpDecorate %_struct_63 Block
-OpMemberDecorate %_struct_63 0 Offset 0
-OpMemberDecorate %_struct_63 1 Offset 4
-OpDecorate %65 DescriptorSet 7
-OpDecorate %65 Binding 0
-OpDecorate %89 BuiltIn LaunchIdNV
-%void = OpTypeVoid
-)";
-
-  const std::string func_before =
-      R"(%3 = OpTypeFunction %void
+%3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
 %float = OpTypeFloat 32
 %StorageBuffer = OpTypeStruct %uint %float
@@ -5266,6 +2978,22 @@
 %v4float = OpTypeVector %float 4
 %uint_0 = OpConstant %uint 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %34 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+)" + kOutputGlobals + R"(
+; CHECK: %v3uint = OpTypeVector %uint 3
+; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
+; CHECK: %113 = OpConstantNull %v4float
+; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
+; CHECK: %141 = OpConstantNull %uint
+)";
+  // clang-format on
+
+  const std::string main_func = R"(
 %main = OpFunction %void None %3
 %5 = OpLabel
 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
@@ -5276,211 +3004,69 @@
 %29 = OpCompositeExtract %float %27 0
 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
 OpStore %31 %29
+; CHECK-NOT: OpStore %31 %29
+; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %134 = OpULessThan %bool %uint_0 %133
+; CHECK: OpSelectionMerge %135 None
+; CHECK: OpBranchConditional %134 %136 %137
+; CHECK: %136 = OpLabel
+; CHECK: %138 = OpLoad %uint %25
+; CHECK: OpBranch %135
+; CHECK: %137 = OpLabel
+; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %135
+; CHECK: %135 = OpLabel
+; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
+; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
+; CHECK: %28 = OpLoad %13 %27
+; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
+; CHECK: %50 = OpULessThan %bool %142 %48
+; CHECK: OpSelectionMerge %51 None
+; CHECK: OpBranchConditional %50 %52 %53
+; CHECK: %52 = OpLabel
+; CHECK: %54 = OpLoad %13 %27
+; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
+; CHECK: %144 = OpULessThan %bool %uint_0 %143
+; CHECK: OpSelectionMerge %145 None
+; CHECK: OpBranchConditional %144 %146 %147
+; CHECK: %146 = OpLabel
+; CHECK: %148 = OpLoad %13 %27
+; CHECK: %149 = OpImageRead %v4float %148 %20
+; CHECK: OpBranch %145
+; CHECK: %147 = OpLabel
+; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
+; CHECK: OpBranch %145
+; CHECK: %145 = OpLabel
+; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
+; CHECK: OpBranch %51
+; CHECK: %53 = OpLabel
+; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: OpBranch %51
+; CHECK: %51 = OpLabel
+; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
+; CHECK: %30 = OpCompositeExtract %float %114 0
+; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
+; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %153 = OpULessThan %bool %uint_0 %152
+; CHECK: OpSelectionMerge %154 None
+; CHECK: OpBranchConditional %153 %155 %156
+; CHECK: %155 = OpLabel
+; CHECK: OpStore %31 %30
+; CHECK: OpBranch %154
+; CHECK: %156 = OpLabel
+; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %154
+; CHECK: %154 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%7 = OpTypeFunction %void
-%uint = OpTypeInt 32 0
-%float = OpTypeFloat 32
-%StorageBuffer = OpTypeStruct %uint %float
-%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
-%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
-%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
-%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
-%_runtimearr_13 = OpTypeRuntimeArray %13
-%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
-%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
-%v2int = OpTypeVector %int 2
-%20 = OpConstantComposite %v2int %int_0 %int_0
-%v4float = OpTypeVector %float 4
-%uint_0 = OpConstant %uint 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint_1 = OpConstant %uint 1
-%34 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_39 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
-%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%57 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_63 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63
-%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_5314 = OpConstant %uint 5314
-%uint_3 = OpConstant %uint 3
-%v3uint = OpTypeVector %uint 3
-%_ptr_Input_v3uint = OpTypePointer Input %v3uint
-%89 = OpVariable %_ptr_Input_v3uint Input
-%uint_5 = OpConstant %uint 5
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_51 = OpConstant %uint 51
-%113 = OpConstantNull %v4float
-%116 = OpTypeFunction %uint %uint %uint %uint %uint
-%uint_48 = OpConstant %uint 48
-%141 = OpConstantNull %uint
-%uint_54 = OpConstant %uint 54
-%main = OpFunction %void None %7
-%24 = OpLabel
-%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
-%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%134 = OpULessThan %bool %uint_0 %133
-OpSelectionMerge %135 None
-OpBranchConditional %134 %136 %137
-%136 = OpLabel
-%138 = OpLoad %uint %25
-OpBranch %135
-%137 = OpLabel
-%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0
-OpBranch %135
-%135 = OpLabel
-%142 = OpPhi %uint %138 %136 %141 %137
-%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
-%28 = OpLoad %13 %27
-%48 = OpFunctionCall %uint %33 %uint_1 %uint_1
-%50 = OpULessThan %bool %142 %48
-OpSelectionMerge %51 None
-OpBranchConditional %50 %52 %53
-%52 = OpLabel
-%54 = OpLoad %13 %27
-%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142
-%144 = OpULessThan %bool %uint_0 %143
-OpSelectionMerge %145 None
-OpBranchConditional %144 %146 %147
-%146 = OpLabel
-%148 = OpLoad %13 %27
-%149 = OpImageRead %v4float %148 %20
-OpBranch %145
-%147 = OpLabel
-%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0
-OpBranch %145
-%145 = OpLabel
-%151 = OpPhi %v4float %149 %146 %113 %147
-OpBranch %51
-%53 = OpLabel
-%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48
-OpBranch %51
-%51 = OpLabel
-%114 = OpPhi %v4float %151 %145 %113 %53
-%30 = OpCompositeExtract %float %114 0
-%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
-%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%153 = OpULessThan %bool %uint_0 %152
-OpSelectionMerge %154 None
-OpBranchConditional %153 %155 %156
-%155 = OpLabel
-OpStore %31 %30
-OpBranch %154
-%156 = OpLabel
-%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0
-OpBranch %154
-%154 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%33 = OpFunction %uint None %34
-%35 = OpFunctionParameter %uint
-%36 = OpFunctionParameter %uint
-%37 = OpLabel
-%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35
-%44 = OpLoad %uint %43
-%45 = OpIAdd %uint %44 %36
-%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45
-%47 = OpLoad %uint %46
-OpReturnValue %47
-OpFunctionEnd
-%56 = OpFunction %void None %57
-%58 = OpFunctionParameter %uint
-%59 = OpFunctionParameter %uint
-%60 = OpFunctionParameter %uint
-%61 = OpFunctionParameter %uint
-%62 = OpLabel
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0
-%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10
-%70 = OpIAdd %uint %69 %uint_10
-%71 = OpArrayLength %uint %65 1
-%72 = OpULessThanEqual %bool %70 %71
-OpSelectionMerge %73 None
-OpBranchConditional %72 %74 %73
-%74 = OpLabel
-%75 = OpIAdd %uint %69 %uint_0
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75
-OpStore %76 %uint_10
-%78 = OpIAdd %uint %69 %uint_1
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78
-OpStore %79 %uint_23
-%81 = OpIAdd %uint %69 %uint_2
-%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81
-OpStore %82 %58
-%85 = OpIAdd %uint %69 %uint_3
-%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85
-OpStore %86 %uint_5314
-%90 = OpLoad %v3uint %89
-%91 = OpCompositeExtract %uint %90 0
-%92 = OpCompositeExtract %uint %90 1
-%93 = OpCompositeExtract %uint %90 2
-%94 = OpIAdd %uint %69 %uint_4
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94
-OpStore %95 %91
-%97 = OpIAdd %uint %69 %uint_5
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97
-OpStore %98 %92
-%100 = OpIAdd %uint %69 %uint_6
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100
-OpStore %101 %93
-%103 = OpIAdd %uint %69 %uint_7
-%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103
-OpStore %104 %59
-%106 = OpIAdd %uint %69 %uint_8
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106
-OpStore %107 %60
-%109 = OpIAdd %uint %69 %uint_9
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109
-OpStore %110 %61
-OpBranch %73
-%73 = OpLabel
-OpReturn
-OpFunctionEnd
-%115 = OpFunction %uint None %116
-%117 = OpFunctionParameter %uint
-%118 = OpFunctionParameter %uint
-%119 = OpFunctionParameter %uint
-%120 = OpFunctionParameter %uint
-%121 = OpLabel
-%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117
-%123 = OpLoad %uint %122
-%124 = OpIAdd %uint %123 %118
-%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124
-%126 = OpLoad %uint %125
-%127 = OpIAdd %uint %126 %119
-%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127
-%129 = OpLoad %uint %128
-%130 = OpIAdd %uint %129 %120
-%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130
-%132 = OpLoad %uint %131
-OpReturnValue %132
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -5501,14 +3087,17 @@
   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability RuntimeDescriptorArray
+  // clang-format off
+  const std::string defs = R"(
+OpCapability RuntimeDescriptorArray
 OpCapability RayTracingNV
 OpExtension "SPV_EXT_descriptor_indexing"
 OpExtension "SPV_NV_ray_tracing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint AnyHitNV %main "main"
+; CHECK: OpEntryPoint AnyHitNV %main "main" %89
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -5526,51 +3115,11 @@
 OpDecorate %images DescriptorSet 0
 OpDecorate %images Binding 1
 OpDecorate %images NonWritable
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
 %void = OpTypeVoid
-)";
-
-  const std::string defs_after =
-      R"(OpCapability RuntimeDescriptorArray
-OpCapability RayTracingNV
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_NV_ray_tracing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint AnyHitNV %main "main" %89
-OpSource GLSL 460
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpSourceExtension "GL_NV_ray_tracing"
-OpName %main "main"
-OpName %StorageBuffer "StorageBuffer"
-OpMemberName %StorageBuffer 0 "index"
-OpMemberName %StorageBuffer 1 "red"
-OpName %sbo "sbo"
-OpName %images "images"
-OpMemberDecorate %StorageBuffer 0 Offset 0
-OpMemberDecorate %StorageBuffer 1 Offset 4
-OpDecorate %StorageBuffer BufferBlock
-OpDecorate %sbo DescriptorSet 0
-OpDecorate %sbo Binding 0
-OpDecorate %images DescriptorSet 0
-OpDecorate %images Binding 1
-OpDecorate %images NonWritable
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_39 Block
-OpMemberDecorate %_struct_39 0 Offset 0
-OpDecorate %41 DescriptorSet 7
-OpDecorate %41 Binding 1
-OpDecorate %_struct_63 Block
-OpMemberDecorate %_struct_63 0 Offset 0
-OpMemberDecorate %_struct_63 1 Offset 4
-OpDecorate %65 DescriptorSet 7
-OpDecorate %65 Binding 0
-OpDecorate %89 BuiltIn LaunchIdNV
-%void = OpTypeVoid
-)";
-
-  const std::string func_before =
-      R"(%3 = OpTypeFunction %void
+%3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
 %float = OpTypeFloat 32
 %StorageBuffer = OpTypeStruct %uint %float
@@ -5590,6 +3139,23 @@
 %v4float = OpTypeVector %float 4
 %uint_0 = OpConstant %uint 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %34 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v3uint = OpTypeVector %uint 3
+; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
+; CHECK: %113 = OpConstantNull %v4float
+; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
+; CHECK: %141 = OpConstantNull %uint
+)";
+  // clang-format on
+
+  const std::string main_func = R"(
 %main = OpFunction %void None %3
 %5 = OpLabel
 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
@@ -5600,211 +3166,69 @@
 %29 = OpCompositeExtract %float %27 0
 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
 OpStore %31 %29
+; CHECK-NOT: OpStore %31 %29
+; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %134 = OpULessThan %bool %uint_0 %133
+; CHECK: OpSelectionMerge %135 None
+; CHECK: OpBranchConditional %134 %136 %137
+; CHECK: %136 = OpLabel
+; CHECK: %138 = OpLoad %uint %25
+; CHECK: OpBranch %135
+; CHECK: %137 = OpLabel
+; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %135
+; CHECK: %135 = OpLabel
+; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
+; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
+; CHECK: %28 = OpLoad %13 %27
+; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
+; CHECK: %50 = OpULessThan %bool %142 %48
+; CHECK: OpSelectionMerge %51 None
+; CHECK: OpBranchConditional %50 %52 %53
+; CHECK: %52 = OpLabel
+; CHECK: %54 = OpLoad %13 %27
+; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
+; CHECK: %144 = OpULessThan %bool %uint_0 %143
+; CHECK: OpSelectionMerge %145 None
+; CHECK: OpBranchConditional %144 %146 %147
+; CHECK: %146 = OpLabel
+; CHECK: %148 = OpLoad %13 %27
+; CHECK: %149 = OpImageRead %v4float %148 %20
+; CHECK: OpBranch %145
+; CHECK: %147 = OpLabel
+; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
+; CHECK: OpBranch %145
+; CHECK: %145 = OpLabel
+; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
+; CHECK: OpBranch %51
+; CHECK: %53 = OpLabel
+; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: OpBranch %51
+; CHECK: %51 = OpLabel
+; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
+; CHECK: %30 = OpCompositeExtract %float %114 0
+; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
+; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %153 = OpULessThan %bool %uint_0 %152
+; CHECK: OpSelectionMerge %154 None
+; CHECK: OpBranchConditional %153 %155 %156
+; CHECK: %155 = OpLabel
+; CHECK: OpStore %31 %30
+; CHECK: OpBranch %154
+; CHECK: %156 = OpLabel
+; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %154
+; CHECK: %154 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%7 = OpTypeFunction %void
-%uint = OpTypeInt 32 0
-%float = OpTypeFloat 32
-%StorageBuffer = OpTypeStruct %uint %float
-%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
-%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
-%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
-%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
-%_runtimearr_13 = OpTypeRuntimeArray %13
-%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
-%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
-%v2int = OpTypeVector %int 2
-%20 = OpConstantComposite %v2int %int_0 %int_0
-%v4float = OpTypeVector %float 4
-%uint_0 = OpConstant %uint 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint_1 = OpConstant %uint 1
-%34 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_39 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
-%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%57 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_63 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63
-%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_5315 = OpConstant %uint 5315
-%uint_3 = OpConstant %uint 3
-%v3uint = OpTypeVector %uint 3
-%_ptr_Input_v3uint = OpTypePointer Input %v3uint
-%89 = OpVariable %_ptr_Input_v3uint Input
-%uint_5 = OpConstant %uint 5
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_51 = OpConstant %uint 51
-%113 = OpConstantNull %v4float
-%116 = OpTypeFunction %uint %uint %uint %uint %uint
-%uint_48 = OpConstant %uint 48
-%141 = OpConstantNull %uint
-%uint_54 = OpConstant %uint 54
-%main = OpFunction %void None %7
-%24 = OpLabel
-%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
-%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%134 = OpULessThan %bool %uint_0 %133
-OpSelectionMerge %135 None
-OpBranchConditional %134 %136 %137
-%136 = OpLabel
-%138 = OpLoad %uint %25
-OpBranch %135
-%137 = OpLabel
-%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0
-OpBranch %135
-%135 = OpLabel
-%142 = OpPhi %uint %138 %136 %141 %137
-%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
-%28 = OpLoad %13 %27
-%48 = OpFunctionCall %uint %33 %uint_1 %uint_1
-%50 = OpULessThan %bool %142 %48
-OpSelectionMerge %51 None
-OpBranchConditional %50 %52 %53
-%52 = OpLabel
-%54 = OpLoad %13 %27
-%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142
-%144 = OpULessThan %bool %uint_0 %143
-OpSelectionMerge %145 None
-OpBranchConditional %144 %146 %147
-%146 = OpLabel
-%148 = OpLoad %13 %27
-%149 = OpImageRead %v4float %148 %20
-OpBranch %145
-%147 = OpLabel
-%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0
-OpBranch %145
-%145 = OpLabel
-%151 = OpPhi %v4float %149 %146 %113 %147
-OpBranch %51
-%53 = OpLabel
-%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48
-OpBranch %51
-%51 = OpLabel
-%114 = OpPhi %v4float %151 %145 %113 %53
-%30 = OpCompositeExtract %float %114 0
-%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
-%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%153 = OpULessThan %bool %uint_0 %152
-OpSelectionMerge %154 None
-OpBranchConditional %153 %155 %156
-%155 = OpLabel
-OpStore %31 %30
-OpBranch %154
-%156 = OpLabel
-%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0
-OpBranch %154
-%154 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%33 = OpFunction %uint None %34
-%35 = OpFunctionParameter %uint
-%36 = OpFunctionParameter %uint
-%37 = OpLabel
-%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35
-%44 = OpLoad %uint %43
-%45 = OpIAdd %uint %44 %36
-%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45
-%47 = OpLoad %uint %46
-OpReturnValue %47
-OpFunctionEnd
-%56 = OpFunction %void None %57
-%58 = OpFunctionParameter %uint
-%59 = OpFunctionParameter %uint
-%60 = OpFunctionParameter %uint
-%61 = OpFunctionParameter %uint
-%62 = OpLabel
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0
-%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10
-%70 = OpIAdd %uint %69 %uint_10
-%71 = OpArrayLength %uint %65 1
-%72 = OpULessThanEqual %bool %70 %71
-OpSelectionMerge %73 None
-OpBranchConditional %72 %74 %73
-%74 = OpLabel
-%75 = OpIAdd %uint %69 %uint_0
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75
-OpStore %76 %uint_10
-%78 = OpIAdd %uint %69 %uint_1
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78
-OpStore %79 %uint_23
-%81 = OpIAdd %uint %69 %uint_2
-%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81
-OpStore %82 %58
-%85 = OpIAdd %uint %69 %uint_3
-%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85
-OpStore %86 %uint_5315
-%90 = OpLoad %v3uint %89
-%91 = OpCompositeExtract %uint %90 0
-%92 = OpCompositeExtract %uint %90 1
-%93 = OpCompositeExtract %uint %90 2
-%94 = OpIAdd %uint %69 %uint_4
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94
-OpStore %95 %91
-%97 = OpIAdd %uint %69 %uint_5
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97
-OpStore %98 %92
-%100 = OpIAdd %uint %69 %uint_6
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100
-OpStore %101 %93
-%103 = OpIAdd %uint %69 %uint_7
-%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103
-OpStore %104 %59
-%106 = OpIAdd %uint %69 %uint_8
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106
-OpStore %107 %60
-%109 = OpIAdd %uint %69 %uint_9
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109
-OpStore %110 %61
-OpBranch %73
-%73 = OpLabel
-OpReturn
-OpFunctionEnd
-%115 = OpFunction %uint None %116
-%117 = OpFunctionParameter %uint
-%118 = OpFunctionParameter %uint
-%119 = OpFunctionParameter %uint
-%120 = OpFunctionParameter %uint
-%121 = OpLabel
-%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117
-%123 = OpLoad %uint %122
-%124 = OpIAdd %uint %123 %118
-%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124
-%126 = OpLoad %uint %125
-%127 = OpIAdd %uint %126 %119
-%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127
-%129 = OpLoad %uint %128
-%130 = OpIAdd %uint %129 %120
-%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130
-%132 = OpLoad %uint %131
-OpReturnValue %132
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -5825,14 +3249,17 @@
   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability RuntimeDescriptorArray
+  // clang-format off
+  const std::string defs = R"(
+OpCapability RuntimeDescriptorArray
 OpCapability RayTracingNV
 OpExtension "SPV_EXT_descriptor_indexing"
 OpExtension "SPV_NV_ray_tracing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint ClosestHitNV %main "main"
+; CHECK: OpEntryPoint ClosestHitNV %main "main" %89
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -5850,51 +3277,11 @@
 OpDecorate %images DescriptorSet 0
 OpDecorate %images Binding 1
 OpDecorate %images NonWritable
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
 %void = OpTypeVoid
-)";
-
-  const std::string defs_after =
-      R"(OpCapability RuntimeDescriptorArray
-OpCapability RayTracingNV
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_NV_ray_tracing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint ClosestHitNV %main "main" %89
-OpSource GLSL 460
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpSourceExtension "GL_NV_ray_tracing"
-OpName %main "main"
-OpName %StorageBuffer "StorageBuffer"
-OpMemberName %StorageBuffer 0 "index"
-OpMemberName %StorageBuffer 1 "red"
-OpName %sbo "sbo"
-OpName %images "images"
-OpMemberDecorate %StorageBuffer 0 Offset 0
-OpMemberDecorate %StorageBuffer 1 Offset 4
-OpDecorate %StorageBuffer BufferBlock
-OpDecorate %sbo DescriptorSet 0
-OpDecorate %sbo Binding 0
-OpDecorate %images DescriptorSet 0
-OpDecorate %images Binding 1
-OpDecorate %images NonWritable
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_39 Block
-OpMemberDecorate %_struct_39 0 Offset 0
-OpDecorate %41 DescriptorSet 7
-OpDecorate %41 Binding 1
-OpDecorate %_struct_63 Block
-OpMemberDecorate %_struct_63 0 Offset 0
-OpMemberDecorate %_struct_63 1 Offset 4
-OpDecorate %65 DescriptorSet 7
-OpDecorate %65 Binding 0
-OpDecorate %89 BuiltIn LaunchIdNV
-%void = OpTypeVoid
-)";
-
-  const std::string func_before =
-      R"(%3 = OpTypeFunction %void
+%3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
 %float = OpTypeFloat 32
 %StorageBuffer = OpTypeStruct %uint %float
@@ -5914,6 +3301,23 @@
 %v4float = OpTypeVector %float 4
 %uint_0 = OpConstant %uint 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %34 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v3uint = OpTypeVector %uint 3
+; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
+; CHECK: %113 = OpConstantNull %v4float
+; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
+; CHECK: %141 = OpConstantNull %uint
+)";
+  // clang-format on
+
+  const std::string main_func = R"(
 %main = OpFunction %void None %3
 %5 = OpLabel
 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
@@ -5924,211 +3328,69 @@
 %29 = OpCompositeExtract %float %27 0
 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
 OpStore %31 %29
+; CHECK-NOT: OpStore %31 %29
+; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %134 = OpULessThan %bool %uint_0 %133
+; CHECK: OpSelectionMerge %135 None
+; CHECK: OpBranchConditional %134 %136 %137
+; CHECK: %136 = OpLabel
+; CHECK: %138 = OpLoad %uint %25
+; CHECK: OpBranch %135
+; CHECK: %137 = OpLabel
+; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %135
+; CHECK: %135 = OpLabel
+; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
+; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
+; CHECK: %28 = OpLoad %13 %27
+; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
+; CHECK: %50 = OpULessThan %bool %142 %48
+; CHECK: OpSelectionMerge %51 None
+; CHECK: OpBranchConditional %50 %52 %53
+; CHECK: %52 = OpLabel
+; CHECK: %54 = OpLoad %13 %27
+; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
+; CHECK: %144 = OpULessThan %bool %uint_0 %143
+; CHECK: OpSelectionMerge %145 None
+; CHECK: OpBranchConditional %144 %146 %147
+; CHECK: %146 = OpLabel
+; CHECK: %148 = OpLoad %13 %27
+; CHECK: %149 = OpImageRead %v4float %148 %20
+; CHECK: OpBranch %145
+; CHECK: %147 = OpLabel
+; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
+; CHECK: OpBranch %145
+; CHECK: %145 = OpLabel
+; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
+; CHECK: OpBranch %51
+; CHECK: %53 = OpLabel
+; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: OpBranch %51
+; CHECK: %51 = OpLabel
+; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
+; CHECK: %30 = OpCompositeExtract %float %114 0
+; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
+; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %153 = OpULessThan %bool %uint_0 %152
+; CHECK: OpSelectionMerge %154 None
+; CHECK: OpBranchConditional %153 %155 %156
+; CHECK: %155 = OpLabel
+; CHECK: OpStore %31 %30
+; CHECK: OpBranch %154
+; CHECK: %156 = OpLabel
+; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %154
+; CHECK: %154 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%7 = OpTypeFunction %void
-%uint = OpTypeInt 32 0
-%float = OpTypeFloat 32
-%StorageBuffer = OpTypeStruct %uint %float
-%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
-%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
-%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
-%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
-%_runtimearr_13 = OpTypeRuntimeArray %13
-%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
-%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
-%v2int = OpTypeVector %int 2
-%20 = OpConstantComposite %v2int %int_0 %int_0
-%v4float = OpTypeVector %float 4
-%uint_0 = OpConstant %uint 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint_1 = OpConstant %uint 1
-%34 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_39 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
-%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%57 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_63 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63
-%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_5316 = OpConstant %uint 5316
-%uint_3 = OpConstant %uint 3
-%v3uint = OpTypeVector %uint 3
-%_ptr_Input_v3uint = OpTypePointer Input %v3uint
-%89 = OpVariable %_ptr_Input_v3uint Input
-%uint_5 = OpConstant %uint 5
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_51 = OpConstant %uint 51
-%113 = OpConstantNull %v4float
-%116 = OpTypeFunction %uint %uint %uint %uint %uint
-%uint_48 = OpConstant %uint 48
-%141 = OpConstantNull %uint
-%uint_54 = OpConstant %uint 54
-%main = OpFunction %void None %7
-%24 = OpLabel
-%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
-%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%134 = OpULessThan %bool %uint_0 %133
-OpSelectionMerge %135 None
-OpBranchConditional %134 %136 %137
-%136 = OpLabel
-%138 = OpLoad %uint %25
-OpBranch %135
-%137 = OpLabel
-%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0
-OpBranch %135
-%135 = OpLabel
-%142 = OpPhi %uint %138 %136 %141 %137
-%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
-%28 = OpLoad %13 %27
-%48 = OpFunctionCall %uint %33 %uint_1 %uint_1
-%50 = OpULessThan %bool %142 %48
-OpSelectionMerge %51 None
-OpBranchConditional %50 %52 %53
-%52 = OpLabel
-%54 = OpLoad %13 %27
-%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142
-%144 = OpULessThan %bool %uint_0 %143
-OpSelectionMerge %145 None
-OpBranchConditional %144 %146 %147
-%146 = OpLabel
-%148 = OpLoad %13 %27
-%149 = OpImageRead %v4float %148 %20
-OpBranch %145
-%147 = OpLabel
-%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0
-OpBranch %145
-%145 = OpLabel
-%151 = OpPhi %v4float %149 %146 %113 %147
-OpBranch %51
-%53 = OpLabel
-%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48
-OpBranch %51
-%51 = OpLabel
-%114 = OpPhi %v4float %151 %145 %113 %53
-%30 = OpCompositeExtract %float %114 0
-%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
-%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%153 = OpULessThan %bool %uint_0 %152
-OpSelectionMerge %154 None
-OpBranchConditional %153 %155 %156
-%155 = OpLabel
-OpStore %31 %30
-OpBranch %154
-%156 = OpLabel
-%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0
-OpBranch %154
-%154 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%33 = OpFunction %uint None %34
-%35 = OpFunctionParameter %uint
-%36 = OpFunctionParameter %uint
-%37 = OpLabel
-%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35
-%44 = OpLoad %uint %43
-%45 = OpIAdd %uint %44 %36
-%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45
-%47 = OpLoad %uint %46
-OpReturnValue %47
-OpFunctionEnd
-%56 = OpFunction %void None %57
-%58 = OpFunctionParameter %uint
-%59 = OpFunctionParameter %uint
-%60 = OpFunctionParameter %uint
-%61 = OpFunctionParameter %uint
-%62 = OpLabel
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0
-%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10
-%70 = OpIAdd %uint %69 %uint_10
-%71 = OpArrayLength %uint %65 1
-%72 = OpULessThanEqual %bool %70 %71
-OpSelectionMerge %73 None
-OpBranchConditional %72 %74 %73
-%74 = OpLabel
-%75 = OpIAdd %uint %69 %uint_0
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75
-OpStore %76 %uint_10
-%78 = OpIAdd %uint %69 %uint_1
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78
-OpStore %79 %uint_23
-%81 = OpIAdd %uint %69 %uint_2
-%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81
-OpStore %82 %58
-%85 = OpIAdd %uint %69 %uint_3
-%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85
-OpStore %86 %uint_5316
-%90 = OpLoad %v3uint %89
-%91 = OpCompositeExtract %uint %90 0
-%92 = OpCompositeExtract %uint %90 1
-%93 = OpCompositeExtract %uint %90 2
-%94 = OpIAdd %uint %69 %uint_4
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94
-OpStore %95 %91
-%97 = OpIAdd %uint %69 %uint_5
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97
-OpStore %98 %92
-%100 = OpIAdd %uint %69 %uint_6
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100
-OpStore %101 %93
-%103 = OpIAdd %uint %69 %uint_7
-%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103
-OpStore %104 %59
-%106 = OpIAdd %uint %69 %uint_8
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106
-OpStore %107 %60
-%109 = OpIAdd %uint %69 %uint_9
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109
-OpStore %110 %61
-OpBranch %73
-%73 = OpLabel
-OpReturn
-OpFunctionEnd
-%115 = OpFunction %uint None %116
-%117 = OpFunctionParameter %uint
-%118 = OpFunctionParameter %uint
-%119 = OpFunctionParameter %uint
-%120 = OpFunctionParameter %uint
-%121 = OpLabel
-%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117
-%123 = OpLoad %uint %122
-%124 = OpIAdd %uint %123 %118
-%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124
-%126 = OpLoad %uint %125
-%127 = OpIAdd %uint %126 %119
-%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127
-%129 = OpLoad %uint %128
-%130 = OpIAdd %uint %129 %120
-%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130
-%132 = OpLoad %uint %131
-OpReturnValue %132
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -6149,14 +3411,17 @@
   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability RuntimeDescriptorArray
+  // clang-format off
+  const std::string defs = R"(
+OpCapability RuntimeDescriptorArray
 OpCapability RayTracingNV
 OpExtension "SPV_EXT_descriptor_indexing"
 OpExtension "SPV_NV_ray_tracing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint MissNV %main "main"
+; CHECK: OpEntryPoint MissNV %main "main" %89
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -6174,51 +3439,11 @@
 OpDecorate %images DescriptorSet 0
 OpDecorate %images Binding 1
 OpDecorate %images NonWritable
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
 %void = OpTypeVoid
-)";
-
-  const std::string defs_after =
-      R"(OpCapability RuntimeDescriptorArray
-OpCapability RayTracingNV
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_NV_ray_tracing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint MissNV %main "main" %89
-OpSource GLSL 460
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpSourceExtension "GL_NV_ray_tracing"
-OpName %main "main"
-OpName %StorageBuffer "StorageBuffer"
-OpMemberName %StorageBuffer 0 "index"
-OpMemberName %StorageBuffer 1 "red"
-OpName %sbo "sbo"
-OpName %images "images"
-OpMemberDecorate %StorageBuffer 0 Offset 0
-OpMemberDecorate %StorageBuffer 1 Offset 4
-OpDecorate %StorageBuffer BufferBlock
-OpDecorate %sbo DescriptorSet 0
-OpDecorate %sbo Binding 0
-OpDecorate %images DescriptorSet 0
-OpDecorate %images Binding 1
-OpDecorate %images NonWritable
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_39 Block
-OpMemberDecorate %_struct_39 0 Offset 0
-OpDecorate %41 DescriptorSet 7
-OpDecorate %41 Binding 1
-OpDecorate %_struct_63 Block
-OpMemberDecorate %_struct_63 0 Offset 0
-OpMemberDecorate %_struct_63 1 Offset 4
-OpDecorate %65 DescriptorSet 7
-OpDecorate %65 Binding 0
-OpDecorate %89 BuiltIn LaunchIdNV
-%void = OpTypeVoid
-)";
-
-  const std::string func_before =
-      R"(%3 = OpTypeFunction %void
+%3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
 %float = OpTypeFloat 32
 %StorageBuffer = OpTypeStruct %uint %float
@@ -6238,6 +3463,23 @@
 %v4float = OpTypeVector %float 4
 %uint_0 = OpConstant %uint 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %34 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v3uint = OpTypeVector %uint 3
+; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
+; CHECK: %113 = OpConstantNull %v4float
+; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
+; CHECK: %141 = OpConstantNull %uint
+)";
+  // clang-format on
+
+  const std::string main_func = R"(
 %main = OpFunction %void None %3
 %5 = OpLabel
 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
@@ -6248,211 +3490,69 @@
 %29 = OpCompositeExtract %float %27 0
 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
 OpStore %31 %29
+; CHECK-NOT OpStore %31 %29
+; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %134 = OpULessThan %bool %uint_0 %133
+; CHECK: OpSelectionMerge %135 None
+; CHECK: OpBranchConditional %134 %136 %137
+; CHECK: %136 = OpLabel
+; CHECK: %138 = OpLoad %uint %25
+; CHECK: OpBranch %135
+; CHECK: %137 = OpLabel
+; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %135
+; CHECK: %135 = OpLabel
+; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
+; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
+; CHECK: %28 = OpLoad %13 %27
+; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
+; CHECK: %50 = OpULessThan %bool %142 %48
+; CHECK: OpSelectionMerge %51 None
+; CHECK: OpBranchConditional %50 %52 %53
+; CHECK: %52 = OpLabel
+; CHECK: %54 = OpLoad %13 %27
+; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
+; CHECK: %144 = OpULessThan %bool %uint_0 %143
+; CHECK: OpSelectionMerge %145 None
+; CHECK: OpBranchConditional %144 %146 %147
+; CHECK: %146 = OpLabel
+; CHECK: %148 = OpLoad %13 %27
+; CHECK: %149 = OpImageRead %v4float %148 %20
+; CHECK: OpBranch %145
+; CHECK: %147 = OpLabel
+; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
+; CHECK: OpBranch %145
+; CHECK: %145 = OpLabel
+; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
+; CHECK: OpBranch %51
+; CHECK: %53 = OpLabel
+; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: OpBranch %51
+; CHECK: %51 = OpLabel
+; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
+; CHECK: %30 = OpCompositeExtract %float %114 0
+; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
+; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %153 = OpULessThan %bool %uint_0 %152
+; CHECK: OpSelectionMerge %154 None
+; CHECK: OpBranchConditional %153 %155 %156
+; CHECK: %155 = OpLabel
+; CHECK: OpStore %31 %30
+; CHECK: OpBranch %154
+; CHECK: %156 = OpLabel
+; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %154
+; CHECK: %154 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%7 = OpTypeFunction %void
-%uint = OpTypeInt 32 0
-%float = OpTypeFloat 32
-%StorageBuffer = OpTypeStruct %uint %float
-%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
-%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
-%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
-%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
-%_runtimearr_13 = OpTypeRuntimeArray %13
-%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
-%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
-%v2int = OpTypeVector %int 2
-%20 = OpConstantComposite %v2int %int_0 %int_0
-%v4float = OpTypeVector %float 4
-%uint_0 = OpConstant %uint 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint_1 = OpConstant %uint 1
-%34 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_39 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
-%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%57 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_63 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63
-%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_5317 = OpConstant %uint 5317
-%uint_3 = OpConstant %uint 3
-%v3uint = OpTypeVector %uint 3
-%_ptr_Input_v3uint = OpTypePointer Input %v3uint
-%89 = OpVariable %_ptr_Input_v3uint Input
-%uint_5 = OpConstant %uint 5
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_51 = OpConstant %uint 51
-%113 = OpConstantNull %v4float
-%116 = OpTypeFunction %uint %uint %uint %uint %uint
-%uint_48 = OpConstant %uint 48
-%141 = OpConstantNull %uint
-%uint_54 = OpConstant %uint 54
-%main = OpFunction %void None %7
-%24 = OpLabel
-%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
-%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%134 = OpULessThan %bool %uint_0 %133
-OpSelectionMerge %135 None
-OpBranchConditional %134 %136 %137
-%136 = OpLabel
-%138 = OpLoad %uint %25
-OpBranch %135
-%137 = OpLabel
-%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0
-OpBranch %135
-%135 = OpLabel
-%142 = OpPhi %uint %138 %136 %141 %137
-%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
-%28 = OpLoad %13 %27
-%48 = OpFunctionCall %uint %33 %uint_1 %uint_1
-%50 = OpULessThan %bool %142 %48
-OpSelectionMerge %51 None
-OpBranchConditional %50 %52 %53
-%52 = OpLabel
-%54 = OpLoad %13 %27
-%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142
-%144 = OpULessThan %bool %uint_0 %143
-OpSelectionMerge %145 None
-OpBranchConditional %144 %146 %147
-%146 = OpLabel
-%148 = OpLoad %13 %27
-%149 = OpImageRead %v4float %148 %20
-OpBranch %145
-%147 = OpLabel
-%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0
-OpBranch %145
-%145 = OpLabel
-%151 = OpPhi %v4float %149 %146 %113 %147
-OpBranch %51
-%53 = OpLabel
-%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48
-OpBranch %51
-%51 = OpLabel
-%114 = OpPhi %v4float %151 %145 %113 %53
-%30 = OpCompositeExtract %float %114 0
-%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
-%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%153 = OpULessThan %bool %uint_0 %152
-OpSelectionMerge %154 None
-OpBranchConditional %153 %155 %156
-%155 = OpLabel
-OpStore %31 %30
-OpBranch %154
-%156 = OpLabel
-%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0
-OpBranch %154
-%154 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%33 = OpFunction %uint None %34
-%35 = OpFunctionParameter %uint
-%36 = OpFunctionParameter %uint
-%37 = OpLabel
-%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35
-%44 = OpLoad %uint %43
-%45 = OpIAdd %uint %44 %36
-%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45
-%47 = OpLoad %uint %46
-OpReturnValue %47
-OpFunctionEnd
-%56 = OpFunction %void None %57
-%58 = OpFunctionParameter %uint
-%59 = OpFunctionParameter %uint
-%60 = OpFunctionParameter %uint
-%61 = OpFunctionParameter %uint
-%62 = OpLabel
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0
-%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10
-%70 = OpIAdd %uint %69 %uint_10
-%71 = OpArrayLength %uint %65 1
-%72 = OpULessThanEqual %bool %70 %71
-OpSelectionMerge %73 None
-OpBranchConditional %72 %74 %73
-%74 = OpLabel
-%75 = OpIAdd %uint %69 %uint_0
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75
-OpStore %76 %uint_10
-%78 = OpIAdd %uint %69 %uint_1
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78
-OpStore %79 %uint_23
-%81 = OpIAdd %uint %69 %uint_2
-%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81
-OpStore %82 %58
-%85 = OpIAdd %uint %69 %uint_3
-%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85
-OpStore %86 %uint_5317
-%90 = OpLoad %v3uint %89
-%91 = OpCompositeExtract %uint %90 0
-%92 = OpCompositeExtract %uint %90 1
-%93 = OpCompositeExtract %uint %90 2
-%94 = OpIAdd %uint %69 %uint_4
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94
-OpStore %95 %91
-%97 = OpIAdd %uint %69 %uint_5
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97
-OpStore %98 %92
-%100 = OpIAdd %uint %69 %uint_6
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100
-OpStore %101 %93
-%103 = OpIAdd %uint %69 %uint_7
-%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103
-OpStore %104 %59
-%106 = OpIAdd %uint %69 %uint_8
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106
-OpStore %107 %60
-%109 = OpIAdd %uint %69 %uint_9
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109
-OpStore %110 %61
-OpBranch %73
-%73 = OpLabel
-OpReturn
-OpFunctionEnd
-%115 = OpFunction %uint None %116
-%117 = OpFunctionParameter %uint
-%118 = OpFunctionParameter %uint
-%119 = OpFunctionParameter %uint
-%120 = OpFunctionParameter %uint
-%121 = OpLabel
-%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117
-%123 = OpLoad %uint %122
-%124 = OpIAdd %uint %123 %118
-%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124
-%126 = OpLoad %uint %125
-%127 = OpIAdd %uint %126 %119
-%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127
-%129 = OpLoad %uint %128
-%130 = OpIAdd %uint %129 %120
-%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130
-%132 = OpLoad %uint %131
-OpReturnValue %132
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest,
@@ -6473,14 +3573,17 @@
   //    sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability RuntimeDescriptorArray
+  // clang-format off
+  const std::string defs = R"(
+OpCapability RuntimeDescriptorArray
 OpCapability RayTracingNV
 OpExtension "SPV_EXT_descriptor_indexing"
 OpExtension "SPV_NV_ray_tracing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint CallableNV %main "main"
+; CHECK: OpEntryPoint CallableNV %main "main" %89
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -6498,51 +3601,11 @@
 OpDecorate %images DescriptorSet 0
 OpDecorate %images Binding 1
 OpDecorate %images NonWritable
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kInputDecorations + kOutputDecorations + R"(
+; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
 %void = OpTypeVoid
-)";
-
-  const std::string defs_after =
-      R"(OpCapability RuntimeDescriptorArray
-OpCapability RayTracingNV
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_NV_ray_tracing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint CallableNV %main "main" %89
-OpSource GLSL 460
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpSourceExtension "GL_NV_ray_tracing"
-OpName %main "main"
-OpName %StorageBuffer "StorageBuffer"
-OpMemberName %StorageBuffer 0 "index"
-OpMemberName %StorageBuffer 1 "red"
-OpName %sbo "sbo"
-OpName %images "images"
-OpMemberDecorate %StorageBuffer 0 Offset 0
-OpMemberDecorate %StorageBuffer 1 Offset 4
-OpDecorate %StorageBuffer BufferBlock
-OpDecorate %sbo DescriptorSet 0
-OpDecorate %sbo Binding 0
-OpDecorate %images DescriptorSet 0
-OpDecorate %images Binding 1
-OpDecorate %images NonWritable
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_39 Block
-OpMemberDecorate %_struct_39 0 Offset 0
-OpDecorate %41 DescriptorSet 7
-OpDecorate %41 Binding 1
-OpDecorate %_struct_63 Block
-OpMemberDecorate %_struct_63 0 Offset 0
-OpMemberDecorate %_struct_63 1 Offset 4
-OpDecorate %65 DescriptorSet 7
-OpDecorate %65 Binding 0
-OpDecorate %89 BuiltIn LaunchIdNV
-%void = OpTypeVoid
-)";
-
-  const std::string func_before =
-      R"(%3 = OpTypeFunction %void
+%3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
 %float = OpTypeFloat 32
 %StorageBuffer = OpTypeStruct %uint %float
@@ -6562,6 +3625,23 @@
 %v4float = OpTypeVector %float 4
 %uint_0 = OpConstant %uint 0
 %_ptr_Uniform_float = OpTypePointer Uniform %float
+; CHECK: %34 = OpTypeFunction %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %bool = OpTypeBool
+; CHECK: %57 = OpTypeFunction %void %uint %uint %uint %uint
+)" + kOutputGlobals + R"(
+; CHECK: %v3uint = OpTypeVector %uint 3
+; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+; CHECK: %89 = OpVariable %_ptr_Input_v3uint Input
+; CHECK: %113 = OpConstantNull %v4float
+; CHECK: %116 = OpTypeFunction %uint %uint %uint %uint %uint
+; CHECK: %141 = OpConstantNull %uint
+)";
+  // clang-format on
+
+  const std::string main_func = R"(
 %main = OpFunction %void None %3
 %5 = OpLabel
 %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
@@ -6572,211 +3652,69 @@
 %29 = OpCompositeExtract %float %27 0
 %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
 OpStore %31 %29
+; CHECK-NOT: OpStore %31 %29
+; CHECK: %133 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %134 = OpULessThan %bool %uint_0 %133
+; CHECK: OpSelectionMerge %135 None
+; CHECK: OpBranchConditional %134 %136 %137
+; CHECK: %136 = OpLabel
+; CHECK: %138 = OpLoad %uint %25
+; CHECK: OpBranch %135
+; CHECK: %137 = OpLabel
+; CHECK: %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_48 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %135
+; CHECK: %135 = OpLabel
+; CHECK: %142 = OpPhi %uint %138 %136 %141 %137
+; CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
+; CHECK: %28 = OpLoad %13 %27
+; CHECK: %48 = OpFunctionCall %uint %inst_bindless_direct_read_2 %uint_1 %uint_1
+; CHECK: %50 = OpULessThan %bool %142 %48
+; CHECK: OpSelectionMerge %51 None
+; CHECK: OpBranchConditional %50 %52 %53
+; CHECK: %52 = OpLabel
+; CHECK: %54 = OpLoad %13 %27
+; CHECK: %143 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 %142
+; CHECK: %144 = OpULessThan %bool %uint_0 %143
+; CHECK: OpSelectionMerge %145 None
+; CHECK: OpBranchConditional %144 %146 %147
+; CHECK: %146 = OpLabel
+; CHECK: %148 = OpLoad %13 %27
+; CHECK: %149 = OpImageRead %v4float %148 %20
+; CHECK: OpBranch %145
+; CHECK: %147 = OpLabel
+; CHECK: %150 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_1 %142 %uint_0
+; CHECK: OpBranch %145
+; CHECK: %145 = OpLabel
+; CHECK: %151 = OpPhi %v4float %149 %146 %113 %147
+; CHECK: OpBranch %51
+; CHECK: %53 = OpLabel
+; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: OpBranch %51
+; CHECK: %51 = OpLabel
+; CHECK: %114 = OpPhi %v4float %151 %145 %113 %53
+; CHECK: %30 = OpCompositeExtract %float %114 0
+; CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
+; CHECK: %152 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %153 = OpULessThan %bool %uint_0 %152
+; CHECK: OpSelectionMerge %154 None
+; CHECK: OpBranchConditional %153 %155 %156
+; CHECK: %155 = OpLabel
+; CHECK: OpStore %31 %30
+; CHECK: OpBranch %154
+; CHECK: %156 = OpLabel
+; CHECK: %158 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_54 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %154
+; CHECK: %154 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%7 = OpTypeFunction %void
-%uint = OpTypeInt 32 0
-%float = OpTypeFloat 32
-%StorageBuffer = OpTypeStruct %uint %float
-%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
-%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
-%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
-%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
-%_runtimearr_13 = OpTypeRuntimeArray %13
-%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
-%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
-%v2int = OpTypeVector %int 2
-%20 = OpConstantComposite %v2int %int_0 %int_0
-%v4float = OpTypeVector %float 4
-%uint_0 = OpConstant %uint 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%uint_1 = OpConstant %uint 1
-%34 = OpTypeFunction %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_39 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
-%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%bool = OpTypeBool
-%57 = OpTypeFunction %void %uint %uint %uint %uint
-%_struct_63 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63
-%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_5318 = OpConstant %uint 5318
-%uint_3 = OpConstant %uint 3
-%v3uint = OpTypeVector %uint 3
-%_ptr_Input_v3uint = OpTypePointer Input %v3uint
-%89 = OpVariable %_ptr_Input_v3uint Input
-%uint_5 = OpConstant %uint 5
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_51 = OpConstant %uint 51
-%113 = OpConstantNull %v4float
-%116 = OpTypeFunction %uint %uint %uint %uint %uint
-%uint_48 = OpConstant %uint 48
-%141 = OpConstantNull %uint
-%uint_54 = OpConstant %uint 54
-%main = OpFunction %void None %7
-%24 = OpLabel
-%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
-%133 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%134 = OpULessThan %bool %uint_0 %133
-OpSelectionMerge %135 None
-OpBranchConditional %134 %136 %137
-%136 = OpLabel
-%138 = OpLoad %uint %25
-OpBranch %135
-%137 = OpLabel
-%140 = OpFunctionCall %void %56 %uint_48 %uint_1 %uint_0 %uint_0
-OpBranch %135
-%135 = OpLabel
-%142 = OpPhi %uint %138 %136 %141 %137
-%27 = OpAccessChain %_ptr_UniformConstant_13 %images %142
-%28 = OpLoad %13 %27
-%48 = OpFunctionCall %uint %33 %uint_1 %uint_1
-%50 = OpULessThan %bool %142 %48
-OpSelectionMerge %51 None
-OpBranchConditional %50 %52 %53
-%52 = OpLabel
-%54 = OpLoad %13 %27
-%143 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_1 %142
-%144 = OpULessThan %bool %uint_0 %143
-OpSelectionMerge %145 None
-OpBranchConditional %144 %146 %147
-%146 = OpLabel
-%148 = OpLoad %13 %27
-%149 = OpImageRead %v4float %148 %20
-OpBranch %145
-%147 = OpLabel
-%150 = OpFunctionCall %void %56 %uint_51 %uint_1 %142 %uint_0
-OpBranch %145
-%145 = OpLabel
-%151 = OpPhi %v4float %149 %146 %113 %147
-OpBranch %51
-%53 = OpLabel
-%112 = OpFunctionCall %void %56 %uint_51 %uint_0 %142 %48
-OpBranch %51
-%51 = OpLabel
-%114 = OpPhi %v4float %151 %145 %113 %53
-%30 = OpCompositeExtract %float %114 0
-%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
-%152 = OpFunctionCall %uint %115 %uint_0 %uint_0 %uint_0 %uint_0
-%153 = OpULessThan %bool %uint_0 %152
-OpSelectionMerge %154 None
-OpBranchConditional %153 %155 %156
-%155 = OpLabel
-OpStore %31 %30
-OpBranch %154
-%156 = OpLabel
-%158 = OpFunctionCall %void %56 %uint_54 %uint_1 %uint_0 %uint_0
-OpBranch %154
-%154 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%33 = OpFunction %uint None %34
-%35 = OpFunctionParameter %uint
-%36 = OpFunctionParameter %uint
-%37 = OpLabel
-%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35
-%44 = OpLoad %uint %43
-%45 = OpIAdd %uint %44 %36
-%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45
-%47 = OpLoad %uint %46
-OpReturnValue %47
-OpFunctionEnd
-%56 = OpFunction %void None %57
-%58 = OpFunctionParameter %uint
-%59 = OpFunctionParameter %uint
-%60 = OpFunctionParameter %uint
-%61 = OpFunctionParameter %uint
-%62 = OpLabel
-%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0
-%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10
-%70 = OpIAdd %uint %69 %uint_10
-%71 = OpArrayLength %uint %65 1
-%72 = OpULessThanEqual %bool %70 %71
-OpSelectionMerge %73 None
-OpBranchConditional %72 %74 %73
-%74 = OpLabel
-%75 = OpIAdd %uint %69 %uint_0
-%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75
-OpStore %76 %uint_10
-%78 = OpIAdd %uint %69 %uint_1
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78
-OpStore %79 %uint_23
-%81 = OpIAdd %uint %69 %uint_2
-%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81
-OpStore %82 %58
-%85 = OpIAdd %uint %69 %uint_3
-%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85
-OpStore %86 %uint_5318
-%90 = OpLoad %v3uint %89
-%91 = OpCompositeExtract %uint %90 0
-%92 = OpCompositeExtract %uint %90 1
-%93 = OpCompositeExtract %uint %90 2
-%94 = OpIAdd %uint %69 %uint_4
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94
-OpStore %95 %91
-%97 = OpIAdd %uint %69 %uint_5
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %97
-OpStore %98 %92
-%100 = OpIAdd %uint %69 %uint_6
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %100
-OpStore %101 %93
-%103 = OpIAdd %uint %69 %uint_7
-%104 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %103
-OpStore %104 %59
-%106 = OpIAdd %uint %69 %uint_8
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %106
-OpStore %107 %60
-%109 = OpIAdd %uint %69 %uint_9
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %109
-OpStore %110 %61
-OpBranch %73
-%73 = OpLabel
-OpReturn
-OpFunctionEnd
-%115 = OpFunction %uint None %116
-%117 = OpFunctionParameter %uint
-%118 = OpFunctionParameter %uint
-%119 = OpFunctionParameter %uint
-%120 = OpFunctionParameter %uint
-%121 = OpLabel
-%122 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %117
-%123 = OpLoad %uint %122
-%124 = OpIAdd %uint %123 %118
-%125 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %124
-%126 = OpLoad %uint %125
-%127 = OpIAdd %uint %126 %119
-%128 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %127
-%129 = OpLoad %uint %128
-%130 = OpIAdd %uint %129 %120
-%131 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %130
-%132 = OpLoad %uint %131
-OpReturnValue %132
-OpFunctionEnd
-)";
+  const std::string new_funcs = kDirectRead2 + kStreamWrite4Ray + kDirectRead4;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest, InstBoundsInitSameBlockOpReplication) {
@@ -6806,16 +3744,17 @@
   //   outColor = vec4(x, y, 0.0, 0.0);
   // }
   //
-  // clang-format on
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability ShaderNonUniformEXT
 OpCapability SampledImageArrayNonUniformIndexingEXT
 OpExtension "SPV_EXT_descriptor_indexing"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %inTexcoord %outColor
+; CHECK: OpEntryPoint Fragment %main "main" %inTexcoord %outColor %gl_FragCoord
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
@@ -6845,6 +3784,12 @@
 OpDecorate %uniforms DescriptorSet 0
 OpDecorate %uniforms Binding 0
 OpDecorate %outColor Location 0
+; CHECK: OpDecorate %63 NonUniform
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
+)" + kInputDecorations + R"(
+; CHECK: OpDecorate %151 NonUniform
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %int = OpTypeInt 32 1
@@ -6876,122 +3821,23 @@
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %outColor = OpVariable %_ptr_Output_v4float Output
 %float_0 = OpConstant %float 0
+; CHECK: %bool = OpTypeBool
+; CHECK: %68 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+; CHECK: %v4uint = OpTypeVector %uint 4
+; CHECK: %122 = OpConstantNull %v4float
+; CHECK: %126 = OpTypeFunction %uint %uint %uint %uint %uint
+)" + kInputGlobals + R"(
+; CHECK: %165 = OpConstantNull %v2float
 )";
+  // clang-format on
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability ShaderNonUniform
-OpCapability SampledImageArrayNonUniformIndexing
-OpExtension "SPV_EXT_descriptor_indexing"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %inTexcoord %outColor %gl_FragCoord
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_nonuniform_qualifier"
-OpName %main "main"
-OpName %index "index"
-OpName %x "x"
-OpName %uniformTexArr "uniformTexArr"
-OpName %uniformSampler "uniformSampler"
-OpName %inTexcoord "inTexcoord"
-OpName %y "y"
-OpName %uniformTex "uniformTex"
-OpName %Uniforms "Uniforms"
-OpMemberName %Uniforms 0 "var0"
-OpName %uniforms "uniforms"
-OpName %outColor "outColor"
-OpDecorate %uniformTexArr DescriptorSet 0
-OpDecorate %uniformTexArr Binding 3
-OpDecorate %19 NonUniform
-OpDecorate %22 NonUniform
-OpDecorate %uniformSampler DescriptorSet 0
-OpDecorate %uniformSampler Binding 1
-OpDecorate %inTexcoord Location 0
-OpDecorate %uniformTex DescriptorSet 0
-OpDecorate %uniformTex Binding 2
-OpMemberDecorate %Uniforms 0 Offset 0
-OpDecorate %Uniforms Block
-OpDecorate %uniforms DescriptorSet 0
-OpDecorate %uniforms Binding 0
-OpDecorate %outColor Location 0
-OpDecorate %63 NonUniform
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_75 Block
-OpMemberDecorate %_struct_75 0 Offset 0
-OpMemberDecorate %_struct_75 1 Offset 4
-OpDecorate %77 DescriptorSet 7
-OpDecorate %77 Binding 0
-OpDecorate %gl_FragCoord BuiltIn FragCoord
-OpDecorate %_struct_132 Block
-OpMemberDecorate %_struct_132 0 Offset 0
-OpDecorate %134 DescriptorSet 7
-OpDecorate %134 Binding 1
-OpDecorate %151 NonUniform
-%void = OpTypeVoid
-%3 = OpTypeFunction %void
-%int = OpTypeInt 32 1
-%_ptr_Function_int = OpTypePointer Function %int
-%int_0 = OpConstant %int 0
-%float = OpTypeFloat 32
-%_ptr_Function_float = OpTypePointer Function %float
-%13 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%uint = OpTypeInt 32 0
-%uint_8 = OpConstant %uint 8
-%_arr_13_uint_8 = OpTypeArray %13 %uint_8
-%_ptr_UniformConstant__arr_13_uint_8 = OpTypePointer UniformConstant %_arr_13_uint_8
-%uniformTexArr = OpVariable %_ptr_UniformConstant__arr_13_uint_8 UniformConstant
-%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
-%23 = OpTypeSampler
-%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23
-%uniformSampler = OpVariable %_ptr_UniformConstant_23 UniformConstant
-%27 = OpTypeSampledImage %13
-%v2float = OpTypeVector %float 2
-%_ptr_Input_v2float = OpTypePointer Input %v2float
-%inTexcoord = OpVariable %_ptr_Input_v2float Input
-%v4float = OpTypeVector %float 4
-%uint_0 = OpConstant %uint 0
-%uniformTex = OpVariable %_ptr_UniformConstant_13 UniformConstant
-%Uniforms = OpTypeStruct %v2float
-%_ptr_Uniform_Uniforms = OpTypePointer Uniform %Uniforms
-%uniforms = OpVariable %_ptr_Uniform_Uniforms Uniform
-%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%outColor = OpVariable %_ptr_Output_v4float Output
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%68 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_75 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_75 = OpTypePointer StorageBuffer %_struct_75
-%77 = OpVariable %_ptr_StorageBuffer__struct_75 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_1 = OpConstant %uint 1
-%uint_23 = OpConstant %uint 23
-%uint_2 = OpConstant %uint 2
-%uint_3 = OpConstant %uint 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-%v4uint = OpTypeVector %uint 4
-%uint_5 = OpConstant %uint 5
-%uint_7 = OpConstant %uint 7
-%uint_9 = OpConstant %uint 9
-%uint_79 = OpConstant %uint 79
-%122 = OpConstantNull %v4float
-%126 = OpTypeFunction %uint %uint %uint %uint %uint
-%_struct_132 = OpTypeStruct %_runtimearr_uint
-%_ptr_StorageBuffer__struct_132 = OpTypePointer StorageBuffer %_struct_132
-%134 = OpVariable %_ptr_StorageBuffer__struct_132 StorageBuffer
-%uint_87 = OpConstant %uint 87
-%165 = OpConstantNull %v2float
-%uint_89 = OpConstant %uint 89
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %index = OpVariable %_ptr_Function_int Function
 %x = OpVariable %_ptr_Function_float Function
@@ -7015,6 +3861,36 @@
 %49 = OpFMul %v2float %42 %48
 %50 = OpImageSampleImplicitLod %v4float %41 %49
 %51 = OpCompositeExtract %float %50 0
+; CHECK-NOT: %51 = OpCompositeExtract %float %50 0
+; CHECK: %157 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
+; CHECK: %158 = OpULessThan %bool %uint_0 %157
+; CHECK: OpSelectionMerge %159 None
+; CHECK: OpBranchConditional %158 %160 %161
+; CHECK: %160 = OpLabel
+; CHECK: %162 = OpLoad %v2float %47
+; CHECK: OpBranch %159
+; CHECK: %161 = OpLabel
+; CHECK: %164 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_87 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %159
+; CHECK: %159 = OpLabel
+; CHECK: %166 = OpPhi %v2float %162 %160 %165 %161
+; CHECK: %49 = OpFMul %v2float %42 %166
+; CHECK: %167 = OpSampledImage %27 %39 %40
+; CHECK: %168 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_2 %uint_0
+; CHECK: %169 = OpULessThan %bool %uint_0 %168
+; CHECK: OpSelectionMerge %170 None
+; CHECK: OpBranchConditional %169 %171 %172
+; CHECK: %171 = OpLabel
+; CHECK: %173 = OpLoad %13 %uniformTex
+; CHECK: %174 = OpSampledImage %27 %173 %40
+; CHECK: %175 = OpImageSampleImplicitLod %v4float %174 %49
+; CHECK: OpBranch %170
+; CHECK: %172 = OpLabel
+; CHECK: %177 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_89 %uint_1 %uint_0 %uint_0
+; CHECK: OpBranch %170
+; CHECK: %170 = OpLabel
+; CHECK: %178 = OpPhi %v4float %175 %171 %122 %172
+; CHECK: %51 = OpCompositeExtract %float %178 0
 OpStore %y %51
 %54 = OpLoad %float %x
 %55 = OpLoad %float %y
@@ -7024,168 +3900,12 @@
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %3
-%5 = OpLabel
-%index = OpVariable %_ptr_Function_int Function
-%x = OpVariable %_ptr_Function_float Function
-%y = OpVariable %_ptr_Function_float Function
-OpStore %index %int_0
-%19 = OpLoad %int %index
-%21 = OpAccessChain %_ptr_UniformConstant_13 %uniformTexArr %19
-%22 = OpLoad %13 %21
-%26 = OpLoad %23 %uniformSampler
-%28 = OpSampledImage %27 %22 %26
-%32 = OpLoad %v2float %inTexcoord
-%59 = OpULessThan %bool %19 %uint_8
-OpSelectionMerge %60 None
-OpBranchConditional %59 %61 %62
-%61 = OpLabel
-%63 = OpLoad %13 %21
-%64 = OpSampledImage %27 %63 %26
-%124 = OpBitcast %uint %19
-%146 = OpFunctionCall %uint %125 %uint_0 %uint_0 %uint_3 %124
-%147 = OpULessThan %bool %uint_0 %146
-OpSelectionMerge %148 None
-OpBranchConditional %147 %149 %150
-%149 = OpLabel
-%151 = OpLoad %13 %21
-%152 = OpSampledImage %27 %151 %26
-%153 = OpImageSampleImplicitLod %v4float %152 %32
-OpBranch %148
-%150 = OpLabel
-%154 = OpBitcast %uint %19
-%155 = OpFunctionCall %void %67 %uint_79 %uint_1 %154 %uint_0
-OpBranch %148
-%148 = OpLabel
-%156 = OpPhi %v4float %153 %149 %122 %150
-OpBranch %60
-%62 = OpLabel
-%66 = OpBitcast %uint %19
-%121 = OpFunctionCall %void %67 %uint_79 %uint_0 %66 %uint_8
-OpBranch %60
-%60 = OpLabel
-%123 = OpPhi %v4float %156 %148 %122 %62
-%36 = OpCompositeExtract %float %123 0
-OpStore %x %36
-%39 = OpLoad %13 %uniformTex
-%40 = OpLoad %23 %uniformSampler
-%41 = OpSampledImage %27 %39 %40
-%42 = OpLoad %v2float %inTexcoord
-%47 = OpAccessChain %_ptr_Uniform_v2float %uniforms %int_0
-%157 = OpFunctionCall %uint %125 %uint_0 %uint_0 %uint_0 %uint_0
-%158 = OpULessThan %bool %uint_0 %157
-OpSelectionMerge %159 None
-OpBranchConditional %158 %160 %161
-%160 = OpLabel
-%162 = OpLoad %v2float %47
-OpBranch %159
-%161 = OpLabel
-%164 = OpFunctionCall %void %67 %uint_87 %uint_1 %uint_0 %uint_0
-OpBranch %159
-%159 = OpLabel
-%166 = OpPhi %v2float %162 %160 %165 %161
-%49 = OpFMul %v2float %42 %166
-%167 = OpSampledImage %27 %39 %40
-%168 = OpFunctionCall %uint %125 %uint_0 %uint_0 %uint_2 %uint_0
-%169 = OpULessThan %bool %uint_0 %168
-OpSelectionMerge %170 None
-OpBranchConditional %169 %171 %172
-%171 = OpLabel
-%173 = OpLoad %13 %uniformTex
-%174 = OpSampledImage %27 %173 %40
-%175 = OpImageSampleImplicitLod %v4float %174 %49
-OpBranch %170
-%172 = OpLabel
-%177 = OpFunctionCall %void %67 %uint_89 %uint_1 %uint_0 %uint_0
-OpBranch %170
-%170 = OpLabel
-%178 = OpPhi %v4float %175 %171 %122 %172
-%51 = OpCompositeExtract %float %178 0
-OpStore %y %51
-%54 = OpLoad %float %x
-%55 = OpLoad %float %y
-%57 = OpCompositeConstruct %v4float %54 %55 %float_0 %float_0
-OpStore %outColor %57
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%67 = OpFunction %void None %68
-%69 = OpFunctionParameter %uint
-%70 = OpFunctionParameter %uint
-%71 = OpFunctionParameter %uint
-%72 = OpFunctionParameter %uint
-%73 = OpLabel
-%79 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_0
-%82 = OpAtomicIAdd %uint %79 %uint_4 %uint_0 %uint_10
-%83 = OpIAdd %uint %82 %uint_10
-%84 = OpArrayLength %uint %77 1
-%85 = OpULessThanEqual %bool %83 %84
-OpSelectionMerge %86 None
-OpBranchConditional %85 %87 %86
-%87 = OpLabel
-%88 = OpIAdd %uint %82 %uint_0
-%90 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %88
-OpStore %90 %uint_10
-%92 = OpIAdd %uint %82 %uint_1
-%93 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %92
-OpStore %93 %uint_23
-%95 = OpIAdd %uint %82 %uint_2
-%96 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %95
-OpStore %96 %69
-%98 = OpIAdd %uint %82 %uint_3
-%99 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %98
-OpStore %99 %uint_4
-%102 = OpLoad %v4float %gl_FragCoord
-%104 = OpBitcast %v4uint %102
-%105 = OpCompositeExtract %uint %104 0
-%106 = OpIAdd %uint %82 %uint_4
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %106
-OpStore %107 %105
-%108 = OpCompositeExtract %uint %104 1
-%110 = OpIAdd %uint %82 %uint_5
-%111 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %110
-OpStore %111 %108
-%113 = OpIAdd %uint %82 %uint_7
-%114 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %113
-OpStore %114 %70
-%115 = OpIAdd %uint %82 %uint_8
-%116 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %115
-OpStore %116 %71
-%118 = OpIAdd %uint %82 %uint_9
-%119 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %118
-OpStore %119 %72
-OpBranch %86
-%86 = OpLabel
-OpReturn
-OpFunctionEnd
-%125 = OpFunction %uint None %126
-%127 = OpFunctionParameter %uint
-%128 = OpFunctionParameter %uint
-%129 = OpFunctionParameter %uint
-%130 = OpFunctionParameter %uint
-%131 = OpLabel
-%135 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %127
-%136 = OpLoad %uint %135
-%137 = OpIAdd %uint %136 %128
-%138 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %137
-%139 = OpLoad %uint %138
-%140 = OpIAdd %uint %139 %129
-%141 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %140
-%142 = OpLoad %uint %141
-%143 = OpIAdd %uint %142 %130
-%144 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %143
-%145 = OpLoad %uint %144
-OpReturnValue %145
-OpFunctionEnd
-)";
+  const std::string new_funcs = kStreamWrite4Frag + kDirectRead4;
 
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u, true, true, false, false, false);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(defs + main_func + new_funcs,
+                                               true, 7u, 23u, true, true, false,
+                                               false, false);
 }
 
 TEST_F(InstBindlessTest, MultipleUniformNonAggregateRefsNoDescInit) {
@@ -7225,13 +3945,14 @@
   //   return ps_output;
   // }
 
+  // clang-format off
   const std::string text = R"(
                OpCapability Shader
 ;CHECK:        OpExtension "SPV_KHR_storage_buffer_storage_class"
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
-;CHECK:        OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %130 %157 %gl_FragCoord
+;CHECK:        OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_FragCoord
                OpExecutionMode %MainPs OriginUpperLeft
                OpSource HLSL 500
                OpName %MainPs "MainPs"
@@ -7260,15 +3981,7 @@
                OpDecorate %i_vTextureCoords Location 0
                OpDecorate %_entryPointOutput_vColor Location 0
  ;CHECK:       OpDecorate %_runtimearr_uint ArrayStride 4
- ;CHECK:       OpDecorate %_struct_128 Block
- ;CHECK:       OpMemberDecorate %_struct_128 0 Offset 0
- ;CHECK:       OpDecorate %130 DescriptorSet 7
- ;CHECK:       OpDecorate %130 Binding 1
- ;CHECK:       OpDecorate %_struct_155 Block
- ;CHECK:       OpMemberDecorate %_struct_155 0 Offset 0
- ;CHECK:       OpMemberDecorate %_struct_155 1 Offset 4
- ;CHECK:       OpDecorate %157 DescriptorSet 7
- ;CHECK:       OpDecorate %157 Binding 0
+)" + kInputDecorations + kOutputDecorations + R"(
  ;CHECK:       OpDecorate %gl_FragCoord BuiltIn FragCoord
        %void = OpTypeVoid
           %3 = OpTypeFunction %void
@@ -7300,36 +4013,19 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
- ;CHECK:      %uint_7 = OpConstant %uint 7
- ;CHECK:      %uint_1 = OpConstant %uint 1
  ;CHECK:         %122 = OpTypeFunction %uint %uint %uint %uint
  ;CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
- ;CHECK: %_struct_128 = OpTypeStruct %_runtimearr_uint
- ;CHECK: %_ptr_StorageBuffer__struct_128 = OpTypePointer StorageBuffer %_struct_128
- ;CHECK:         %130 = OpVariable %_ptr_StorageBuffer__struct_128 StorageBuffer
+ )" + kInputGlobals + R"(
  ;CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
- ;CHECK:     %uint_4 = OpConstant %uint 4
  ;CHECK:         %148 = OpTypeFunction %void %uint %uint %uint %uint %uint
- ;CHECK: %_struct_155 = OpTypeStruct %uint %_runtimearr_uint
- ;CHECK: %_ptr_StorageBuffer__struct_155 = OpTypePointer StorageBuffer %_struct_155
- ;CHECK:        %157 = OpVariable %_ptr_StorageBuffer__struct_155 StorageBuffer
- ;CHECK:    %uint_11 = OpConstant %uint 11
- ;CHECK:    %uint_23 = OpConstant %uint 23
- ;CHECK:     %uint_2 = OpConstant %uint 2
- ;CHECK:      %uint_3 = OpConstant %uint 3
+ )" + kOutputGlobals + R"(
  ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
  ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
  ;CHECK:     %v4uint = OpTypeVector %uint 4
- ;CHECK:     %uint_5 = OpConstant %uint 5
- ;CHECK:     %uint_8 = OpConstant %uint 8
- ;CHECK:     %uint_9 = OpConstant %uint 9
- ;CHECK:    %uint_10 = OpConstant %uint 10
- ;CHECK:    %uint_71 = OpConstant %uint 71
  ;CHECK:        %202 = OpConstantNull %v2float
- ;CHECK:    %uint_75 = OpConstant %uint 75
      %MainPs = OpFunction %void None %3
           %5 = OpLabel
- ;CHECK: %140 = OpFunctionCall %uint %121 %uint_1 %uint_1 %uint_0
+ ;CHECK: %140 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_1 %uint_0
  ;CHECK:        OpBranch %117
  ;CHECK: %117 = OpLabel
  ;CHECK:        OpBranch %116
@@ -7352,7 +4048,7 @@
  ;CHECK:        %146 = OpLoad %v2float %86
  ;CHECK:               OpBranch %143
  ;CHECK:        %145 = OpLabel
- ;CHECK:        %201 = OpFunctionCall %void %147 %uint_71 %uint_4 %uint_0 %119 %140
+ ;CHECK:        %201 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_71 %uint_4 %uint_0 %119 %140
  ;CHECK:               OpBranch %143
  ;CHECK:        %143 = OpLabel
  ;CHECK:        %203 = OpPhi %v2float %146 %144 %202 %145
@@ -7369,7 +4065,7 @@
  ;CHECK:        %209 = OpLoad %v2float %89
  ;CHECK:               OpBranch %206
  ;CHECK:        %208 = OpLabel
- ;CHECK:        %211 = OpFunctionCall %void %147 %uint_75 %uint_4 %uint_0 %204 %140
+ ;CHECK:        %211 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_75 %uint_4 %uint_0 %204 %140
  ;CHECK:               OpBranch %206
  ;CHECK:        %206 = OpLabel
  ;CHECK:        %212 = OpPhi %v2float %209 %207 %202 %208
@@ -7386,75 +4082,8 @@
                OpStore %_entryPointOutput_vColor %100
                OpReturn
                OpFunctionEnd
- ;CHECK:        %121 = OpFunction %uint None %122
- ;CHECK:        %123 = OpFunctionParameter %uint
- ;CHECK:        %124 = OpFunctionParameter %uint
- ;CHECK:        %125 = OpFunctionParameter %uint
- ;CHECK:        %126 = OpLabel
- ;CHECK:        %132 = OpAccessChain %_ptr_StorageBuffer_uint %130 %uint_0 %123
- ;CHECK:        %133 = OpLoad %uint %132
- ;CHECK:        %134 = OpIAdd %uint %133 %124
- ;CHECK:        %135 = OpAccessChain %_ptr_StorageBuffer_uint %130 %uint_0 %134
- ;CHECK:        %136 = OpLoad %uint %135
- ;CHECK:        %137 = OpIAdd %uint %136 %125
- ;CHECK:        %138 = OpAccessChain %_ptr_StorageBuffer_uint %130 %uint_0 %137
- ;CHECK:        %139 = OpLoad %uint %138
- ;CHECK:               OpReturnValue %139
- ;CHECK:               OpFunctionEnd
- ;CHECK:        %147 = OpFunction %void None %148
- ;CHECK:        %149 = OpFunctionParameter %uint
- ;CHECK:        %150 = OpFunctionParameter %uint
- ;CHECK:        %151 = OpFunctionParameter %uint
- ;CHECK:        %152 = OpFunctionParameter %uint
- ;CHECK:        %153 = OpFunctionParameter %uint
- ;CHECK:        %154 = OpLabel
- ;CHECK:        %158 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_0
- ;CHECK:        %160 = OpAtomicIAdd %uint %158 %uint_4 %uint_0 %uint_11
- ;CHECK:        %161 = OpIAdd %uint %160 %uint_11
- ;CHECK:        %162 = OpArrayLength %uint %157 1
- ;CHECK:        %163 = OpULessThanEqual %bool %161 %162
- ;CHECK:               OpSelectionMerge %164 None
- ;CHECK:               OpBranchConditional %163 %165 %164
- ;CHECK:        %165 = OpLabel
- ;CHECK:        %166 = OpIAdd %uint %160 %uint_0
- ;CHECK:        %167 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %166
- ;CHECK:               OpStore %167 %uint_11
- ;CHECK:        %169 = OpIAdd %uint %160 %uint_1
- ;CHECK:        %170 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %169
- ;CHECK:               OpStore %170 %uint_23
- ;CHECK:        %172 = OpIAdd %uint %160 %uint_2
- ;CHECK:        %173 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %172
- ;CHECK:               OpStore %173 %149
- ;CHECK:        %175 = OpIAdd %uint %160 %uint_3
- ;CHECK:        %176 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %175
- ;CHECK:               OpStore %176 %uint_4
- ;CHECK:        %179 = OpLoad %v4float %gl_FragCoord
- ;CHECK:        %181 = OpBitcast %v4uint %179
- ;CHECK:        %182 = OpCompositeExtract %uint %181 0
- ;CHECK:        %183 = OpIAdd %uint %160 %uint_4
- ;CHECK:        %184 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %183
- ;CHECK:               OpStore %184 %182
- ;CHECK:        %185 = OpCompositeExtract %uint %181 1
- ;CHECK:        %187 = OpIAdd %uint %160 %uint_5
- ;CHECK:        %188 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %187
- ;CHECK:               OpStore %188 %185
- ;CHECK:        %189 = OpIAdd %uint %160 %uint_7
- ;CHECK:        %190 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %189
- ;CHECK:               OpStore %190 %150
- ;CHECK:        %192 = OpIAdd %uint %160 %uint_8
- ;CHECK:        %193 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %192
- ;CHECK:               OpStore %193 %151
- ;CHECK:        %195 = OpIAdd %uint %160 %uint_9
- ;CHECK:        %196 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %195
- ;CHECK:               OpStore %196 %152
- ;CHECK:        %198 = OpIAdd %uint %160 %uint_10
- ;CHECK:        %199 = OpAccessChain %_ptr_StorageBuffer_uint %157 %uint_1 %198
- ;CHECK:               OpStore %199 %153
- ;CHECK:               OpBranch %164
- ;CHECK:        %164 = OpLabel
- ;CHECK:               OpReturn
- ;CHECK:               OpFunctionEnd
- )";
+)" + kDirectRead3 + kStreamWrite5Frag;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -7498,6 +4127,7 @@
   //   return ps_output;
   // }
 
+  // clang-format off
   const std::string text = R"(
                OpCapability Shader
 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
@@ -7540,15 +4170,7 @@
                OpDecorate %i_vTextureCoords Location 0
                OpDecorate %_entryPointOutput_vColor Location 0
 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:               OpDecorate %_struct_111 Block
-;CHECK:               OpMemberDecorate %_struct_111 0 Offset 0
-;CHECK:               OpDecorate %113 DescriptorSet 7
-;CHECK:               OpDecorate %113 Binding 1
-;CHECK:               OpDecorate %_struct_139 Block
-;CHECK:               OpMemberDecorate %_struct_139 0 Offset 0
-;CHECK:               OpMemberDecorate %_struct_139 1 Offset 4
-;CHECK:               OpDecorate %141 DescriptorSet 7
-;CHECK:               OpDecorate %141 Binding 0
+)" + kInputDecorations + kOutputDecorations + R"(
 ;CHECK:               OpDecorate %gl_FragCoord BuiltIn FragCoord
        %void = OpTypeVoid
           %3 = OpTypeFunction %void
@@ -7583,39 +4205,20 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-;CHECK:     %uint_0 = OpConstant %uint 0
-;CHECK:    %uint_80 = OpConstant %uint 80
-;CHECK:    %uint_64 = OpConstant %uint 64
-;CHECK:     %uint_7 = OpConstant %uint 7
-;CHECK:     %uint_2 = OpConstant %uint 2
-;CHECK:     %uint_1 = OpConstant %uint 1
 ;CHECK:        %105 = OpTypeFunction %uint %uint %uint %uint
 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK:%_struct_111 = OpTypeStruct %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_111 = OpTypePointer StorageBuffer %_struct_111
-;CHECK:        %113 = OpVariable %_ptr_StorageBuffer__struct_111 StorageBuffer
+)" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
-;CHECK:     %uint_4 = OpConstant %uint 4
 ;CHECK:        %132 = OpTypeFunction %void %uint %uint %uint %uint %uint
-;CHECK:%_struct_139 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_139 = OpTypePointer StorageBuffer %_struct_139
-;CHECK:        %141 = OpVariable %_ptr_StorageBuffer__struct_139 StorageBuffer
-;CHECK:    %uint_11 = OpConstant %uint 11
-;CHECK:    %uint_23 = OpConstant %uint 23
-;CHECK:     %uint_3 = OpConstant %uint 3
+)" + kOutputGlobals + R"(
 ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
 ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ;CHECK:     %v4uint = OpTypeVector %uint 4
-;CHECK:     %uint_5 = OpConstant %uint 5
-;CHECK:     %uint_8 = OpConstant %uint 8
-;CHECK:     %uint_9 = OpConstant %uint 9
-;CHECK:    %uint_10 = OpConstant %uint 10
-;CHECK:    %uint_78 = OpConstant %uint 78
 ;CHECK:        %185 = OpConstantNull %v2float
      %MainPs = OpFunction %void None %3
           %5 = OpLabel
-;CHECK:        %123 = OpFunctionCall %uint %104 %uint_1 %uint_2 %uint_0
+;CHECK:        %123 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_2 %uint_0
 ;CHECK:               OpBranch %93
 ;CHECK:         %93 = OpLabel
 ;CHECK:               OpBranch %92
@@ -7637,7 +4240,7 @@
 ;CHECK:        %130 = OpLoad %v2float %81
 ;CHECK:               OpBranch %127
 ;CHECK:        %129 = OpLabel
-;CHECK:        %184 = OpFunctionCall %void %131 %uint_78 %uint_4 %uint_0 %101 %123
+;CHECK:        %184 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_78 %uint_4 %uint_0 %101 %123
 ;CHECK:               OpBranch %127
 ;CHECK:        %127 = OpLabel
 ;CHECK:        %186 = OpPhi %v2float %130 %128 %185 %129
@@ -7651,75 +4254,8 @@
                OpStore %_entryPointOutput_vColor %91
                OpReturn
                OpFunctionEnd
-;CHECK:        %104 = OpFunction %uint None %105
-;CHECK:        %106 = OpFunctionParameter %uint
-;CHECK:        %107 = OpFunctionParameter %uint
-;CHECK:        %108 = OpFunctionParameter %uint
-;CHECK:        %109 = OpLabel
-;CHECK:        %115 = OpAccessChain %_ptr_StorageBuffer_uint %113 %uint_0 %106
-;CHECK:        %116 = OpLoad %uint %115
-;CHECK:        %117 = OpIAdd %uint %116 %107
-;CHECK:        %118 = OpAccessChain %_ptr_StorageBuffer_uint %113 %uint_0 %117
-;CHECK:        %119 = OpLoad %uint %118
-;CHECK:        %120 = OpIAdd %uint %119 %108
-;CHECK:        %121 = OpAccessChain %_ptr_StorageBuffer_uint %113 %uint_0 %120
-;CHECK:        %122 = OpLoad %uint %121
-;CHECK:               OpReturnValue %122
-;CHECK:               OpFunctionEnd
-;CHECK:        %131 = OpFunction %void None %132
-;CHECK:        %133 = OpFunctionParameter %uint
-;CHECK:        %134 = OpFunctionParameter %uint
-;CHECK:        %135 = OpFunctionParameter %uint
-;CHECK:        %136 = OpFunctionParameter %uint
-;CHECK:        %137 = OpFunctionParameter %uint
-;CHECK:        %138 = OpLabel
-;CHECK:        %142 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_0
-;CHECK:        %144 = OpAtomicIAdd %uint %142 %uint_4 %uint_0 %uint_11
-;CHECK:        %145 = OpIAdd %uint %144 %uint_11
-;CHECK:        %146 = OpArrayLength %uint %141 1
-;CHECK:        %147 = OpULessThanEqual %bool %145 %146
-;CHECK:               OpSelectionMerge %148 None
-;CHECK:               OpBranchConditional %147 %149 %148
-;CHECK:        %149 = OpLabel
-;CHECK:        %150 = OpIAdd %uint %144 %uint_0
-;CHECK:        %151 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %150
-;CHECK:               OpStore %151 %uint_11
-;CHECK:        %153 = OpIAdd %uint %144 %uint_1
-;CHECK:        %154 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %153
-;CHECK:               OpStore %154 %uint_23
-;CHECK:        %155 = OpIAdd %uint %144 %uint_2
-;CHECK:        %156 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %155
-;CHECK:               OpStore %156 %133
-;CHECK:        %158 = OpIAdd %uint %144 %uint_3
-;CHECK:        %159 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %158
-;CHECK:               OpStore %159 %uint_4
-;CHECK:        %162 = OpLoad %v4float %gl_FragCoord
-;CHECK:        %164 = OpBitcast %v4uint %162
-;CHECK:        %165 = OpCompositeExtract %uint %164 0
-;CHECK:        %166 = OpIAdd %uint %144 %uint_4
-;CHECK:        %167 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %166
-;CHECK:               OpStore %167 %165
-;CHECK:        %168 = OpCompositeExtract %uint %164 1
-;CHECK:        %170 = OpIAdd %uint %144 %uint_5
-;CHECK:        %171 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %170
-;CHECK:               OpStore %171 %168
-;CHECK:        %172 = OpIAdd %uint %144 %uint_7
-;CHECK:        %173 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %172
-;CHECK:               OpStore %173 %134
-;CHECK:        %175 = OpIAdd %uint %144 %uint_8
-;CHECK:        %176 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %175
-;CHECK:               OpStore %176 %135
-;CHECK:        %178 = OpIAdd %uint %144 %uint_9
-;CHECK:        %179 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %178
-;CHECK:               OpStore %179 %136
-;CHECK:        %181 = OpIAdd %uint %144 %uint_10
-;CHECK:        %182 = OpAccessChain %_ptr_StorageBuffer_uint %141 %uint_1 %181
-;CHECK:               OpStore %182 %137
-;CHECK:               OpBranch %148
-;CHECK:        %148 = OpLabel
-;CHECK:               OpReturn
-;CHECK:               OpFunctionEnd
- )";
+)" + kDirectRead3 + kStreamWrite5Frag;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -7733,13 +4269,14 @@
   //
   // Same source as UniformArrayRefNoDescInit
 
+  // clang-format off
   const std::string text = R"(
                OpCapability Shader
 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
-;CHECK:               OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %113 %144 %gl_FragCoord
+;CHECK:        OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_FragCoord
                OpExecutionMode %MainPs OriginUpperLeft
                OpSource HLSL 500
                OpName %MainPs "MainPs"
@@ -7776,15 +4313,7 @@
                OpDecorate %i_vTextureCoords Location 0
                OpDecorate %_entryPointOutput_vColor Location 0
 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:               OpDecorate %_struct_111 Block
-;CHECK:               OpMemberDecorate %_struct_111 0 Offset 0
-;CHECK:               OpDecorate %113 DescriptorSet 7
-;CHECK:               OpDecorate %113 Binding 1
-;CHECK:               OpDecorate %_struct_142 Block
-;CHECK:               OpMemberDecorate %_struct_142 0 Offset 0
-;CHECK:               OpMemberDecorate %_struct_142 1 Offset 4
-;CHECK:               OpDecorate %144 DescriptorSet 7
-;CHECK:               OpDecorate %144 Binding 0
+)" + kInputDecorations + kOutputDecorations + R"(
 ;CHECK:               OpDecorate %gl_FragCoord BuiltIn FragCoord
        %void = OpTypeVoid
           %3 = OpTypeFunction %void
@@ -7819,42 +4348,22 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-;CHECK:     %uint_0 = OpConstant %uint 0
-;CHECK:    %uint_80 = OpConstant %uint 80
-;CHECK:    %uint_64 = OpConstant %uint 64
-;CHECK:     %uint_7 = OpConstant %uint 7
-;CHECK:     %uint_2 = OpConstant %uint 2
 ;CHECK:        %104 = OpTypeFunction %uint %uint %uint %uint %uint
 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK:%_struct_111 = OpTypeStruct %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_111 = OpTypePointer StorageBuffer %_struct_111
-;CHECK:        %113 = OpVariable %_ptr_StorageBuffer__struct_111 StorageBuffer
+)" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
-;CHECK:     %uint_4 = OpConstant %uint 4
 ;CHECK:        %135 = OpTypeFunction %void %uint %uint %uint %uint %uint
-;CHECK:%_struct_142 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_142 = OpTypePointer StorageBuffer %_struct_142
-;CHECK:        %144 = OpVariable %_ptr_StorageBuffer__struct_142 StorageBuffer
-;CHECK:    %uint_11 = OpConstant %uint 11
-;CHECK:     %uint_1 = OpConstant %uint 1
-;CHECK:    %uint_23 = OpConstant %uint 23
-;CHECK:     %uint_3 = OpConstant %uint 3
+)" + kOutputGlobals + R"(
 ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
 ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ;CHECK:     %v4uint = OpTypeVector %uint 4
-;CHECK:     %uint_5 = OpConstant %uint 5
-;CHECK:     %uint_8 = OpConstant %uint 8
-;CHECK:     %uint_9 = OpConstant %uint 9
-;CHECK:    %uint_10 = OpConstant %uint 10
-;CHECK:    %uint_78 = OpConstant %uint 78
 ;CHECK:        %189 = OpConstantNull %v2float
-;CHECK:    %uint_83 = OpConstant %uint 83
 ;CHECK:        %201 = OpConstantNull %v4float
      %MainPs = OpFunction %void None %3
           %5 = OpLabel
-;CHECK:        %126 = OpFunctionCall %uint %103 %uint_0 %uint_0 %uint_2 %uint_0
-;CHECK:        %191 = OpFunctionCall %uint %103 %uint_0 %uint_0 %uint_0 %uint_0
+;CHECK:        %126 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_2 %uint_0
+;CHECK:        %191 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %uint_0
 ;CHECK:               OpBranch %93
 ;CHECK:         %93 = OpLabel
 ;CHECK:               OpBranch %92
@@ -7878,7 +4387,7 @@
 ;CHECK:        %133 = OpLoad %v2float %81
 ;CHECK:               OpBranch %130
 ;CHECK:        %132 = OpLabel
-;CHECK:        %188 = OpFunctionCall %void %134 %uint_78 %uint_4 %uint_0 %101 %126
+;CHECK:        %188 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_78 %uint_4 %uint_0 %101 %126
 ;CHECK:               OpBranch %130
 ;CHECK:        %130 = OpLabel
 ;CHECK:        %190 = OpPhi %v2float %133 %131 %189 %132
@@ -7899,86 +4408,15 @@
 ;CHECK:        %198 = OpImageSampleImplicitLod %v4float %197 %86
 ;CHECK:               OpBranch %193
 ;CHECK:        %195 = OpLabel
-;CHECK:        %200 = OpFunctionCall %void %134 %uint_83 %uint_1 %uint_0 %uint_0 %uint_0
+;CHECK:        %200 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_83 %uint_1 %uint_0 %uint_0 %uint_0
 ;CHECK:               OpBranch %193
 ;CHECK:        %193 = OpLabel
 ;CHECK:        %202 = OpPhi %v4float %198 %194 %201 %195
 ;CHECK:               OpStore %_entryPointOutput_vColor %202
                OpReturn
                OpFunctionEnd
-;CHECK:        %103 = OpFunction %uint None %104
-;CHECK:        %105 = OpFunctionParameter %uint
-;CHECK:        %106 = OpFunctionParameter %uint
-;CHECK:        %107 = OpFunctionParameter %uint
-;CHECK:        %108 = OpFunctionParameter %uint
-;CHECK:        %109 = OpLabel
-;CHECK:        %115 = OpAccessChain %_ptr_StorageBuffer_uint %113 %uint_0 %105
-;CHECK:        %116 = OpLoad %uint %115
-;CHECK:        %117 = OpIAdd %uint %116 %106
-;CHECK:        %118 = OpAccessChain %_ptr_StorageBuffer_uint %113 %uint_0 %117
-;CHECK:        %119 = OpLoad %uint %118
-;CHECK:        %120 = OpIAdd %uint %119 %107
-;CHECK:        %121 = OpAccessChain %_ptr_StorageBuffer_uint %113 %uint_0 %120
-;CHECK:        %122 = OpLoad %uint %121
-;CHECK:        %123 = OpIAdd %uint %122 %108
-;CHECK:        %124 = OpAccessChain %_ptr_StorageBuffer_uint %113 %uint_0 %123
-;CHECK:        %125 = OpLoad %uint %124
-;CHECK:               OpReturnValue %125
-;CHECK:               OpFunctionEnd
-;CHECK:        %134 = OpFunction %void None %135
-;CHECK:        %136 = OpFunctionParameter %uint
-;CHECK:        %137 = OpFunctionParameter %uint
-;CHECK:        %138 = OpFunctionParameter %uint
-;CHECK:        %139 = OpFunctionParameter %uint
-;CHECK:        %140 = OpFunctionParameter %uint
-;CHECK:        %141 = OpLabel
-;CHECK:        %145 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_0
-;CHECK:        %147 = OpAtomicIAdd %uint %145 %uint_4 %uint_0 %uint_11
-;CHECK:        %148 = OpIAdd %uint %147 %uint_11
-;CHECK:        %149 = OpArrayLength %uint %144 1
-;CHECK:        %150 = OpULessThanEqual %bool %148 %149
-;CHECK:               OpSelectionMerge %151 None
-;CHECK:               OpBranchConditional %150 %152 %151
-;CHECK:        %152 = OpLabel
-;CHECK:        %153 = OpIAdd %uint %147 %uint_0
-;CHECK:        %155 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %153
-;CHECK:               OpStore %155 %uint_11
-;CHECK:        %157 = OpIAdd %uint %147 %uint_1
-;CHECK:        %158 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %157
-;CHECK:               OpStore %158 %uint_23
-;CHECK:        %159 = OpIAdd %uint %147 %uint_2
-;CHECK:        %160 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %159
-;CHECK:               OpStore %160 %136
-;CHECK:        %162 = OpIAdd %uint %147 %uint_3
-;CHECK:        %163 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %162
-;CHECK:               OpStore %163 %uint_4
-;CHECK:        %166 = OpLoad %v4float %gl_FragCoord
-;CHECK:        %168 = OpBitcast %v4uint %166
-;CHECK:        %169 = OpCompositeExtract %uint %168 0
-;CHECK:        %170 = OpIAdd %uint %147 %uint_4
-;CHECK:        %171 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %170
-;CHECK:               OpStore %171 %169
-;CHECK:        %172 = OpCompositeExtract %uint %168 1
-;CHECK:        %174 = OpIAdd %uint %147 %uint_5
-;CHECK:        %175 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %174
-;CHECK:               OpStore %175 %172
-;CHECK:        %176 = OpIAdd %uint %147 %uint_7
-;CHECK:        %177 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %176
-;CHECK:               OpStore %177 %137
-;CHECK:        %179 = OpIAdd %uint %147 %uint_8
-;CHECK:        %180 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %179
-;CHECK:               OpStore %180 %138
-;CHECK:        %182 = OpIAdd %uint %147 %uint_9
-;CHECK:        %183 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %182
-;CHECK:               OpStore %183 %139
-;CHECK:        %185 = OpIAdd %uint %147 %uint_10
-;CHECK:        %186 = OpAccessChain %_ptr_StorageBuffer_uint %144 %uint_1 %185
-;CHECK:               OpStore %186 %140
-;CHECK:               OpBranch %151
-;CHECK:        %151 = OpLabel
-;CHECK:               OpReturn
-;CHECK:               OpFunctionEnd
- )";
+)" + kDirectRead4 + kStreamWrite5Frag;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -7992,6 +4430,7 @@
   //
   // Use Simple source with min16uint g_nDataIdx
 
+  // clang-format off
   const std::string text = R"(
                OpCapability Shader
                OpCapability Int16
@@ -8000,7 +4439,7 @@
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %_ %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
-;CHECK:               OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %_ %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %60 %gl_FragCoord %119
+;CHECK:        OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %_ %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %inst_bindless_output_buffer %gl_FragCoord %inst_bindless_input_buffer
                OpExecutionMode %MainPs OriginUpperLeft
                OpSource HLSL 500
                OpName %MainPs "MainPs"
@@ -8020,16 +4459,9 @@
                OpDecorate %i_vTextureCoords Location 0
                OpDecorate %_entryPointOutput_vColor Location 0
 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:               OpDecorate %_struct_58 Block
-;CHECK:               OpMemberDecorate %_struct_58 0 Offset 0
-;CHECK:               OpMemberDecorate %_struct_58 1 Offset 4
-;CHECK:               OpDecorate %60 DescriptorSet 7
-;CHECK:               OpDecorate %60 Binding 0
+)" + kOutputDecorations + R"(
 ;CHECK:               OpDecorate %gl_FragCoord BuiltIn FragCoord
-;CHECK:               OpDecorate %_struct_117 Block
-;CHECK:               OpMemberDecorate %_struct_117 0 Offset 0
-;CHECK:               OpDecorate %119 DescriptorSet 7
-;CHECK:               OpDecorate %119 Binding 1
+)" + kInputDecorations + R"(
        %void = OpTypeVoid
          %10 = OpTypeFunction %void
       %float = OpTypeFloat 32
@@ -8057,33 +4489,17 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-;CHECK:     %uint_0 = OpConstant %uint 0
 ;CHECK:       %bool = OpTypeBool
 ;CHECK:         %51 = OpTypeFunction %void %uint %uint %uint %uint
 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK: %_struct_58 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_58 = OpTypePointer StorageBuffer %_struct_58
-;CHECK:         %60 = OpVariable %_ptr_StorageBuffer__struct_58 StorageBuffer
+)" + kOutputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-;CHECK:    %uint_10 = OpConstant %uint 10
-;CHECK:     %uint_4 = OpConstant %uint 4
-;CHECK:     %uint_1 = OpConstant %uint 1
-;CHECK:    %uint_23 = OpConstant %uint 23
-;CHECK:     %uint_2 = OpConstant %uint 2
-;CHECK:     %uint_3 = OpConstant %uint 3
 ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
 ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ;CHECK:     %v4uint = OpTypeVector %uint 4
-;CHECK:     %uint_5 = OpConstant %uint 5
-;CHECK:     %uint_7 = OpConstant %uint 7
-;CHECK:     %uint_8 = OpConstant %uint 8
-;CHECK:     %uint_9 = OpConstant %uint 9
-;CHECK:    %uint_60 = OpConstant %uint 60
 ;CHECK:        %106 = OpConstantNull %v4float
 ;CHECK:        %111 = OpTypeFunction %uint %uint %uint %uint %uint
-;CHECK:%_struct_117 = OpTypeStruct %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_117 = OpTypePointer StorageBuffer %_struct_117
-;CHECK:        %119 = OpVariable %_ptr_StorageBuffer__struct_117 StorageBuffer
+)" + kInputGlobals + R"(
      %MainPs = OpFunction %void None %10
          %30 = OpLabel
 ;CHECK:               OpBranch %108
@@ -8109,7 +4525,7 @@
 ;CHECK:         %47 = OpLoad %16 %34
 ;CHECK:         %48 = OpSampledImage %27 %47 %36
 ;CHECK:        %109 = OpUConvert %uint %33
-;CHECK:        %131 = OpFunctionCall %uint %110 %uint_0 %uint_0 %uint_0 %109
+;CHECK:        %131 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_0 %109
 ;CHECK:        %132 = OpULessThan %bool %uint_0 %131
 ;CHECK:               OpSelectionMerge %133 None
 ;CHECK:               OpBranchConditional %132 %134 %135
@@ -8120,88 +4536,21 @@
 ;CHECK:               OpBranch %133
 ;CHECK:        %135 = OpLabel
 ;CHECK:        %139 = OpUConvert %uint %33
-;CHECK:        %140 = OpFunctionCall %void %50 %uint_60 %uint_1 %139 %uint_0
+;CHECK:        %140 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_60 %uint_1 %139 %uint_0
 ;CHECK:               OpBranch %133
 ;CHECK:        %133 = OpLabel
 ;CHECK:        %141 = OpPhi %v4float %138 %134 %106 %135
 ;CHECK:               OpBranch %44
 ;CHECK:         %46 = OpLabel
-;CHECK:        %105 = OpFunctionCall %void %50 %uint_60 %uint_0 %41 %uint_128
+;CHECK:        %105 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_60 %uint_0 %41 %uint_128
 ;CHECK:               OpBranch %44
 ;CHECK:         %44 = OpLabel
 ;CHECK:        %107 = OpPhi %v4float %141 %133 %106 %46
 ;CHECK:               OpStore %_entryPointOutput_vColor %107
                OpReturn
                OpFunctionEnd
-;CHECK:         %50 = OpFunction %void None %51
-;CHECK:         %52 = OpFunctionParameter %uint
-;CHECK:         %53 = OpFunctionParameter %uint
-;CHECK:         %54 = OpFunctionParameter %uint
-;CHECK:         %55 = OpFunctionParameter %uint
-;CHECK:         %56 = OpLabel
-;CHECK:         %62 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_0
-;CHECK:         %65 = OpAtomicIAdd %uint %62 %uint_4 %uint_0 %uint_10
-;CHECK:         %66 = OpIAdd %uint %65 %uint_10
-;CHECK:         %67 = OpArrayLength %uint %60 1
-;CHECK:         %68 = OpULessThanEqual %bool %66 %67
-;CHECK:               OpSelectionMerge %69 None
-;CHECK:               OpBranchConditional %68 %70 %69
-;CHECK:         %70 = OpLabel
-;CHECK:         %71 = OpIAdd %uint %65 %uint_0
-;CHECK:         %73 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %71
-;CHECK:               OpStore %73 %uint_10
-;CHECK:         %75 = OpIAdd %uint %65 %uint_1
-;CHECK:         %76 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %75
-;CHECK:               OpStore %76 %uint_23
-;CHECK:         %78 = OpIAdd %uint %65 %uint_2
-;CHECK:         %79 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %78
-;CHECK:               OpStore %79 %52
-;CHECK:         %81 = OpIAdd %uint %65 %uint_3
-;CHECK:         %82 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %81
-;CHECK:               OpStore %82 %uint_4
-;CHECK:         %85 = OpLoad %v4float %gl_FragCoord
-;CHECK:         %87 = OpBitcast %v4uint %85
-;CHECK:         %88 = OpCompositeExtract %uint %87 0
-;CHECK:         %89 = OpIAdd %uint %65 %uint_4
-;CHECK:         %90 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %89
-;CHECK:               OpStore %90 %88
-;CHECK:         %91 = OpCompositeExtract %uint %87 1
-;CHECK:         %93 = OpIAdd %uint %65 %uint_5
-;CHECK:         %94 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %93
-;CHECK:               OpStore %94 %91
-;CHECK:         %96 = OpIAdd %uint %65 %uint_7
-;CHECK:         %97 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %96
-;CHECK:               OpStore %97 %53
-;CHECK:         %99 = OpIAdd %uint %65 %uint_8
-;CHECK:        %100 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %99
-;CHECK:               OpStore %100 %54
-;CHECK:        %102 = OpIAdd %uint %65 %uint_9
-;CHECK:        %103 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %102
-;CHECK:               OpStore %103 %55
-;CHECK:               OpBranch %69
-;CHECK:         %69 = OpLabel
-;CHECK:               OpReturn
-;CHECK:               OpFunctionEnd
-;CHECK:        %110 = OpFunction %uint None %111
-;CHECK:        %112 = OpFunctionParameter %uint
-;CHECK:        %113 = OpFunctionParameter %uint
-;CHECK:        %114 = OpFunctionParameter %uint
-;CHECK:        %115 = OpFunctionParameter %uint
-;CHECK:        %116 = OpLabel
-;CHECK:        %120 = OpAccessChain %_ptr_StorageBuffer_uint %119 %uint_0 %112
-;CHECK:        %121 = OpLoad %uint %120
-;CHECK:        %122 = OpIAdd %uint %121 %113
-;CHECK:        %123 = OpAccessChain %_ptr_StorageBuffer_uint %119 %uint_0 %122
-;CHECK:        %124 = OpLoad %uint %123
-;CHECK:        %125 = OpIAdd %uint %124 %114
-;CHECK:        %126 = OpAccessChain %_ptr_StorageBuffer_uint %119 %uint_0 %125
-;CHECK:        %127 = OpLoad %uint %126
-;CHECK:        %128 = OpIAdd %uint %127 %115
-;CHECK:        %129 = OpAccessChain %_ptr_StorageBuffer_uint %119 %uint_0 %128
-;CHECK:        %130 = OpLoad %uint %129
-;CHECK:               OpReturnValue %130
-;CHECK:               OpFunctionEnd
- )";
+)" + kStreamWrite4Frag + kDirectRead4;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -8245,6 +4594,7 @@
   //   return ps_output;
   // }
 
+  // clang-format off
   const std::string text = R"(
                OpCapability Shader
                OpCapability Int16
@@ -8253,7 +4603,7 @@
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
-;CHECK:               OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %69 %97 %gl_FragCoord
+;CHECK:        OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_FragCoord
                OpExecutionMode %MainPs OriginUpperLeft
                OpSource HLSL 500
                OpName %MainPs "MainPs"
@@ -8290,15 +4640,7 @@
                OpDecorate %i_vTextureCoords Location 0
                OpDecorate %_entryPointOutput_vColor Location 0
 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:               OpDecorate %_struct_67 Block
-;CHECK:               OpMemberDecorate %_struct_67 0 Offset 0
-;CHECK:               OpDecorate %69 DescriptorSet 7
-;CHECK:               OpDecorate %69 Binding 1
-;CHECK:               OpDecorate %_struct_95 Block
-;CHECK:               OpMemberDecorate %_struct_95 0 Offset 0
-;CHECK:               OpMemberDecorate %_struct_95 1 Offset 4
-;CHECK:               OpDecorate %97 DescriptorSet 7
-;CHECK:               OpDecorate %97 Binding 0
+)" + kInputDecorations + kOutputDecorations + R"(
 ;CHECK:               OpDecorate %gl_FragCoord BuiltIn FragCoord
        %void = OpTypeVoid
          %14 = OpTypeFunction %void
@@ -8334,39 +4676,20 @@
 %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
-;CHECK:     %uint_0 = OpConstant %uint 0
-;CHECK:    %uint_80 = OpConstant %uint 80
-;CHECK:    %uint_64 = OpConstant %uint 64
-;CHECK:     %uint_7 = OpConstant %uint 7
-;CHECK:     %uint_1 = OpConstant %uint 1
 ;CHECK:         %61 = OpTypeFunction %uint %uint %uint %uint
 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK: %_struct_67 = OpTypeStruct %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_67 = OpTypePointer StorageBuffer %_struct_67
-;CHECK:         %69 = OpVariable %_ptr_StorageBuffer__struct_67 StorageBuffer
+)" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
-;CHECK:     %uint_4 = OpConstant %uint 4
 ;CHECK:         %88 = OpTypeFunction %void %uint %uint %uint %uint %uint
-;CHECK: %_struct_95 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_95 = OpTypePointer StorageBuffer %_struct_95
-;CHECK:         %97 = OpVariable %_ptr_StorageBuffer__struct_95 StorageBuffer
-;CHECK:    %uint_11 = OpConstant %uint 11
-;CHECK:    %uint_23 = OpConstant %uint 23
-;CHECK:     %uint_2 = OpConstant %uint 2
-;CHECK:     %uint_3 = OpConstant %uint 3
+)" + kOutputGlobals + R"(
 ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
 ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ;CHECK:     %v4uint = OpTypeVector %uint 4
-;CHECK:     %uint_5 = OpConstant %uint 5
-;CHECK:     %uint_8 = OpConstant %uint 8
-;CHECK:     %uint_9 = OpConstant %uint 9
-;CHECK:    %uint_10 = OpConstant %uint 10
-;CHECK:    %uint_81 = OpConstant %uint 81
 ;CHECK:        %142 = OpConstantNull %v2float
      %MainPs = OpFunction %void None %14
          %37 = OpLabel
-;CHECK:         %79 = OpFunctionCall %uint %60 %uint_1 %uint_0 %uint_0
+;CHECK:         %79 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
 ;CHECK:               OpBranch %49
 ;CHECK:         %49 = OpLabel
 ;CHECK:               OpBranch %48
@@ -8391,7 +4714,7 @@
 ;CHECK:         %86 = OpLoad %v2float %41
 ;CHECK:               OpBranch %83
 ;CHECK:         %85 = OpLabel
-;CHECK:        %141 = OpFunctionCall %void %87 %uint_81 %uint_4 %uint_0 %58 %79
+;CHECK:        %141 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_81 %uint_4 %uint_0 %58 %79
 ;CHECK:               OpBranch %83
 ;CHECK:         %83 = OpLabel
 ;CHECK:        %143 = OpPhi %v2float %86 %84 %142 %85
@@ -8403,75 +4726,8 @@
                OpStore %_entryPointOutput_vColor %47
                OpReturn
                OpFunctionEnd
-;CHECK:         %60 = OpFunction %uint None %61
-;CHECK:         %62 = OpFunctionParameter %uint
-;CHECK:         %63 = OpFunctionParameter %uint
-;CHECK:         %64 = OpFunctionParameter %uint
-;CHECK:         %65 = OpLabel
-;CHECK:         %71 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_0 %62
-;CHECK:         %72 = OpLoad %uint %71
-;CHECK:         %73 = OpIAdd %uint %72 %63
-;CHECK:         %74 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_0 %73
-;CHECK:         %75 = OpLoad %uint %74
-;CHECK:         %76 = OpIAdd %uint %75 %64
-;CHECK:         %77 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_0 %76
-;CHECK:         %78 = OpLoad %uint %77
-;CHECK:               OpReturnValue %78
-;CHECK:               OpFunctionEnd
-;CHECK:         %87 = OpFunction %void None %88
-;CHECK:         %89 = OpFunctionParameter %uint
-;CHECK:         %90 = OpFunctionParameter %uint
-;CHECK:         %91 = OpFunctionParameter %uint
-;CHECK:         %92 = OpFunctionParameter %uint
-;CHECK:         %93 = OpFunctionParameter %uint
-;CHECK:         %94 = OpLabel
-;CHECK:         %98 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_0
-;CHECK:        %100 = OpAtomicIAdd %uint %98 %uint_4 %uint_0 %uint_11
-;CHECK:        %101 = OpIAdd %uint %100 %uint_11
-;CHECK:        %102 = OpArrayLength %uint %97 1
-;CHECK:        %103 = OpULessThanEqual %bool %101 %102
-;CHECK:               OpSelectionMerge %104 None
-;CHECK:               OpBranchConditional %103 %105 %104
-;CHECK:        %105 = OpLabel
-;CHECK:        %106 = OpIAdd %uint %100 %uint_0
-;CHECK:        %107 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %106
-;CHECK:               OpStore %107 %uint_11
-;CHECK:        %109 = OpIAdd %uint %100 %uint_1
-;CHECK:        %110 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %109
-;CHECK:               OpStore %110 %uint_23
-;CHECK:        %112 = OpIAdd %uint %100 %uint_2
-;CHECK:        %113 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %112
-;CHECK:               OpStore %113 %89
-;CHECK:        %115 = OpIAdd %uint %100 %uint_3
-;CHECK:        %116 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %115
-;CHECK:               OpStore %116 %uint_4
-;CHECK:        %119 = OpLoad %v4float %gl_FragCoord
-;CHECK:        %121 = OpBitcast %v4uint %119
-;CHECK:        %122 = OpCompositeExtract %uint %121 0
-;CHECK:        %123 = OpIAdd %uint %100 %uint_4
-;CHECK:        %124 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %123
-;CHECK:               OpStore %124 %122
-;CHECK:        %125 = OpCompositeExtract %uint %121 1
-;CHECK:        %127 = OpIAdd %uint %100 %uint_5
-;CHECK:        %128 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %127
-;CHECK:               OpStore %128 %125
-;CHECK:        %129 = OpIAdd %uint %100 %uint_7
-;CHECK:        %130 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %129
-;CHECK:               OpStore %130 %90
-;CHECK:        %132 = OpIAdd %uint %100 %uint_8
-;CHECK:        %133 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %132
-;CHECK:               OpStore %133 %91
-;CHECK:        %135 = OpIAdd %uint %100 %uint_9
-;CHECK:        %136 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %135
-;CHECK:               OpStore %136 %92
-;CHECK:        %138 = OpIAdd %uint %100 %uint_10
-;CHECK:        %139 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %138
-;CHECK:               OpStore %139 %93
-;CHECK:               OpBranch %104
-;CHECK:        %104 = OpLabel
-;CHECK:               OpReturn
-;CHECK:               OpFunctionEnd
- )";
+               )" + kDirectRead3 + kStreamWrite5Frag;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -8498,13 +4754,14 @@
   //    v_vtxResult = var[2][1];
   // }
 
-  const std::string text = R"(
+  // clang-format off
+  std::string text = R"(
                OpCapability Shader
 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position
-;CHECK:               OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %45 %72 %gl_VertexIndex %gl_InstanceIndex
+;CHECK:        OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_VertexIndex %gl_InstanceIndex
                OpSource GLSL 450
                OpSourceExtension "GL_EXT_scalar_block_layout"
                OpName %main "main"
@@ -8527,16 +4784,9 @@
 ;CHECK:               OpDecorate %116 RelaxedPrecision
                OpDecorate %a_position Location 0
 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:               OpDecorate %_struct_43 Block
-;CHECK:               OpMemberDecorate %_struct_43 0 Offset 0
-;CHECK:               OpDecorate %45 DescriptorSet 7
-;CHECK:               OpDecorate %45 Binding 1
+)" + kInputDecorations + R"(
 ;CHECK:               OpDecorate %61 RelaxedPrecision
-;CHECK:               OpDecorate %_struct_70 Block
-;CHECK:               OpMemberDecorate %_struct_70 0 Offset 0
-;CHECK:               OpMemberDecorate %_struct_70 1 Offset 4
-;CHECK:               OpDecorate %72 DescriptorSet 7
-;CHECK:               OpDecorate %72 Binding 0
+)" + kOutputDecorations + R"(
 ;CHECK:               OpDecorate %gl_VertexIndex BuiltIn VertexIndex
 ;CHECK:               OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex
        %void = OpTypeVoid
@@ -8558,24 +4808,13 @@
     %v4float = OpTypeVector %float 4
 %_ptr_Input_v4float = OpTypePointer Input %v4float
  %a_position = OpVariable %_ptr_Input_v4float Input
-;CHECK;     %uint_0 = OpConstant %uint 0
-;CHECK;     %uint_16 = OpConstant %uint 16
-;CHECK;     %uint_4 = OpConstant %uint 4
-;CHECK;     %uint_3 = OpConstant %uint 3
 ;CHECK;         %37 = OpTypeFunction %uint %uint %uint %uint
 ;CHECK;%_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK; %_struct_43 = OpTypeStruct %_runtimearr_uint
-;CHECK;%_ptr_StorageBuffer__struct_43 = OpTypePointer StorageBuffer %_struct_43
-;CHECK;         %45 = OpVariable %_ptr_StorageBuffer__struct_43 StorageBuffer
+)" + kInputGlobals + R"(
 ;CHECK;%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK;       %bool = OpTypeBool
 ;CHECK;         %63 = OpTypeFunction %void %uint %uint %uint %uint %uint
-;CHECK; %_struct_70 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK;%_ptr_StorageBuffer__struct_70 = OpTypePointer StorageBuffer %_struct_70
-;CHECK;         %72 = OpVariable %_ptr_StorageBuffer__struct_70 StorageBuffer
-;CHECK;    %uint_11 = OpConstant %uint 11
-;CHECK;    %uint_23 = OpConstant %uint 23
-;CHECK;     %uint_2 = OpConstant %uint 2
+)" + kOutputGlobals + R"(
 ;CHECK;%_ptr_Input_uint = OpTypePointer Input %uint
 ;CHECK;%gl_VertexIndex = OpVariable %_ptr_Input_uint Input
 ;CHECK;%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
@@ -8588,7 +4827,7 @@
 ;CHECK;        %115 = OpConstantNull %float
        %main = OpFunction %void None %3
           %5 = OpLabel
-;CHECK:         %55 = OpFunctionCall %uint %36 %uint_1 %uint_0 %uint_0
+;CHECK:         %55 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
 ;CHECK:               OpBranch %26
 ;CHECK:         %26 = OpLabel
 ;CHECK:               OpBranch %25
@@ -8608,7 +4847,7 @@
 ;CHECK:         %61 = OpLoad %float %20
 ;CHECK:               OpBranch %58
 ;CHECK:         %60 = OpLabel
-;CHECK:        %114 = OpFunctionCall %void %62 %uint_45 %uint_4 %uint_0 %35 %55
+;CHECK:        %114 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_45 %uint_4 %uint_0 %35 %55
 ;CHECK:               OpBranch %58
 ;CHECK:         %58 = OpLabel
 ;CHECK:        %116 = OpPhi %float %61 %59 %115 %60
@@ -8617,73 +4856,8 @@
 ;CHECK:               OpStore %v_vtxResult %116
                OpReturn
                OpFunctionEnd
-;CHECK:         %36 = OpFunction %uint None %37
-;CHECK:         %38 = OpFunctionParameter %uint
-;CHECK:         %39 = OpFunctionParameter %uint
-;CHECK:         %40 = OpFunctionParameter %uint
-;CHECK:         %41 = OpLabel
-;CHECK:         %47 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0 %38
-;CHECK:         %48 = OpLoad %uint %47
-;CHECK:         %49 = OpIAdd %uint %48 %39
-;CHECK:         %50 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0 %49
-;CHECK:         %51 = OpLoad %uint %50
-;CHECK:         %52 = OpIAdd %uint %51 %40
-;CHECK:         %53 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0 %52
-;CHECK:         %54 = OpLoad %uint %53
-;CHECK:               OpReturnValue %54
-;CHECK:               OpFunctionEnd
-;CHECK:         %62 = OpFunction %void None %63
-;CHECK:         %64 = OpFunctionParameter %uint
-;CHECK:         %65 = OpFunctionParameter %uint
-;CHECK:         %66 = OpFunctionParameter %uint
-;CHECK:         %67 = OpFunctionParameter %uint
-;CHECK:         %68 = OpFunctionParameter %uint
-;CHECK:         %69 = OpLabel
-;CHECK:         %73 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_0
-;CHECK:         %75 = OpAtomicIAdd %uint %73 %uint_4 %uint_0 %uint_11
-;CHECK:         %76 = OpIAdd %uint %75 %uint_11
-;CHECK:         %77 = OpArrayLength %uint %72 1
-;CHECK:         %78 = OpULessThanEqual %bool %76 %77
-;CHECK:               OpSelectionMerge %79 None
-;CHECK:               OpBranchConditional %78 %80 %79
-;CHECK:         %80 = OpLabel
-;CHECK:         %81 = OpIAdd %uint %75 %uint_0
-;CHECK:         %82 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %81
-;CHECK:               OpStore %82 %uint_11
-;CHECK:         %84 = OpIAdd %uint %75 %uint_1
-;CHECK:         %85 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %84
-;CHECK:               OpStore %85 %uint_23
-;CHECK:         %87 = OpIAdd %uint %75 %uint_2
-;CHECK:         %88 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %87
-;CHECK:               OpStore %88 %64
-;CHECK:         %89 = OpIAdd %uint %75 %uint_3
-;CHECK:         %90 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %89
-;CHECK:               OpStore %90 %uint_0
-;CHECK:         %93 = OpLoad %uint %gl_VertexIndex
-;CHECK:         %94 = OpIAdd %uint %75 %uint_4
-;CHECK:         %95 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %94
-;CHECK:               OpStore %95 %93
-;CHECK:         %97 = OpLoad %uint %gl_InstanceIndex
-;CHECK:         %99 = OpIAdd %uint %75 %uint_5
-;CHECK:        %100 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %99
-;CHECK:               OpStore %100 %97
-;CHECK:        %102 = OpIAdd %uint %75 %uint_7
-;CHECK:        %103 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %102
-;CHECK:               OpStore %103 %65
-;CHECK:        %105 = OpIAdd %uint %75 %uint_8
-;CHECK:        %106 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %105
-;CHECK:               OpStore %106 %66
-;CHECK:        %108 = OpIAdd %uint %75 %uint_9
-;CHECK:        %109 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %108
-;CHECK:               OpStore %109 %67
-;CHECK:        %111 = OpIAdd %uint %75 %uint_10
-;CHECK:        %112 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %111
-;CHECK:               OpStore %112 %68
-;CHECK:               OpBranch %79
-;CHECK:         %79 = OpLabel
-;CHECK:               OpReturn
-;CHECK:               OpFunctionEnd
- )";
+               )" + kDirectRead3 + kStreamWrite5Vert;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -8710,13 +4884,14 @@
   //    v_vtxResult = var[2][1];
   // }
 
+  // clang-format off
   const std::string text = R"(
                OpCapability Shader
 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position
-;CHECK:               OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %45 %72 %gl_VertexIndex %gl_InstanceIndex
+;CHECK:        OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_VertexIndex %gl_InstanceIndex
                OpSource GLSL 450
                OpSourceExtension "GL_EXT_scalar_block_layout"
                OpName %main "main"
@@ -8739,16 +4914,9 @@
 ;CHECK:               OpDecorate %115 RelaxedPrecision
                OpDecorate %a_position Location 0
 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:               OpDecorate %_struct_43 Block
-;CHECK:               OpMemberDecorate %_struct_43 0 Offset 0
-;CHECK:               OpDecorate %45 DescriptorSet 7
-;CHECK:               OpDecorate %45 Binding 1
+)" + kInputDecorations + R"(
 ;CHECK:               OpDecorate %61 RelaxedPrecision
-;CHECK:               OpDecorate %_struct_70 Block
-;CHECK:               OpMemberDecorate %_struct_70 0 Offset 0
-;CHECK:               OpMemberDecorate %_struct_70 1 Offset 4
-;CHECK:               OpDecorate %72 DescriptorSet 7
-;CHECK:               OpDecorate %72 Binding 0
+)" + kOutputDecorations + R"(
 ;CHECK:               OpDecorate %gl_VertexIndex BuiltIn VertexIndex
 ;CHECK:               OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex
        %void = OpTypeVoid
@@ -8770,36 +4938,20 @@
     %v4float = OpTypeVector %float 4
 %_ptr_Input_v4float = OpTypePointer Input %v4float
  %a_position = OpVariable %_ptr_Input_v4float Input
-;CHECK:     %uint_0 = OpConstant %uint 0
-;CHECK:     %uint_8 = OpConstant %uint 8
-;CHECK:     %uint_4 = OpConstant %uint 4
-;CHECK:     %uint_3 = OpConstant %uint 3
 ;CHECK:         %37 = OpTypeFunction %uint %uint %uint %uint
 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK: %_struct_43 = OpTypeStruct %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_43 = OpTypePointer StorageBuffer %_struct_43
-;CHECK:         %45 = OpVariable %_ptr_StorageBuffer__struct_43 StorageBuffer
+)" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
 ;CHECK:         %63 = OpTypeFunction %void %uint %uint %uint %uint %uint
-;CHECK: %_struct_70 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_70 = OpTypePointer StorageBuffer %_struct_70
-;CHECK:         %72 = OpVariable %_ptr_StorageBuffer__struct_70 StorageBuffer
-;CHECK:    %uint_11 = OpConstant %uint 11
-;CHECK:    %uint_23 = OpConstant %uint 23
-;CHECK:     %uint_2 = OpConstant %uint 2
+)" + kOutputGlobals + R"(
 ;CHECK:%_ptr_Input_uint = OpTypePointer Input %uint
 ;CHECK:%gl_VertexIndex = OpVariable %_ptr_Input_uint Input
 ;CHECK:%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
-;CHECK:     %uint_5 = OpConstant %uint 5
-;CHECK:     %uint_7 = OpConstant %uint 7
-;CHECK:     %uint_9 = OpConstant %uint 9
-;CHECK:    %uint_10 = OpConstant %uint 10
-;CHECK:    %uint_45 = OpConstant %uint 45
 ;CHECK:        %114 = OpConstantNull %float
 %main = OpFunction %void None %3
           %5 = OpLabel
-;CHECK:         %55 = OpFunctionCall %uint %36 %uint_1 %uint_0 %uint_0
+;CHECK:         %55 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
 ;CHECK:               OpBranch %26
 ;CHECK:         %26 = OpLabel
 ;CHECK:               OpBranch %25
@@ -8819,7 +4971,7 @@
 ;CHECK:         %61 = OpLoad %float %20
 ;CHECK:               OpBranch %58
 ;CHECK:         %60 = OpLabel
-;CHECK:        %113 = OpFunctionCall %void %62 %uint_45 %uint_4 %uint_0 %35 %55
+;CHECK:        %113 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_45 %uint_4 %uint_0 %35 %55
 ;CHECK:               OpBranch %58
 ;CHECK:         %58 = OpLabel
 ;CHECK:        %115 = OpPhi %float %61 %59 %114 %60
@@ -8828,73 +4980,8 @@
 ;CHECK:               OpStore %v_vtxResult %115
                OpReturn
                OpFunctionEnd
-;CHECK:         %36 = OpFunction %uint None %37
-;CHECK:         %38 = OpFunctionParameter %uint
-;CHECK:         %39 = OpFunctionParameter %uint
-;CHECK:         %40 = OpFunctionParameter %uint
-;CHECK:         %41 = OpLabel
-;CHECK:         %47 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0 %38
-;CHECK:         %48 = OpLoad %uint %47
-;CHECK:         %49 = OpIAdd %uint %48 %39
-;CHECK:         %50 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0 %49
-;CHECK:         %51 = OpLoad %uint %50
-;CHECK:         %52 = OpIAdd %uint %51 %40
-;CHECK:         %53 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0 %52
-;CHECK:         %54 = OpLoad %uint %53
-;CHECK:               OpReturnValue %54
-;CHECK:               OpFunctionEnd
-;CHECK:         %62 = OpFunction %void None %63
-;CHECK:         %64 = OpFunctionParameter %uint
-;CHECK:         %65 = OpFunctionParameter %uint
-;CHECK:         %66 = OpFunctionParameter %uint
-;CHECK:         %67 = OpFunctionParameter %uint
-;CHECK:         %68 = OpFunctionParameter %uint
-;CHECK:         %69 = OpLabel
-;CHECK:         %73 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_0
-;CHECK:         %75 = OpAtomicIAdd %uint %73 %uint_4 %uint_0 %uint_11
-;CHECK:         %76 = OpIAdd %uint %75 %uint_11
-;CHECK:         %77 = OpArrayLength %uint %72 1
-;CHECK:         %78 = OpULessThanEqual %bool %76 %77
-;CHECK:               OpSelectionMerge %79 None
-;CHECK:               OpBranchConditional %78 %80 %79
-;CHECK:         %80 = OpLabel
-;CHECK:         %81 = OpIAdd %uint %75 %uint_0
-;CHECK:         %82 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %81
-;CHECK:               OpStore %82 %uint_11
-;CHECK:         %84 = OpIAdd %uint %75 %uint_1
-;CHECK:         %85 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %84
-;CHECK:               OpStore %85 %uint_23
-;CHECK:         %87 = OpIAdd %uint %75 %uint_2
-;CHECK:         %88 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %87
-;CHECK:               OpStore %88 %64
-;CHECK:         %89 = OpIAdd %uint %75 %uint_3
-;CHECK:         %90 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %89
-;CHECK:               OpStore %90 %uint_0
-;CHECK:         %93 = OpLoad %uint %gl_VertexIndex
-;CHECK:         %94 = OpIAdd %uint %75 %uint_4
-;CHECK:         %95 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %94
-;CHECK:               OpStore %95 %93
-;CHECK:         %97 = OpLoad %uint %gl_InstanceIndex
-;CHECK:         %99 = OpIAdd %uint %75 %uint_5
-;CHECK:        %100 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %99
-;CHECK:               OpStore %100 %97
-;CHECK:        %102 = OpIAdd %uint %75 %uint_7
-;CHECK:        %103 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %102
-;CHECK:               OpStore %103 %65
-;CHECK:        %104 = OpIAdd %uint %75 %uint_8
-;CHECK:        %105 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %104
-;CHECK:               OpStore %105 %66
-;CHECK:        %107 = OpIAdd %uint %75 %uint_9
-;CHECK:        %108 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %107
-;CHECK:               OpStore %108 %67
-;CHECK:        %110 = OpIAdd %uint %75 %uint_10
-;CHECK:        %111 = OpAccessChain %_ptr_StorageBuffer_uint %72 %uint_1 %110
-;CHECK:               OpStore %111 %68
-;CHECK:               OpBranch %79
-;CHECK:         %79 = OpLabel
-;CHECK:               OpReturn
-;CHECK:               OpFunctionEnd
- )";
+               )" + kDirectRead3 + kStreamWrite5Vert;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   ValidatorOptions()->uniform_buffer_standard_layout = true;
@@ -8922,13 +5009,14 @@
   //    v_vtxResult = var[2][3][1];
   // }
 
+  // clang-format off
   const std::string text = R"(
                OpCapability Shader
 ;CHECK:               OpExtension "SPV_KHR_storage_buffer_storage_class"
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position
-;CHECK:               OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %54 %81 %gl_VertexIndex %gl_InstanceIndex
+;CHECK:        OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_VertexIndex %gl_InstanceIndex
                OpSource GLSL 450
                OpSourceExtension "GL_EXT_scalar_block_layout"
                OpName %main "main"
@@ -8952,16 +5040,9 @@
 ;CHECK:               OpDecorate %125 RelaxedPrecision
                OpDecorate %a_position Location 0
 ;CHECK:               OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:               OpDecorate %_struct_52 Block
-;CHECK:               OpMemberDecorate %_struct_52 0 Offset 0
-;CHECK:               OpDecorate %54 DescriptorSet 7
-;CHECK:               OpDecorate %54 Binding 1
+)" + kInputDecorations + R"(
 ;CHECK:               OpDecorate %70 RelaxedPrecision
-;CHECK:               OpDecorate %_struct_79 Block
-;CHECK:               OpMemberDecorate %_struct_79 0 Offset 0
-;CHECK:               OpMemberDecorate %_struct_79 1 Offset 4
-;CHECK:               OpDecorate %81 DescriptorSet 7
-;CHECK:               OpDecorate %81 Binding 0
+)" + kOutputDecorations + R"(
 ;CHECK:               OpDecorate %gl_VertexIndex BuiltIn VertexIndex
 ;CHECK:               OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex
        %void = OpTypeVoid
@@ -8988,39 +5069,20 @@
     %v4float = OpTypeVector %float 4
 %_ptr_Input_v4float = OpTypePointer Input %v4float
  %a_position = OpVariable %_ptr_Input_v4float Input
-;CHECK:     %uint_0 = OpConstant %uint 0
-;CHECK:   %uint_128 = OpConstant %uint 128
-;CHECK:    %uint_32 = OpConstant %uint 32
-;CHECK:    %uint_16 = OpConstant %uint 16
-;CHECK:    %uint_19 = OpConstant %uint 19
-;CHECK:     %uint_1 = OpConstant %uint 1
 ;CHECK:         %46 = OpTypeFunction %uint %uint %uint %uint
 ;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK: %_struct_52 = OpTypeStruct %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_52 = OpTypePointer StorageBuffer %_struct_52
-;CHECK:         %54 = OpVariable %_ptr_StorageBuffer__struct_52 StorageBuffer
+)" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
 ;CHECK:         %72 = OpTypeFunction %void %uint %uint %uint %uint %uint
-;CHECK: %_struct_79 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:%_ptr_StorageBuffer__struct_79 = OpTypePointer StorageBuffer %_struct_79
-;CHECK:         %81 = OpVariable %_ptr_StorageBuffer__struct_79 StorageBuffer
-;CHECK:    %uint_11 = OpConstant %uint 11
-;CHECK:    %uint_23 = OpConstant %uint 23
-;CHECK:     %uint_2 = OpConstant %uint 2
+)" + kOutputGlobals + R"(
 ;CHECK:%_ptr_Input_uint = OpTypePointer Input %uint
 ;CHECK:%gl_VertexIndex = OpVariable %_ptr_Input_uint Input
 ;CHECK:%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
-;CHECK:     %uint_5 = OpConstant %uint 5
-;CHECK:     %uint_7 = OpConstant %uint 7
-;CHECK:     %uint_8 = OpConstant %uint 8
-;CHECK:     %uint_9 = OpConstant %uint 9
-;CHECK:    %uint_10 = OpConstant %uint 10
-;CHECK:    %uint_51 = OpConstant %uint 51
 ;CHECK:        %124 = OpConstantNull %v2float
        %main = OpFunction %void None %3
           %5 = OpLabel
-;CHECK:         %64 = OpFunctionCall %uint %45 %uint_1 %uint_0 %uint_0
+;CHECK:         %64 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
 ;CHECK:               OpBranch %31
 ;CHECK:         %31 = OpLabel
 ;CHECK:               OpBranch %30
@@ -9044,80 +5106,15 @@
 ;CHECK:         %70 = OpLoad %v2float %25
 ;CHECK:               OpBranch %67
 ;CHECK:         %69 = OpLabel
-;CHECK:        %123 = OpFunctionCall %void %71 %uint_51 %uint_4 %uint_0 %43 %64
+;CHECK:        %123 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_51 %uint_4 %uint_0 %43 %64
 ;CHECK:               OpBranch %67
 ;CHECK:         %67 = OpLabel
 ;CHECK:        %125 = OpPhi %v2float %70 %68 %124 %69
 ;CHECK:               OpStore %v_vtxResult %125
                OpReturn
                OpFunctionEnd
-;CHECK:         %45 = OpFunction %uint None %46
-;CHECK:         %47 = OpFunctionParameter %uint
-;CHECK:         %48 = OpFunctionParameter %uint
-;CHECK:         %49 = OpFunctionParameter %uint
-;CHECK:         %50 = OpLabel
-;CHECK:         %56 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_0 %47
-;CHECK:         %57 = OpLoad %uint %56
-;CHECK:         %58 = OpIAdd %uint %57 %48
-;CHECK:         %59 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_0 %58
-;CHECK:         %60 = OpLoad %uint %59
-;CHECK:         %61 = OpIAdd %uint %60 %49
-;CHECK:         %62 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_0 %61
-;CHECK:         %63 = OpLoad %uint %62
-;CHECK:               OpReturnValue %63
-;CHECK:               OpFunctionEnd
-;CHECK:         %71 = OpFunction %void None %72
-;CHECK:         %73 = OpFunctionParameter %uint
-;CHECK:         %74 = OpFunctionParameter %uint
-;CHECK:         %75 = OpFunctionParameter %uint
-;CHECK:         %76 = OpFunctionParameter %uint
-;CHECK:         %77 = OpFunctionParameter %uint
-;CHECK:         %78 = OpLabel
-;CHECK:         %82 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_0
-;CHECK:         %84 = OpAtomicIAdd %uint %82 %uint_4 %uint_0 %uint_11
-;CHECK:         %85 = OpIAdd %uint %84 %uint_11
-;CHECK:         %86 = OpArrayLength %uint %81 1
-;CHECK:         %87 = OpULessThanEqual %bool %85 %86
-;CHECK:               OpSelectionMerge %88 None
-;CHECK:               OpBranchConditional %87 %89 %88
-;CHECK:         %89 = OpLabel
-;CHECK:         %90 = OpIAdd %uint %84 %uint_0
-;CHECK:         %91 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %90
-;CHECK:               OpStore %91 %uint_11
-;CHECK:         %93 = OpIAdd %uint %84 %uint_1
-;CHECK:         %94 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %93
-;CHECK:               OpStore %94 %uint_23
-;CHECK:         %96 = OpIAdd %uint %84 %uint_2
-;CHECK:         %97 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %96
-;CHECK:               OpStore %97 %73
-;CHECK:         %98 = OpIAdd %uint %84 %uint_3
-;CHECK:         %99 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %98
-;CHECK:               OpStore %99 %uint_0
-;CHECK:        %102 = OpLoad %uint %gl_VertexIndex
-;CHECK:        %103 = OpIAdd %uint %84 %uint_4
-;CHECK:        %104 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %103
-;CHECK:               OpStore %104 %102
-;CHECK:        %106 = OpLoad %uint %gl_InstanceIndex
-;CHECK:        %108 = OpIAdd %uint %84 %uint_5
-;CHECK:        %109 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %108
-;CHECK:               OpStore %109 %106
-;CHECK:        %111 = OpIAdd %uint %84 %uint_7
-;CHECK:        %112 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %111
-;CHECK:               OpStore %112 %74
-;CHECK:        %114 = OpIAdd %uint %84 %uint_8
-;CHECK:        %115 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %114
-;CHECK:               OpStore %115 %75
-;CHECK:        %117 = OpIAdd %uint %84 %uint_9
-;CHECK:        %118 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %117
-;CHECK:               OpStore %118 %76
-;CHECK:        %120 = OpIAdd %uint %84 %uint_10
-;CHECK:        %121 = OpAccessChain %_ptr_StorageBuffer_uint %81 %uint_1 %120
-;CHECK:               OpStore %121 %77
-;CHECK:               OpBranch %88
-;CHECK:         %88 = OpLabel
-;CHECK:               OpReturn
-;CHECK:               OpFunctionEnd
- )";
+               )" + kDirectRead3 + kStreamWrite5Vert;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -9137,6 +5134,7 @@
   //    x = imageLoad(s, ii);
   // }
 
+  // clang-format off
   const std::string text = R"(
                           OpCapability Shader
                           OpCapability ImageBuffer
@@ -9158,11 +5156,7 @@
                           OpDecorate %ii Flat
                           OpDecorate %ii Location 13
 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:                   OpDecorate %_struct_43 Block
-;CHECK:                   OpMemberDecorate %_struct_43 0 Offset 0
-;CHECK:                   OpMemberDecorate %_struct_43 1 Offset 4
-;CHECK:                   OpDecorate %45 DescriptorSet 7
-;CHECK:                   OpDecorate %45 Binding 0
+)" + kOutputDecorations + R"(
 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
                   %void = OpTypeVoid
                      %3 = OpTypeFunction %void
@@ -9177,29 +5171,14 @@
            %_ptr_Input_int = OpTypePointer Input %int
                     %ii = OpVariable %_ptr_Input_int Input
 ;CHECK:           %uint = OpTypeInt 32 0
-;CHECK:         %uint_0 = OpConstant %uint 0
 ;CHECK:           %bool = OpTypeBool
-;CHECK:         %uint_7 = OpConstant %uint 7
 ;CHECK:             %35 = OpTypeFunction %void %uint %uint %uint %uint %uint
 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK:     %_struct_43 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:    %_ptr_StorageBuffer__struct_43 = OpTypePointer StorageBuffer %_struct_43
-;CHECK:             %45 = OpVariable %_ptr_StorageBuffer__struct_43 StorageBuffer
+)" + kOutputGlobals + R"(
 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-;CHECK:        %uint_11 = OpConstant %uint 11
-;CHECK:         %uint_4 = OpConstant %uint 4
-;CHECK:         %uint_1 = OpConstant %uint 1
-;CHECK:        %uint_23 = OpConstant %uint 23
-;CHECK:         %uint_2 = OpConstant %uint 2
-;CHECK:         %uint_3 = OpConstant %uint 3
 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ;CHECK:         %v4uint = OpTypeVector %uint 4
-;CHECK:         %uint_5 = OpConstant %uint 5
-;CHECK:         %uint_8 = OpConstant %uint 8
-;CHECK:         %uint_9 = OpConstant %uint 9
-;CHECK:        %uint_10 = OpConstant %uint 10
-;CHECK:        %uint_33 = OpConstant %uint 33
 ;CHECK:             %93 = OpConstantNull %v4float
                   %main = OpFunction %void None %3
                      %5 = OpLabel
@@ -9225,67 +5204,15 @@
 ;CHECK:             %33 = OpImageRead %v4float %32 %17
 ;CHECK:                   OpBranch %29
 ;CHECK:             %31 = OpLabel
-;CHECK:             %92 = OpFunctionCall %void %34 %uint_33 %uint_7 %uint_0 %23 %25
+;CHECK:             %92 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_33 %uint_7 %uint_0 %23 %25
 ;CHECK:                   OpBranch %29
 ;CHECK:             %29 = OpLabel
 ;CHECK:             %94 = OpPhi %v4float %33 %30 %93 %31
 ;CHECK:                   OpStore %x %94
                           OpReturn
                           OpFunctionEnd
-;CHECK:             %34 = OpFunction %void None %35
-;CHECK:             %36 = OpFunctionParameter %uint
-;CHECK:             %37 = OpFunctionParameter %uint
-;CHECK:             %38 = OpFunctionParameter %uint
-;CHECK:             %39 = OpFunctionParameter %uint
-;CHECK:             %40 = OpFunctionParameter %uint
-;CHECK:             %41 = OpLabel
-;CHECK:             %47 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0
-;CHECK:             %50 = OpAtomicIAdd %uint %47 %uint_4 %uint_0 %uint_11
-;CHECK:             %51 = OpIAdd %uint %50 %uint_11
-;CHECK:             %52 = OpArrayLength %uint %45 1
-;CHECK:             %53 = OpULessThanEqual %bool %51 %52
-;CHECK:                   OpSelectionMerge %54 None
-;CHECK:                   OpBranchConditional %53 %55 %54
-;CHECK:             %55 = OpLabel
-;CHECK:             %56 = OpIAdd %uint %50 %uint_0
-;CHECK:             %58 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %56
-;CHECK:                   OpStore %58 %uint_11
-;CHECK:             %60 = OpIAdd %uint %50 %uint_1
-;CHECK:             %61 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %60
-;CHECK:                   OpStore %61 %uint_23
-;CHECK:             %63 = OpIAdd %uint %50 %uint_2
-;CHECK:             %64 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %63
-;CHECK:                   OpStore %64 %36
-;CHECK:             %66 = OpIAdd %uint %50 %uint_3
-;CHECK:             %67 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %66
-;CHECK:                   OpStore %67 %uint_4
-;CHECK:             %70 = OpLoad %v4float %gl_FragCoord
-;CHECK:             %72 = OpBitcast %v4uint %70
-;CHECK:             %73 = OpCompositeExtract %uint %72 0
-;CHECK:             %74 = OpIAdd %uint %50 %uint_4
-;CHECK:             %75 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %74
-;CHECK:                   OpStore %75 %73
-;CHECK:             %76 = OpCompositeExtract %uint %72 1
-;CHECK:             %78 = OpIAdd %uint %50 %uint_5
-;CHECK:             %79 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %78
-;CHECK:                   OpStore %79 %76
-;CHECK:             %80 = OpIAdd %uint %50 %uint_7
-;CHECK:             %81 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %80
-;CHECK:                   OpStore %81 %37
-;CHECK:             %83 = OpIAdd %uint %50 %uint_8
-;CHECK:             %84 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %83
-;CHECK:                   OpStore %84 %38
-;CHECK:             %86 = OpIAdd %uint %50 %uint_9
-;CHECK:             %87 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %86
-;CHECK:                   OpStore %87 %39
-;CHECK:             %89 = OpIAdd %uint %50 %uint_10
-;CHECK:             %90 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %89
-;CHECK:                   OpStore %90 %40
-;CHECK:                   OpBranch %54
-;CHECK:             %54 = OpLabel
-;CHECK:                   OpReturn
-;CHECK:                   OpFunctionEnd
-  )";
+                          )" + kStreamWrite5Frag;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -9305,6 +5232,7 @@
   //    imageStore(s, ii, x);
   // }
 
+  // clang-format off
   const std::string text = R"(
                           OpCapability Shader
                           OpCapability ImageBuffer
@@ -9313,7 +5241,7 @@
                      %1 = OpExtInstImport "GLSL.std.450"
                           OpMemoryModel Logical GLSL450
                           OpEntryPoint Fragment %main "main" %s %ii %x
-;CHECK:                   OpEntryPoint Fragment %main "main" %s %ii %x %44 %gl_FragCoord
+;CHECK:                   OpEntryPoint Fragment %main "main" %s %ii %x %inst_bindless_output_buffer %gl_FragCoord
                           OpExecutionMode %main OriginUpperLeft
                           OpSource GLSL 450
                           OpName %main "main"
@@ -9327,11 +5255,7 @@
                           OpDecorate %ii Location 13
                           OpDecorate %x Location 11
 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:                   OpDecorate %_struct_42 Block
-;CHECK:                   OpMemberDecorate %_struct_42 0 Offset 0
-;CHECK:                   OpMemberDecorate %_struct_42 1 Offset 4
-;CHECK:                   OpDecorate %44 DescriptorSet 7
-;CHECK:                   OpDecorate %44 Binding 0
+)" + kOutputDecorations + R"(
 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
                   %void = OpTypeVoid
                      %3 = OpTypeFunction %void
@@ -9346,29 +5270,14 @@
            %_ptr_Output_v4float = OpTypePointer Output %v4float
                      %x = OpVariable %_ptr_Output_v4float Output
 ;CHECK:           %uint = OpTypeInt 32 0
-;CHECK:         %uint_0 = OpConstant %uint 0
 ;CHECK:           %bool = OpTypeBool
-;CHECK:         %uint_7 = OpConstant %uint 7
 ;CHECK:             %34 = OpTypeFunction %void %uint %uint %uint %uint %uint
 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK:     %_struct_42 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:    %_ptr_StorageBuffer__struct_42 = OpTypePointer StorageBuffer %_struct_42
-;CHECK:             %44 = OpVariable %_ptr_StorageBuffer__struct_42 StorageBuffer
+)" + kOutputGlobals + R"(
 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-;CHECK:        %uint_11 = OpConstant %uint 11
-;CHECK:         %uint_4 = OpConstant %uint 4
-;CHECK:         %uint_1 = OpConstant %uint 1
-;CHECK:        %uint_23 = OpConstant %uint 23
-;CHECK:         %uint_2 = OpConstant %uint 2
-;CHECK:         %uint_3 = OpConstant %uint 3
 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ;CHECK:         %v4uint = OpTypeVector %uint 4
-;CHECK:         %uint_5 = OpConstant %uint 5
-;CHECK:         %uint_8 = OpConstant %uint 8
-;CHECK:         %uint_9 = OpConstant %uint 9
-;CHECK:        %uint_10 = OpConstant %uint 10
-;CHECK:        %uint_34 = OpConstant %uint 34
                   %main = OpFunction %void None %3
                      %5 = OpLabel
 ;CHECK:                   OpBranch %21
@@ -9392,65 +5301,13 @@
 ;CHECK:                   OpImageWrite %32 %14 %18
 ;CHECK:                   OpBranch %29
 ;CHECK:             %31 = OpLabel
-;CHECK:             %91 = OpFunctionCall %void %33 %uint_34 %uint_7 %uint_0 %23 %25
+;CHECK:             %91 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_34 %uint_7 %uint_0 %23 %25
 ;CHECK:                   OpBranch %29
 ;CHECK:             %29 = OpLabel
                           OpReturn
                           OpFunctionEnd
-;CHECK:             %33 = OpFunction %void None %34
-;CHECK:             %35 = OpFunctionParameter %uint
-;CHECK:             %36 = OpFunctionParameter %uint
-;CHECK:             %37 = OpFunctionParameter %uint
-;CHECK:             %38 = OpFunctionParameter %uint
-;CHECK:             %39 = OpFunctionParameter %uint
-;CHECK:             %40 = OpLabel
-;CHECK:             %46 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_0
-;CHECK:             %49 = OpAtomicIAdd %uint %46 %uint_4 %uint_0 %uint_11
-;CHECK:             %50 = OpIAdd %uint %49 %uint_11
-;CHECK:             %51 = OpArrayLength %uint %44 1
-;CHECK:             %52 = OpULessThanEqual %bool %50 %51
-;CHECK:                   OpSelectionMerge %53 None
-;CHECK:                   OpBranchConditional %52 %54 %53
-;CHECK:             %54 = OpLabel
-;CHECK:             %55 = OpIAdd %uint %49 %uint_0
-;CHECK:             %57 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %55
-;CHECK:                   OpStore %57 %uint_11
-;CHECK:             %59 = OpIAdd %uint %49 %uint_1
-;CHECK:             %60 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %59
-;CHECK:                   OpStore %60 %uint_23
-;CHECK:             %62 = OpIAdd %uint %49 %uint_2
-;CHECK:             %63 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %62
-;CHECK:                   OpStore %63 %35
-;CHECK:             %65 = OpIAdd %uint %49 %uint_3
-;CHECK:             %66 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %65
-;CHECK:                   OpStore %66 %uint_4
-;CHECK:             %69 = OpLoad %v4float %gl_FragCoord
-;CHECK:             %71 = OpBitcast %v4uint %69
-;CHECK:             %72 = OpCompositeExtract %uint %71 0
-;CHECK:             %73 = OpIAdd %uint %49 %uint_4
-;CHECK:             %74 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %73
-;CHECK:                   OpStore %74 %72
-;CHECK:             %75 = OpCompositeExtract %uint %71 1
-;CHECK:             %77 = OpIAdd %uint %49 %uint_5
-;CHECK:             %78 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %77
-;CHECK:                   OpStore %78 %75
-;CHECK:             %79 = OpIAdd %uint %49 %uint_7
-;CHECK:             %80 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %79
-;CHECK:                   OpStore %80 %36
-;CHECK:             %82 = OpIAdd %uint %49 %uint_8
-;CHECK:             %83 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %82
-;CHECK:                   OpStore %83 %37
-;CHECK:             %85 = OpIAdd %uint %49 %uint_9
-;CHECK:             %86 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %85
-;CHECK:                   OpStore %86 %38
-;CHECK:             %88 = OpIAdd %uint %49 %uint_10
-;CHECK:             %89 = OpAccessChain %_ptr_StorageBuffer_uint %44 %uint_1 %88
-;CHECK:                   OpStore %89 %39
-;CHECK:                   OpBranch %53
-;CHECK:             %53 = OpLabel
-;CHECK:                   OpReturn
-;CHECK:                   OpFunctionEnd
-  )";
+                          )" + kStreamWrite5Frag;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -9470,6 +5327,7 @@
   //    x = texelFetch(s, ii);
   // }
 
+  // clang-format off
   const std::string text = R"(
                           OpCapability Shader
                           OpCapability SampledBuffer
@@ -9478,7 +5336,7 @@
                      %1 = OpExtInstImport "GLSL.std.450"
                           OpMemoryModel Logical GLSL450
                           OpEntryPoint Fragment %main "main" %x %s %ii
-;CHECK:                   OpEntryPoint Fragment %main "main" %x %s %ii %45 %gl_FragCoord
+;CHECK:                   OpEntryPoint Fragment %main "main" %x %s %ii %inst_bindless_output_buffer %gl_FragCoord
                           OpExecutionMode %main OriginUpperLeft
                           OpSource GLSL 450
                           OpName %main "main"
@@ -9491,11 +5349,7 @@
                           OpDecorate %ii Flat
                           OpDecorate %ii Location 13
 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:                   OpDecorate %_struct_43 Block
-;CHECK:                   OpMemberDecorate %_struct_43 0 Offset 0
-;CHECK:                   OpMemberDecorate %_struct_43 1 Offset 4
-;CHECK:                   OpDecorate %45 DescriptorSet 7
-;CHECK:                   OpDecorate %45 Binding 0
+)" + kOutputDecorations + R"(
 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
                   %void = OpTypeVoid
                      %3 = OpTypeFunction %void
@@ -9510,30 +5364,14 @@
            %_ptr_Input_int = OpTypePointer Input %int
                     %ii = OpVariable %_ptr_Input_int Input
 ;CHECK:           %uint = OpTypeInt 32 0
-;CHECK:         %uint_0 = OpConstant %uint 0
 ;CHECK:           %bool = OpTypeBool
-;CHECK:         %uint_6 = OpConstant %uint 6
 ;CHECK:             %35 = OpTypeFunction %void %uint %uint %uint %uint %uint
 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK:     %_struct_43 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:    %_ptr_StorageBuffer__struct_43 = OpTypePointer StorageBuffer %_struct_43
-;CHECK:             %45 = OpVariable %_ptr_StorageBuffer__struct_43 StorageBuffer
+)" + kOutputGlobals + R"(
 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-;CHECK:        %uint_11 = OpConstant %uint 11
-;CHECK:         %uint_4 = OpConstant %uint 4
-;CHECK:         %uint_1 = OpConstant %uint 1
-;CHECK:        %uint_23 = OpConstant %uint 23
-;CHECK:         %uint_2 = OpConstant %uint 2
-;CHECK:         %uint_3 = OpConstant %uint 3
 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ;CHECK:         %v4uint = OpTypeVector %uint 4
-;CHECK:         %uint_5 = OpConstant %uint 5
-;CHECK:         %uint_7 = OpConstant %uint 7
-;CHECK:         %uint_8 = OpConstant %uint 8
-;CHECK:         %uint_9 = OpConstant %uint 9
-;CHECK:        %uint_10 = OpConstant %uint 10
-;CHECK:        %uint_32 = OpConstant %uint 32
 ;CHECK:             %94 = OpConstantNull %v4float
                   %main = OpFunction %void None %3
                      %5 = OpLabel
@@ -9559,67 +5397,15 @@
 ;CHECK:             %33 = OpImageFetch %v4float %32 %17
 ;CHECK:                   OpBranch %29
 ;CHECK:             %31 = OpLabel
-;CHECK:             %93 = OpFunctionCall %void %34 %uint_32 %uint_6 %uint_0 %23 %25
+;CHECK:             %93 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_32 %uint_6 %uint_0 %23 %25
 ;CHECK:                   OpBranch %29
 ;CHECK:             %29 = OpLabel
 ;CHECK:             %95 = OpPhi %v4float %33 %30 %94 %31
 ;CHECK:                   OpStore %x %95
                           OpReturn
                           OpFunctionEnd
-;CHECK:             %34 = OpFunction %void None %35
-;CHECK:             %36 = OpFunctionParameter %uint
-;CHECK:             %37 = OpFunctionParameter %uint
-;CHECK:             %38 = OpFunctionParameter %uint
-;CHECK:             %39 = OpFunctionParameter %uint
-;CHECK:             %40 = OpFunctionParameter %uint
-;CHECK:             %41 = OpLabel
-;CHECK:             %47 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_0
-;CHECK:             %50 = OpAtomicIAdd %uint %47 %uint_4 %uint_0 %uint_11
-;CHECK:             %51 = OpIAdd %uint %50 %uint_11
-;CHECK:             %52 = OpArrayLength %uint %45 1
-;CHECK:             %53 = OpULessThanEqual %bool %51 %52
-;CHECK:                   OpSelectionMerge %54 None
-;CHECK:                   OpBranchConditional %53 %55 %54
-;CHECK:             %55 = OpLabel
-;CHECK:             %56 = OpIAdd %uint %50 %uint_0
-;CHECK:             %58 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %56
-;CHECK:                   OpStore %58 %uint_11
-;CHECK:             %60 = OpIAdd %uint %50 %uint_1
-;CHECK:             %61 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %60
-;CHECK:                   OpStore %61 %uint_23
-;CHECK:             %63 = OpIAdd %uint %50 %uint_2
-;CHECK:             %64 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %63
-;CHECK:                   OpStore %64 %36
-;CHECK:             %66 = OpIAdd %uint %50 %uint_3
-;CHECK:             %67 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %66
-;CHECK:                   OpStore %67 %uint_4
-;CHECK:             %70 = OpLoad %v4float %gl_FragCoord
-;CHECK:             %72 = OpBitcast %v4uint %70
-;CHECK:             %73 = OpCompositeExtract %uint %72 0
-;CHECK:             %74 = OpIAdd %uint %50 %uint_4
-;CHECK:             %75 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %74
-;CHECK:                   OpStore %75 %73
-;CHECK:             %76 = OpCompositeExtract %uint %72 1
-;CHECK:             %78 = OpIAdd %uint %50 %uint_5
-;CHECK:             %79 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %78
-;CHECK:                   OpStore %79 %76
-;CHECK:             %81 = OpIAdd %uint %50 %uint_7
-;CHECK:             %82 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %81
-;CHECK:                   OpStore %82 %37
-;CHECK:             %84 = OpIAdd %uint %50 %uint_8
-;CHECK:             %85 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %84
-;CHECK:                   OpStore %85 %38
-;CHECK:             %87 = OpIAdd %uint %50 %uint_9
-;CHECK:             %88 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %87
-;CHECK:                   OpStore %88 %39
-;CHECK:             %90 = OpIAdd %uint %50 %uint_10
-;CHECK:             %91 = OpAccessChain %_ptr_StorageBuffer_uint %45 %uint_1 %90
-;CHECK:                   OpStore %91 %40
-;CHECK:                   OpBranch %54
-;CHECK:             %54 = OpLabel
-;CHECK:                   OpReturn
-;CHECK:                   OpFunctionEnd
-  )";
+                          )" + kStreamWrite5Frag;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -9639,6 +5425,7 @@
   //    x = texelFetch(s, ii);
   // }
 
+  // clang-format off
   const std::string text = R"(
                           OpCapability Shader
                           OpCapability SampledBuffer
@@ -9647,7 +5434,7 @@
                      %1 = OpExtInstImport "GLSL.std.450"
                           OpMemoryModel Logical GLSL450
                           OpEntryPoint Fragment %main "main" %x %s %ii
-;CHECK:                   OpEntryPoint Fragment %main "main" %x %s %ii %48 %gl_FragCoord
+;CHECK:                   OpEntryPoint Fragment %main "main" %x %s %ii %inst_bindless_output_buffer %gl_FragCoord
                           OpExecutionMode %main OriginUpperLeft
                           OpSource GLSL 450
                           OpName %main "main"
@@ -9660,11 +5447,7 @@
                           OpDecorate %ii Flat
                           OpDecorate %ii Location 13
 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:                   OpDecorate %_struct_46 Block
-;CHECK:                   OpMemberDecorate %_struct_46 0 Offset 0
-;CHECK:                   OpMemberDecorate %_struct_46 1 Offset 4
-;CHECK:                   OpDecorate %48 DescriptorSet 7
-;CHECK:                   OpDecorate %48 Binding 0
+)" + kOutputDecorations + R"(
 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
                   %void = OpTypeVoid
                      %3 = OpTypeFunction %void
@@ -9680,30 +5463,14 @@
            %_ptr_Input_int = OpTypePointer Input %int
                     %ii = OpVariable %_ptr_Input_int Input
 ;CHECK:           %uint = OpTypeInt 32 0
-;CHECK:         %uint_0 = OpConstant %uint 0
 ;CHECK:           %bool = OpTypeBool
-;CHECK:         %uint_6 = OpConstant %uint 6
 ;CHECK:             %38 = OpTypeFunction %void %uint %uint %uint %uint %uint
 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK:     %_struct_46 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:    %_ptr_StorageBuffer__struct_46 = OpTypePointer StorageBuffer %_struct_46
-;CHECK:             %48 = OpVariable %_ptr_StorageBuffer__struct_46 StorageBuffer
+)" + kOutputGlobals + R"(
 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-;CHECK:        %uint_11 = OpConstant %uint 11
-;CHECK:         %uint_4 = OpConstant %uint 4
-;CHECK:         %uint_1 = OpConstant %uint 1
-;CHECK:        %uint_23 = OpConstant %uint 23
-;CHECK:         %uint_2 = OpConstant %uint 2
-;CHECK:         %uint_3 = OpConstant %uint 3
 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ;CHECK:         %v4uint = OpTypeVector %uint 4
-;CHECK:         %uint_5 = OpConstant %uint 5
-;CHECK:         %uint_7 = OpConstant %uint 7
-;CHECK:         %uint_8 = OpConstant %uint 8
-;CHECK:         %uint_9 = OpConstant %uint 9
-;CHECK:        %uint_10 = OpConstant %uint 10
-;CHECK:        %uint_34 = OpConstant %uint 34
 ;CHECK:             %97 = OpConstantNull %v4float
                   %main = OpFunction %void None %3
                      %5 = OpLabel
@@ -9731,67 +5498,15 @@
 ;CHECK:             %36 = OpImageFetch %v4float %35 %18
 ;CHECK:                   OpBranch %31
 ;CHECK:             %33 = OpLabel
-;CHECK:             %96 = OpFunctionCall %void %37 %uint_34 %uint_6 %uint_0 %25 %27
+;CHECK:             %96 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_34 %uint_6 %uint_0 %25 %27
 ;CHECK:                   OpBranch %31
 ;CHECK:             %31 = OpLabel
 ;CHECK:             %98 = OpPhi %v4float %36 %32 %97 %33
 ;CHECK:                   OpStore %x %98
                           OpReturn
                           OpFunctionEnd
-;CHECK:             %37 = OpFunction %void None %38
-;CHECK:             %39 = OpFunctionParameter %uint
-;CHECK:             %40 = OpFunctionParameter %uint
-;CHECK:             %41 = OpFunctionParameter %uint
-;CHECK:             %42 = OpFunctionParameter %uint
-;CHECK:             %43 = OpFunctionParameter %uint
-;CHECK:             %44 = OpLabel
-;CHECK:             %50 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_0
-;CHECK:             %53 = OpAtomicIAdd %uint %50 %uint_4 %uint_0 %uint_11
-;CHECK:             %54 = OpIAdd %uint %53 %uint_11
-;CHECK:             %55 = OpArrayLength %uint %48 1
-;CHECK:             %56 = OpULessThanEqual %bool %54 %55
-;CHECK:                   OpSelectionMerge %57 None
-;CHECK:                   OpBranchConditional %56 %58 %57
-;CHECK:             %58 = OpLabel
-;CHECK:             %59 = OpIAdd %uint %53 %uint_0
-;CHECK:             %61 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %59
-;CHECK:                   OpStore %61 %uint_11
-;CHECK:             %63 = OpIAdd %uint %53 %uint_1
-;CHECK:             %64 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %63
-;CHECK:                   OpStore %64 %uint_23
-;CHECK:             %66 = OpIAdd %uint %53 %uint_2
-;CHECK:             %67 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %66
-;CHECK:                   OpStore %67 %39
-;CHECK:             %69 = OpIAdd %uint %53 %uint_3
-;CHECK:             %70 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %69
-;CHECK:                   OpStore %70 %uint_4
-;CHECK:             %73 = OpLoad %v4float %gl_FragCoord
-;CHECK:             %75 = OpBitcast %v4uint %73
-;CHECK:             %76 = OpCompositeExtract %uint %75 0
-;CHECK:             %77 = OpIAdd %uint %53 %uint_4
-;CHECK:             %78 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %77
-;CHECK:                   OpStore %78 %76
-;CHECK:             %79 = OpCompositeExtract %uint %75 1
-;CHECK:             %81 = OpIAdd %uint %53 %uint_5
-;CHECK:             %82 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %81
-;CHECK:                   OpStore %82 %79
-;CHECK:             %84 = OpIAdd %uint %53 %uint_7
-;CHECK:             %85 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %84
-;CHECK:                   OpStore %85 %40
-;CHECK:             %87 = OpIAdd %uint %53 %uint_8
-;CHECK:             %88 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %87
-;CHECK:                   OpStore %88 %41
-;CHECK:             %90 = OpIAdd %uint %53 %uint_9
-;CHECK:             %91 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %90
-;CHECK:                   OpStore %91 %42
-;CHECK:             %93 = OpIAdd %uint %53 %uint_10
-;CHECK:             %94 = OpAccessChain %_ptr_StorageBuffer_uint %48 %uint_1 %93
-;CHECK:                   OpStore %94 %43
-;CHECK:                   OpBranch %57
-;CHECK:             %57 = OpLabel
-;CHECK:                   OpReturn
-;CHECK:                   OpFunctionEnd
-  )";
+                          )" + kStreamWrite5Frag;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -9812,6 +5527,7 @@
   //    x = texelFetch(samplerBuffer(tBuf, s), ii);
   // }
 
+  // clang-format off
   const std::string text = R"(
                           OpCapability Shader
                           OpCapability SampledBuffer
@@ -9820,7 +5536,7 @@
                      %1 = OpExtInstImport "GLSL.std.450"
                           OpMemoryModel Logical GLSL450
                           OpEntryPoint Fragment %main "main" %x %tBuf %s %ii
-;CHECK:                   OpEntryPoint Fragment %main "main" %x %tBuf %s %ii %54 %gl_FragCoord
+;CHECK:                   OpEntryPoint Fragment %main "main" %x %tBuf %s %ii %inst_bindless_output_buffer %gl_FragCoord
                           OpExecutionMode %main OriginUpperLeft
                           OpSource GLSL 450
                           OpName %main "main"
@@ -9836,11 +5552,7 @@
                           OpDecorate %ii Flat
                           OpDecorate %ii Location 13
 ;CHECK:                   OpDecorate %_runtimearr_uint ArrayStride 4
-;CHECK:                   OpDecorate %_struct_52 Block
-;CHECK:                   OpMemberDecorate %_struct_52 0 Offset 0
-;CHECK:                   OpMemberDecorate %_struct_52 1 Offset 4
-;CHECK:                   OpDecorate %54 DescriptorSet 7
-;CHECK:                   OpDecorate %54 Binding 0
+)" + kOutputDecorations + R"(
 ;CHECK:                   OpDecorate %gl_FragCoord BuiltIn FragCoord
                   %void = OpTypeVoid
                      %3 = OpTypeFunction %void
@@ -9859,30 +5571,14 @@
            %_ptr_Input_int = OpTypePointer Input %int
                     %ii = OpVariable %_ptr_Input_int Input
 ;CHECK:           %uint = OpTypeInt 32 0
-;CHECK:         %uint_0 = OpConstant %uint 0
 ;CHECK:           %bool = OpTypeBool
-;CHECK:         %uint_6 = OpConstant %uint 6
 ;CHECK:             %44 = OpTypeFunction %void %uint %uint %uint %uint %uint
 ;CHECK:    %_runtimearr_uint = OpTypeRuntimeArray %uint
-;CHECK:     %_struct_52 = OpTypeStruct %uint %_runtimearr_uint
-;CHECK:    %_ptr_StorageBuffer__struct_52 = OpTypePointer StorageBuffer %_struct_52
-;CHECK:             %54 = OpVariable %_ptr_StorageBuffer__struct_52 StorageBuffer
+)" + kOutputGlobals + R"(
 ;CHECK:    %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-;CHECK:        %uint_11 = OpConstant %uint 11
-;CHECK:         %uint_4 = OpConstant %uint 4
-;CHECK:         %uint_1 = OpConstant %uint 1
-;CHECK:        %uint_23 = OpConstant %uint 23
-;CHECK:         %uint_2 = OpConstant %uint 2
-;CHECK:         %uint_3 = OpConstant %uint 3
 ;CHECK:    %_ptr_Input_v4float = OpTypePointer Input %v4float
 ;CHECK:    %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ;CHECK:         %v4uint = OpTypeVector %uint 4
-;CHECK:         %uint_5 = OpConstant %uint 5
-;CHECK:         %uint_7 = OpConstant %uint 7
-;CHECK:         %uint_8 = OpConstant %uint 8
-;CHECK:         %uint_9 = OpConstant %uint 9
-;CHECK:        %uint_10 = OpConstant %uint 10
-;CHECK:        %uint_42 = OpConstant %uint 42
 ;CHECK:            %103 = OpConstantNull %v4float
                   %main = OpFunction %void None %3
                      %5 = OpLabel
@@ -9913,67 +5609,15 @@
 ;CHECK:             %42 = OpImageFetch %v4float %41 %23
 ;CHECK:                   OpBranch %36
 ;CHECK:             %38 = OpLabel
-;CHECK:            %102 = OpFunctionCall %void %43 %uint_42 %uint_6 %uint_0 %30 %32
+;CHECK:            %102 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_42 %uint_6 %uint_0 %30 %32
 ;CHECK:                   OpBranch %36
 ;CHECK:             %36 = OpLabel
 ;CHECK:            %104 = OpPhi %v4float %42 %37 %103 %38
 ;CHECK:                   OpStore %x %104
                           OpReturn
                           OpFunctionEnd
-;CHECK:             %43 = OpFunction %void None %44
-;CHECK:             %45 = OpFunctionParameter %uint
-;CHECK:             %46 = OpFunctionParameter %uint
-;CHECK:             %47 = OpFunctionParameter %uint
-;CHECK:             %48 = OpFunctionParameter %uint
-;CHECK:             %49 = OpFunctionParameter %uint
-;CHECK:             %50 = OpLabel
-;CHECK:             %56 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_0
-;CHECK:             %59 = OpAtomicIAdd %uint %56 %uint_4 %uint_0 %uint_11
-;CHECK:             %60 = OpIAdd %uint %59 %uint_11
-;CHECK:             %61 = OpArrayLength %uint %54 1
-;CHECK:             %62 = OpULessThanEqual %bool %60 %61
-;CHECK:                   OpSelectionMerge %63 None
-;CHECK:                   OpBranchConditional %62 %64 %63
-;CHECK:             %64 = OpLabel
-;CHECK:             %65 = OpIAdd %uint %59 %uint_0
-;CHECK:             %67 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %65
-;CHECK:                   OpStore %67 %uint_11
-;CHECK:             %69 = OpIAdd %uint %59 %uint_1
-;CHECK:             %70 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %69
-;CHECK:                   OpStore %70 %uint_23
-;CHECK:             %72 = OpIAdd %uint %59 %uint_2
-;CHECK:             %73 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %72
-;CHECK:                   OpStore %73 %45
-;CHECK:             %75 = OpIAdd %uint %59 %uint_3
-;CHECK:             %76 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %75
-;CHECK:                   OpStore %76 %uint_4
-;CHECK:             %79 = OpLoad %v4float %gl_FragCoord
-;CHECK:             %81 = OpBitcast %v4uint %79
-;CHECK:             %82 = OpCompositeExtract %uint %81 0
-;CHECK:             %83 = OpIAdd %uint %59 %uint_4
-;CHECK:             %84 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %83
-;CHECK:                   OpStore %84 %82
-;CHECK:             %85 = OpCompositeExtract %uint %81 1
-;CHECK:             %87 = OpIAdd %uint %59 %uint_5
-;CHECK:             %88 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %87
-;CHECK:                   OpStore %88 %85
-;CHECK:             %90 = OpIAdd %uint %59 %uint_7
-;CHECK:             %91 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %90
-;CHECK:                   OpStore %91 %46
-;CHECK:             %93 = OpIAdd %uint %59 %uint_8
-;CHECK:             %94 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %93
-;CHECK:                   OpStore %94 %47
-;CHECK:             %96 = OpIAdd %uint %59 %uint_9
-;CHECK:             %97 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %96
-;CHECK:                   OpStore %97 %48
-;CHECK:             %99 = OpIAdd %uint %59 %uint_10
-;CHECK:             %100 = OpAccessChain %_ptr_StorageBuffer_uint %54 %uint_1 %99
-;CHECK:                   OpStore %100 %49
-;CHECK:                   OpBranch %63
-;CHECK:             %63 = OpLabel
-;CHECK:                   OpReturn
-;CHECK:                   OpFunctionEnd
-  )";
+                          )" + kStreamWrite5Frag;
+  // clang-format on
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
diff --git a/third_party/SPIRV-Tools/test/opt/inst_buff_addr_check_test.cpp b/third_party/SPIRV-Tools/test/opt/inst_buff_addr_check_test.cpp
index 95114b2..7886ba7 100644
--- a/third_party/SPIRV-Tools/test/opt/inst_buff_addr_check_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/inst_buff_addr_check_test.cpp
@@ -1,5 +1,5 @@
-// Copyright (c) 2019 Valve Corporation
-// Copyright (c) 2019 LunarG Inc.
+// Copyright (c) 2019-2022 Valve Corporation
+// Copyright (c) 2019-2022 LunarG Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -27,6 +27,148 @@
 namespace opt {
 namespace {
 
+static const std::string kOutputDecorations = R"(
+; CHECK: OpDecorate [[output_buffer_type:%inst_buff_addr_OutputBuffer]] Block
+; CHECK: OpMemberDecorate [[output_buffer_type]] 0 Offset 0
+; CHECK: OpMemberDecorate [[output_buffer_type]] 1 Offset 4
+; CHECK: OpDecorate [[output_buffer_var:%\w+]] DescriptorSet 7
+; CHECK: OpDecorate [[output_buffer_var]] Binding 0
+)";
+
+static const std::string kOutputGlobals = R"(
+; CHECK: [[output_buffer_type]] = OpTypeStruct %uint %uint %_runtimearr_uint
+; CHECK: [[output_ptr_type:%\w+]] = OpTypePointer StorageBuffer [[output_buffer_type]]
+; CHECK: [[output_buffer_var]] = OpVariable [[output_ptr_type]] StorageBuffer
+)";
+
+static const std::string kStreamWrite4Begin = R"(
+; CHECK: {{%\w+}} = OpFunction %void None {{%\w+}}
+; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_4:%\w+]] = OpFunctionParameter %uint
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_1
+; CHECK: {{%\w+}} = OpAtomicIAdd %uint {{%\w+}} %uint_4 %uint_0 %uint_10
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_10
+; CHECK: {{%\w+}} = OpArrayLength %uint [[output_buffer_var]] 2
+; CHECK: {{%\w+}} = OpULessThanEqual %bool {{%\w+}} {{%\w+}}
+; CHECK: OpSelectionMerge {{%\w+}} None
+; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_0
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_10
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_1
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_23
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_2
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_1]]
+)";
+
+static const std::string kStreamWrite4End = R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_2]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_8
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_3]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_9
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_4]]
+; CHECK: OpBranch {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: OpReturn
+; CHECK: OpFunctionEnd
+)";
+
+// clang-format off
+static const std::string kStreamWrite4Frag = kStreamWrite4Begin + R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord
+; CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+)" + kStreamWrite4End;
+
+static const std::string kStreamWrite4Compute = kStreamWrite4Begin + R"(
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpLoad %v3uint %gl_GlobalInvocationID
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_6
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint [[output_buffer_var]] %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+)" + kStreamWrite4End;
+// clang-format on
+
+static const std::string kInputDecorations = R"(
+; CHECK: OpDecorate [[input_buffer_type:%inst_buff_addr_InputBuffer]] Block
+; CHECK: OpMemberDecorate [[input_buffer_type]] 0 Offset 0
+; CHECK: OpDecorate [[input_buffer_var:%\w+]] DescriptorSet 7
+; CHECK: OpDecorate [[input_buffer_var]] Binding 2
+)";
+
+static const std::string kInputGlobals = R"(
+; CHECK: [[input_buffer_type]] = OpTypeStruct %_runtimearr_ulong
+; CHECK: [[input_ptr_type:%\w+]] = OpTypePointer StorageBuffer [[input_buffer_type]]
+; CHECK: [[input_buffer_var]] = OpVariable [[input_ptr_type]] StorageBuffer
+)";
+
+static const std::string kSearchAndTest = R"(
+; CHECK: {{%\w+}} = OpFunction %bool None {{%\w+}}
+; CHECK: [[param_1:%\w+]] = OpFunctionParameter %ulong
+; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: OpBranch {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpPhi %uint %uint_1 {{%\w+}} {{%\w+}} {{%\w+}}
+; CHECK: OpLoopMerge {{%\w+}} {{%\w+}} None
+; CHECK: OpBranch {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_1
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_ulong [[input_buffer_var]] %uint_0 {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %ulong {{%\w+}}
+; CHECK: {{%\w+}} = OpUGreaterThan %bool {{%\w+}} [[param_1]]
+; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpISub %uint {{%\w+}} %uint_1
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_ulong [[input_buffer_var]] %uint_0 {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %ulong {{%\w+}}
+; CHECK: {{%\w+}} = OpISub %ulong [[param_1]] {{%\w+}}
+; CHECK: {{%\w+}} = OpUConvert %ulong [[param_2]]
+; CHECK: {{%\w+}} = OpIAdd %ulong {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_ulong [[input_buffer_var]] %uint_0 %uint_0
+; CHECK: {{%\w+}} = OpLoad %ulong {{%\w+}}
+; CHECK: {{%\w+}} = OpUConvert %uint {{%\w+}}
+; CHECK: {{%\w+}} = OpISub %uint {{%\w+}} %uint_1
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_ulong [[input_buffer_var]] %uint_0 {{%\w+}}
+; CHECK: {{%\w+}} = OpLoad %ulong {{%\w+}}
+; CHECK: {{%\w+}} = OpULessThanEqual %bool {{%\w+}} {{%\w+}}
+; CHECK: OpReturnValue {{%\w+}}
+; CHECK: OpFunctionEnd
+)";
+// clang-format on
+
 using InstBuffAddrTest = PassTest<::testing::Test>;
 
 TEST_F(InstBuffAddrTest, InstPhysicalStorageBufferStore) {
@@ -49,13 +191,16 @@
   //     u_info.data.b = 0xca7;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability PhysicalStorageBufferAddresses
+; CHECK: OpCapability Int64
 OpExtension "SPV_EXT_physical_storage_buffer"
+; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel PhysicalStorageBuffer64 GLSL450
 OpEntryPoint GLCompute %main "main"
+; CHECK: OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
 OpExecutionMode %main LocalSize 1 1 1
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_buffer_reference"
@@ -67,6 +212,10 @@
 OpMemberName %bufStruct 0 "a"
 OpMemberName %bufStruct 1 "b"
 OpName %u_info "u_info"
+)";
+
+  // clang-format off
+  const std::string decorates = R"(
 OpMemberDecorate %ufoo 0 Offset 0
 OpMemberDecorate %ufoo 1 Offset 8
 OpDecorate %ufoo Block
@@ -76,6 +225,14 @@
 OpDecorate %bufStruct Block
 OpDecorate %u_info DescriptorSet 0
 OpDecorate %u_info Binding 0
+; CHECK: OpDecorate %_runtimearr_ulong ArrayStride 8
+)" + kInputDecorations + R"(
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+)";
+
+  const std::string globals = R"(
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_bufStruct PhysicalStorageBuffer
@@ -93,224 +250,58 @@
 %int_1 = OpConstant %int 1
 %int_3239 = OpConstant %int 3239
 %_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int
+; CHECK: %ulong = OpTypeInt 64 0
+; CHECK: %bool = OpTypeBool
+; CHECK: %28 = OpTypeFunction %bool %ulong %uint
+; CHECK: %_runtimearr_ulong = OpTypeRuntimeArray %ulong
+)" + kInputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_ulong = OpTypePointer StorageBuffer %ulong
+; CHECK: %70 = OpTypeFunction %void %uint %uint %uint %uint
+; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
+)" + kOutputGlobals + R"(
+; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+; CHECK: %v3uint = OpTypeVector %uint 3
+; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+; CHECK: %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
 )";
+// clang-format off
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability PhysicalStorageBufferAddresses
-OpCapability Int64
-OpExtension "SPV_EXT_physical_storage_buffer"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel PhysicalStorageBuffer64 GLSL450
-OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
-OpExecutionMode %main LocalSize 1 1 1
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_buffer_reference"
-OpName %main "main"
-OpName %ufoo "ufoo"
-OpMemberName %ufoo 0 "data"
-OpMemberName %ufoo 1 "offset"
-OpName %bufStruct "bufStruct"
-OpMemberName %bufStruct 0 "a"
-OpMemberName %bufStruct 1 "b"
-OpName %u_info "u_info"
-OpMemberDecorate %ufoo 0 Offset 0
-OpMemberDecorate %ufoo 1 Offset 8
-OpDecorate %ufoo Block
-OpDecorate %_arr_int_uint_2 ArrayStride 16
-OpMemberDecorate %bufStruct 0 Offset 0
-OpMemberDecorate %bufStruct 1 Offset 32
-OpDecorate %bufStruct Block
-OpDecorate %u_info DescriptorSet 0
-OpDecorate %u_info Binding 0
-OpDecorate %_runtimearr_ulong ArrayStride 8
-OpDecorate %_struct_39 Block
-OpMemberDecorate %_struct_39 0 Offset 0
-OpDecorate %41 DescriptorSet 7
-OpDecorate %41 Binding 2
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_77 Block
-OpMemberDecorate %_struct_77 0 Offset 0
-OpMemberDecorate %_struct_77 1 Offset 4
-OpDecorate %79 DescriptorSet 7
-OpDecorate %79 Binding 0
-OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
-%void = OpTypeVoid
-%8 = OpTypeFunction %void
-OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_bufStruct PhysicalStorageBuffer
-%uint = OpTypeInt 32 0
-%ufoo = OpTypeStruct %_ptr_PhysicalStorageBuffer_bufStruct %uint
-%int = OpTypeInt 32 1
-%uint_2 = OpConstant %uint 2
-%_arr_int_uint_2 = OpTypeArray %int %uint_2
-%bufStruct = OpTypeStruct %_arr_int_uint_2 %int
-%_ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer PhysicalStorageBuffer %bufStruct
-%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo
-%u_info = OpVariable %_ptr_Uniform_ufoo Uniform
-%int_0 = OpConstant %int 0
-%_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer Uniform %_ptr_PhysicalStorageBuffer_bufStruct
-%int_1 = OpConstant %int 1
-%int_3239 = OpConstant %int 3239
-%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int
-%ulong = OpTypeInt 64 0
-%uint_4 = OpConstant %uint 4
-%bool = OpTypeBool
-%28 = OpTypeFunction %bool %ulong %uint
-%uint_1 = OpConstant %uint 1
-%_runtimearr_ulong = OpTypeRuntimeArray %ulong
-%_struct_39 = OpTypeStruct %_runtimearr_ulong
-%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
-%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
-%_ptr_StorageBuffer_ulong = OpTypePointer StorageBuffer %ulong
-%uint_0 = OpConstant %uint 0
-%uint_32 = OpConstant %uint 32
-%70 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_77 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_77 = OpTypePointer StorageBuffer %_struct_77
-%79 = OpVariable %_ptr_StorageBuffer__struct_77 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_23 = OpConstant %uint 23
-%uint_5 = OpConstant %uint 5
-%uint_3 = OpConstant %uint 3
-%v3uint = OpTypeVector %uint 3
-%_ptr_Input_v3uint = OpTypePointer Input %v3uint
-%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_8 = OpConstant %uint 8
-%uint_9 = OpConstant %uint 9
-%uint_48 = OpConstant %uint 48
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %17 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0
 %18 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %17
 %22 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %18 %int_1
+; CHECK-NOT: %17 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0
+; CHECK-NOT: %18 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %17
+; CHECK-NOT: %22 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %18 %int_1
+; CHECK: %20 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0
+; CHECK: %21 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %20
+; CHECK: %22 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %21 %int_1
+; CHECK: %24 = OpConvertPtrToU %ulong %22
+; CHECK: %61 = OpFunctionCall %bool %inst_buff_addr_search_and_test %24 %uint_4
+; CHECK: OpSelectionMerge %62 None
+; CHECK: OpBranchConditional %61 %63 %64
+; CHECK: %63 = OpLabel
 OpStore %22 %int_3239 Aligned 16
+; CHECK: OpStore %22 %int_3239 Aligned 16
+; CHECK: OpBranch %62
+; CHECK: %64 = OpLabel
+; CHECK: %65 = OpUConvert %uint %24
+; CHECK: %67 = OpShiftRightLogical %ulong %24 %uint_32
+; CHECK: %68 = OpUConvert %uint %67
+; CHECK: %124 = OpFunctionCall %void %inst_buff_addr_stream_write_4 %uint_48 %uint_2 %65 %68
+; CHECK: OpBranch %62
+; CHECK: %62 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %8
-%19 = OpLabel
-%20 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0
-%21 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %20
-%22 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %21 %int_1
-%24 = OpConvertPtrToU %ulong %22
-%61 = OpFunctionCall %bool %26 %24 %uint_4
-OpSelectionMerge %62 None
-OpBranchConditional %61 %63 %64
-%63 = OpLabel
-OpStore %22 %int_3239 Aligned 16
-OpBranch %62
-%64 = OpLabel
-%65 = OpUConvert %uint %24
-%67 = OpShiftRightLogical %ulong %24 %uint_32
-%68 = OpUConvert %uint %67
-%124 = OpFunctionCall %void %69 %uint_48 %uint_2 %65 %68
-OpBranch %62
-%62 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%26 = OpFunction %bool None %28
-%29 = OpFunctionParameter %ulong
-%30 = OpFunctionParameter %uint
-%31 = OpLabel
-OpBranch %32
-%32 = OpLabel
-%34 = OpPhi %uint %uint_1 %31 %35 %33
-OpLoopMerge %37 %33 None
-OpBranch %33
-%33 = OpLabel
-%35 = OpIAdd %uint %34 %uint_1
-%44 = OpAccessChain %_ptr_StorageBuffer_ulong %41 %uint_0 %35
-%45 = OpLoad %ulong %44
-%46 = OpUGreaterThan %bool %45 %29
-OpBranchConditional %46 %37 %32
-%37 = OpLabel
-%47 = OpISub %uint %35 %uint_1
-%48 = OpAccessChain %_ptr_StorageBuffer_ulong %41 %uint_0 %47
-%49 = OpLoad %ulong %48
-%50 = OpISub %ulong %29 %49
-%51 = OpUConvert %ulong %30
-%52 = OpIAdd %ulong %50 %51
-%53 = OpAccessChain %_ptr_StorageBuffer_ulong %41 %uint_0 %uint_0
-%54 = OpLoad %ulong %53
-%55 = OpUConvert %uint %54
-%56 = OpISub %uint %47 %uint_1
-%57 = OpIAdd %uint %56 %55
-%58 = OpAccessChain %_ptr_StorageBuffer_ulong %41 %uint_0 %57
-%59 = OpLoad %ulong %58
-%60 = OpULessThanEqual %bool %52 %59
-OpReturnValue %60
-OpFunctionEnd
-%69 = OpFunction %void None %70
-%71 = OpFunctionParameter %uint
-%72 = OpFunctionParameter %uint
-%73 = OpFunctionParameter %uint
-%74 = OpFunctionParameter %uint
-%75 = OpLabel
-%81 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_0
-%83 = OpAtomicIAdd %uint %81 %uint_4 %uint_0 %uint_10
-%84 = OpIAdd %uint %83 %uint_10
-%85 = OpArrayLength %uint %79 1
-%86 = OpULessThanEqual %bool %84 %85
-OpSelectionMerge %87 None
-OpBranchConditional %86 %88 %87
-%88 = OpLabel
-%89 = OpIAdd %uint %83 %uint_0
-%90 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %89
-OpStore %90 %uint_10
-%92 = OpIAdd %uint %83 %uint_1
-%93 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %92
-OpStore %93 %uint_23
-%94 = OpIAdd %uint %83 %uint_2
-%95 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %94
-OpStore %95 %71
-%98 = OpIAdd %uint %83 %uint_3
-%99 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %98
-OpStore %99 %uint_5
-%103 = OpLoad %v3uint %gl_GlobalInvocationID
-%104 = OpCompositeExtract %uint %103 0
-%105 = OpCompositeExtract %uint %103 1
-%106 = OpCompositeExtract %uint %103 2
-%107 = OpIAdd %uint %83 %uint_4
-%108 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %107
-OpStore %108 %104
-%109 = OpIAdd %uint %83 %uint_5
-%110 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %109
-OpStore %110 %105
-%112 = OpIAdd %uint %83 %uint_6
-%113 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %112
-OpStore %113 %106
-%115 = OpIAdd %uint %83 %uint_7
-%116 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %115
-OpStore %116 %72
-%118 = OpIAdd %uint %83 %uint_8
-%119 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %118
-OpStore %119 %73
-%121 = OpIAdd %uint %83 %uint_9
-%122 = OpAccessChain %_ptr_StorageBuffer_uint %79 %uint_1 %121
-OpStore %122 %74
-OpBranch %87
-%87 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_funcs = kSearchAndTest + kStreamWrite4Compute;
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBuffAddrCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u);
+  SinglePassRunAndMatch<InstBuffAddrCheckPass>(
+      defs + decorates + globals + main_func + output_funcs, true, 7u, 23u);
 }
 
 TEST_F(InstBuffAddrTest, InstPhysicalStorageBufferLoadAndStore) {
@@ -337,9 +328,10 @@
   //   b.x = 531;
   // }
 
-  const std::string defs_before =
-      R"(OpCapability Shader
+  const std::string defs = R"(
+OpCapability Shader
 OpCapability PhysicalStorageBufferAddresses
+; CHECK: OpCapability Int64
 OpExtension "SPV_EXT_physical_storage_buffer"
 OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
@@ -349,12 +341,17 @@
 OpSource GLSL 450
 OpSourceExtension "GL_EXT_buffer_reference"
 OpName %main "main"
+; CHECK: OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
 OpName %blockType "blockType"
 OpMemberName %blockType 0 "x"
 OpMemberName %blockType 1 "next"
 OpName %rootBlock "rootBlock"
 OpMemberName %rootBlock 0 "root"
 OpName %r "r"
+)";
+
+// clang-format off
+  const std::string decorates = R"(
 OpMemberDecorate %blockType 0 Offset 0
 OpMemberDecorate %blockType 1 Offset 8
 OpDecorate %blockType Block
@@ -362,6 +359,15 @@
 OpDecorate %rootBlock Block
 OpDecorate %r DescriptorSet 0
 OpDecorate %r Binding 0
+; CHECK: OpDecorate %_runtimearr_ulong ArrayStride 8
+)" + kInputDecorations + R"(
+; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
+)" + kOutputDecorations + R"(
+; CHECK: OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+)";
+  // clang-format on
+
+  const std::string globals = R"(
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer
@@ -377,99 +383,10 @@
 %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType
 %int_531 = OpConstant %int 531
 %_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int
-)";
+)" + kInputGlobals + kOutputGlobals;
 
-  const std::string defs_after =
-      R"(OpCapability Shader
-OpCapability PhysicalStorageBufferAddresses
-OpCapability Int64
-OpExtension "SPV_EXT_physical_storage_buffer"
-OpExtension "SPV_KHR_storage_buffer_storage_class"
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel PhysicalStorageBuffer64 GLSL450
-OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
-OpExecutionMode %main LocalSize 1 1 1
-OpSource GLSL 450
-OpSourceExtension "GL_EXT_buffer_reference"
-OpName %main "main"
-OpName %blockType "blockType"
-OpMemberName %blockType 0 "x"
-OpMemberName %blockType 1 "next"
-OpName %rootBlock "rootBlock"
-OpMemberName %rootBlock 0 "root"
-OpName %r "r"
-OpMemberDecorate %blockType 0 Offset 0
-OpMemberDecorate %blockType 1 Offset 8
-OpDecorate %blockType Block
-OpMemberDecorate %rootBlock 0 Offset 0
-OpDecorate %rootBlock Block
-OpDecorate %r DescriptorSet 0
-OpDecorate %r Binding 0
-OpDecorate %_runtimearr_ulong ArrayStride 8
-OpDecorate %_struct_45 Block
-OpMemberDecorate %_struct_45 0 Offset 0
-OpDecorate %47 DescriptorSet 7
-OpDecorate %47 Binding 2
-OpDecorate %_runtimearr_uint ArrayStride 4
-OpDecorate %_struct_84 Block
-OpMemberDecorate %_struct_84 0 Offset 0
-OpMemberDecorate %_struct_84 1 Offset 4
-OpDecorate %86 DescriptorSet 7
-OpDecorate %86 Binding 0
-OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
-%void = OpTypeVoid
-%3 = OpTypeFunction %void
-OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer
-%int = OpTypeInt 32 1
-%blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType
-%_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType
-%rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType
-%_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock
-%r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer
-%int_0 = OpConstant %int 0
-%_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType
-%int_1 = OpConstant %int 1
-%_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType
-%int_531 = OpConstant %int 531
-%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int
-%uint = OpTypeInt 32 0
-%uint_2 = OpConstant %uint 2
-%ulong = OpTypeInt 64 0
-%uint_8 = OpConstant %uint 8
-%bool = OpTypeBool
-%34 = OpTypeFunction %bool %ulong %uint
-%uint_1 = OpConstant %uint 1
-%_runtimearr_ulong = OpTypeRuntimeArray %ulong
-%_struct_45 = OpTypeStruct %_runtimearr_ulong
-%_ptr_StorageBuffer__struct_45 = OpTypePointer StorageBuffer %_struct_45
-%47 = OpVariable %_ptr_StorageBuffer__struct_45 StorageBuffer
-%_ptr_StorageBuffer_ulong = OpTypePointer StorageBuffer %ulong
-%uint_0 = OpConstant %uint 0
-%uint_32 = OpConstant %uint 32
-%77 = OpTypeFunction %void %uint %uint %uint %uint
-%_runtimearr_uint = OpTypeRuntimeArray %uint
-%_struct_84 = OpTypeStruct %uint %_runtimearr_uint
-%_ptr_StorageBuffer__struct_84 = OpTypePointer StorageBuffer %_struct_84
-%86 = OpVariable %_ptr_StorageBuffer__struct_84 StorageBuffer
-%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-%uint_10 = OpConstant %uint 10
-%uint_4 = OpConstant %uint 4
-%uint_23 = OpConstant %uint 23
-%uint_5 = OpConstant %uint 5
-%uint_3 = OpConstant %uint 3
-%v3uint = OpTypeVector %uint 3
-%_ptr_Input_v3uint = OpTypePointer Input %v3uint
-%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
-%uint_6 = OpConstant %uint 6
-%uint_7 = OpConstant %uint 7
-%uint_9 = OpConstant %uint 9
-%uint_44 = OpConstant %uint 44
-%132 = OpConstantNull %ulong
-%uint_46 = OpConstant %uint 46
-)";
-
-  const std::string func_before =
-      R"(%main = OpFunction %void None %3
+  const std::string main_func = R"(
+%main = OpFunction %void None %3
 %5 = OpLabel
 %16 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0
 %17 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %16
@@ -477,142 +394,48 @@
 %22 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8
 %26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %22 %int_0
 OpStore %26 %int_531 Aligned 16
+; CHECK-NOT: %22 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8
+; CHECK-NOT: %26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %22 %int_0
+; CHECK: %30 = OpConvertPtrToU %ulong %21
+; CHECK: %67 = OpFunctionCall %bool %inst_buff_addr_search_and_test %30 %uint_8
+; CHECK: OpSelectionMerge %68 None
+; CHECK: OpBranchConditional %67 %69 %70
+; CHECK: %69 = OpLabel
+; CHECK: %71 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8
+; CHECK: OpBranch %68
+; CHECK: %70 = OpLabel
+; CHECK: %72 = OpUConvert %uint %30
+; CHECK: %74 = OpShiftRightLogical %ulong %30 %uint_32
+; CHECK: %75 = OpUConvert %uint %74
+; CHECK: %131 = OpFunctionCall %void %inst_buff_addr_stream_write_4 %uint_44 %uint_2 %72 %75
+; CHECK: %133 = OpConvertUToPtr %_ptr_PhysicalStorageBuffer_blockType %132
+; CHECK: OpBranch %68
+; CHECK: %68 = OpLabel
+; CHECK: %134 = OpPhi %_ptr_PhysicalStorageBuffer_blockType %71 %69 %133 %70
+; CHECK: %26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %134 %int_0
+; CHECK: %135 = OpConvertPtrToU %ulong %26
+; CHECK: %136 = OpFunctionCall %bool %inst_buff_addr_search_and_test %135 %uint_4
+; CHECK: OpSelectionMerge %137 None
+; CHECK: OpBranchConditional %136 %138 %139
+; CHECK: %138 = OpLabel
+; CHECK: OpStore %26 %int_531 Aligned 16
+; CHECK: OpBranch %137
+; CHECK: %139 = OpLabel
+; CHECK: %140 = OpUConvert %uint %135
+; CHECK: %141 = OpShiftRightLogical %ulong %135 %uint_32
+; CHECK: %142 = OpUConvert %uint %141
+; CHECK: %144 = OpFunctionCall %void %inst_buff_addr_stream_write_4 %uint_46 %uint_2 %140 %142
+; CHECK: OpBranch %137
+; CHECK: %137 = OpLabel
 OpReturn
 OpFunctionEnd
 )";
 
-  const std::string func_after =
-      R"(%main = OpFunction %void None %3
-%5 = OpLabel
-%16 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0
-%17 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %16
-%21 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %17 %int_1
-%30 = OpConvertPtrToU %ulong %21
-%67 = OpFunctionCall %bool %32 %30 %uint_8
-OpSelectionMerge %68 None
-OpBranchConditional %67 %69 %70
-%69 = OpLabel
-%71 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8
-OpBranch %68
-%70 = OpLabel
-%72 = OpUConvert %uint %30
-%74 = OpShiftRightLogical %ulong %30 %uint_32
-%75 = OpUConvert %uint %74
-%131 = OpFunctionCall %void %76 %uint_44 %uint_2 %72 %75
-%133 = OpConvertUToPtr %_ptr_PhysicalStorageBuffer_blockType %132
-OpBranch %68
-%68 = OpLabel
-%134 = OpPhi %_ptr_PhysicalStorageBuffer_blockType %71 %69 %133 %70
-%26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %134 %int_0
-%135 = OpConvertPtrToU %ulong %26
-%136 = OpFunctionCall %bool %32 %135 %uint_4
-OpSelectionMerge %137 None
-OpBranchConditional %136 %138 %139
-%138 = OpLabel
-OpStore %26 %int_531 Aligned 16
-OpBranch %137
-%139 = OpLabel
-%140 = OpUConvert %uint %135
-%141 = OpShiftRightLogical %ulong %135 %uint_32
-%142 = OpUConvert %uint %141
-%144 = OpFunctionCall %void %76 %uint_46 %uint_2 %140 %142
-OpBranch %137
-%137 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string new_funcs =
-      R"(%32 = OpFunction %bool None %34
-%35 = OpFunctionParameter %ulong
-%36 = OpFunctionParameter %uint
-%37 = OpLabel
-OpBranch %38
-%38 = OpLabel
-%40 = OpPhi %uint %uint_1 %37 %41 %39
-OpLoopMerge %43 %39 None
-OpBranch %39
-%39 = OpLabel
-%41 = OpIAdd %uint %40 %uint_1
-%50 = OpAccessChain %_ptr_StorageBuffer_ulong %47 %uint_0 %41
-%51 = OpLoad %ulong %50
-%52 = OpUGreaterThan %bool %51 %35
-OpBranchConditional %52 %43 %38
-%43 = OpLabel
-%53 = OpISub %uint %41 %uint_1
-%54 = OpAccessChain %_ptr_StorageBuffer_ulong %47 %uint_0 %53
-%55 = OpLoad %ulong %54
-%56 = OpISub %ulong %35 %55
-%57 = OpUConvert %ulong %36
-%58 = OpIAdd %ulong %56 %57
-%59 = OpAccessChain %_ptr_StorageBuffer_ulong %47 %uint_0 %uint_0
-%60 = OpLoad %ulong %59
-%61 = OpUConvert %uint %60
-%62 = OpISub %uint %53 %uint_1
-%63 = OpIAdd %uint %62 %61
-%64 = OpAccessChain %_ptr_StorageBuffer_ulong %47 %uint_0 %63
-%65 = OpLoad %ulong %64
-%66 = OpULessThanEqual %bool %58 %65
-OpReturnValue %66
-OpFunctionEnd
-%76 = OpFunction %void None %77
-%78 = OpFunctionParameter %uint
-%79 = OpFunctionParameter %uint
-%80 = OpFunctionParameter %uint
-%81 = OpFunctionParameter %uint
-%82 = OpLabel
-%88 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_0
-%91 = OpAtomicIAdd %uint %88 %uint_4 %uint_0 %uint_10
-%92 = OpIAdd %uint %91 %uint_10
-%93 = OpArrayLength %uint %86 1
-%94 = OpULessThanEqual %bool %92 %93
-OpSelectionMerge %95 None
-OpBranchConditional %94 %96 %95
-%96 = OpLabel
-%97 = OpIAdd %uint %91 %uint_0
-%98 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %97
-OpStore %98 %uint_10
-%100 = OpIAdd %uint %91 %uint_1
-%101 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %100
-OpStore %101 %uint_23
-%102 = OpIAdd %uint %91 %uint_2
-%103 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %102
-OpStore %103 %78
-%106 = OpIAdd %uint %91 %uint_3
-%107 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %106
-OpStore %107 %uint_5
-%111 = OpLoad %v3uint %gl_GlobalInvocationID
-%112 = OpCompositeExtract %uint %111 0
-%113 = OpCompositeExtract %uint %111 1
-%114 = OpCompositeExtract %uint %111 2
-%115 = OpIAdd %uint %91 %uint_4
-%116 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %115
-OpStore %116 %112
-%117 = OpIAdd %uint %91 %uint_5
-%118 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %117
-OpStore %118 %113
-%120 = OpIAdd %uint %91 %uint_6
-%121 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %120
-OpStore %121 %114
-%123 = OpIAdd %uint %91 %uint_7
-%124 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %123
-OpStore %124 %79
-%125 = OpIAdd %uint %91 %uint_8
-%126 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %125
-OpStore %126 %80
-%128 = OpIAdd %uint %91 %uint_9
-%129 = OpAccessChain %_ptr_StorageBuffer_uint %86 %uint_1 %128
-OpStore %129 %81
-OpBranch %95
-%95 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
+  const std::string output_funcs = kSearchAndTest + kStreamWrite4Compute;
 
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBuffAddrCheckPass>(
-      defs_before + func_before, defs_after + func_after + new_funcs, true,
-      true, 7u, 23u);
+  SinglePassRunAndMatch<InstBuffAddrCheckPass>(
+      defs + decorates + globals + main_func + output_funcs, true, 7u, 23u);
 }
 
 TEST_F(InstBuffAddrTest, StructLoad) {
@@ -643,7 +466,7 @@
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel PhysicalStorageBuffer64 GLSL450
 OpEntryPoint Fragment %main "main"
-; CHECK: OpEntryPoint Fragment %main "main" %60 %99 %gl_FragCoord
+; CHECK: OpEntryPoint Fragment %main "main" %inst_buff_addr_input_buffer %inst_buff_addr_output_buffer %gl_FragCoord
 OpExecutionMode %main OriginUpperLeft
 OpSource GLSL 450
 OpSourceExtension "GL_ARB_gpu_shader_int64"
@@ -657,27 +480,19 @@
 OpMemberName %TestBuffer 0 "test"
 )";
 
-  const std::string decorates =
-      R"(
+  // clang-format off
+  const std::string decorates = R"(
 OpMemberDecorate %Test_0 0 Offset 0
 OpMemberDecorate %TestBuffer 0 Offset 0
 OpDecorate %TestBuffer Block
 ; CHECK: OpDecorate %_runtimearr_ulong ArrayStride 8
-; CHECK: OpDecorate %_struct_58 Block
-; CHECK: OpMemberDecorate %_struct_58 0 Offset 0
-; CHECK: OpDecorate %60 DescriptorSet 7
-; CHECK: OpDecorate %60 Binding 2
+)" + kInputDecorations + R"(
 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
-; CHECK: OpDecorate %_struct_97 Block
-; CHECK: OpMemberDecorate %_struct_97 0 Offset 0
-; CHECK: OpMemberDecorate %_struct_97 1 Offset 4
-; CHECK: OpDecorate %99 DescriptorSet 7
-; CHECK: OpDecorate %99 Binding 0
+)" + kOutputDecorations + R"(
 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 )";
 
-  const std::string globals =
-      R"(
+  const std::string globals = R"(
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %ulong = OpTypeInt 64 0
@@ -692,15 +507,14 @@
 %_ptr_PhysicalStorageBuffer_Test_0 = OpTypePointer PhysicalStorageBuffer %Test_0
 %ulong_18446744073172680704 = OpConstant %ulong 18446744073172680704
 ; CHECK: %47 = OpTypeFunction %bool %ulong %uint
-; CHECK: %_struct_58 = OpTypeStruct %_runtimearr_ulong
-; CHECK: %60 = OpVariable %_ptr_StorageBuffer__struct_58 StorageBuffer
+)" + kInputGlobals + R"(
 ; CHECK: %90 = OpTypeFunction %void %uint %uint %uint %uint
-; CHECK: %_struct_97 = OpTypeStruct %uint %_runtimearr_uint
-; CHECK: %99 = OpVariable %_ptr_StorageBuffer__struct_97 StorageBuffer
+)" + kOutputGlobals + R"(
 ; CHECK: %143 = OpConstantNull %Test_0
 )";
+  // clang-format on
 
-  const std::string main =
+  const std::string main_func =
       R"(
 %main = OpFunction %void None %3
 %5 = OpLabel
@@ -709,7 +523,7 @@
 %39 = OpLoad %Test_0 %38 Aligned 16
 ; CHECK-NOT: %39 = OpLoad %Test_0 %38 Aligned 16
 ; CHECK: %43 = OpConvertPtrToU %ulong %38
-; CHECK: %80 = OpFunctionCall %bool %45 %43 %uint_4
+; CHECK: %80 = OpFunctionCall %bool %inst_buff_addr_search_and_test %43 %uint_4
 ; CHECK: OpSelectionMerge %81 None
 ; CHECK: OpBranchConditional %80 %82 %83
 ; CHECK: %82 = OpLabel
@@ -719,7 +533,7 @@
 ; CHECK: %85 = OpUConvert %uint %43
 ; CHECK: %87 = OpShiftRightLogical %ulong %43 %uint_32
 ; CHECK: %88 = OpUConvert %uint %87
-; CHECK: %142 = OpFunctionCall %void %89 %uint_37 %uint_2 %85 %88
+; CHECK: %142 = OpFunctionCall %void %inst_buff_addr_stream_write_4 %uint_37 %uint_2 %85 %88
 ; CHECK: OpBranch %81
 ; CHECK: %81 = OpLabel
 ; CHECK: %144 = OpPhi %Test_0 %84 %82 %143 %83
@@ -730,95 +544,12 @@
 OpFunctionEnd
 )";
 
-  const std::string output_funcs =
-      R"(
-; CHECK: %45 = OpFunction %bool None %47
-; CHECK: %48 = OpFunctionParameter %ulong
-; CHECK: %49 = OpFunctionParameter %uint
-; CHECK: %50 = OpLabel
-; CHECK: OpBranch %51
-; CHECK: %51 = OpLabel
-; CHECK: %53 = OpPhi %uint %uint_1 %50 %54 %52
-; CHECK: OpLoopMerge %56 %52 None
-; CHECK: OpBranch %52
-; CHECK: %52 = OpLabel
-; CHECK: %54 = OpIAdd %uint %53 %uint_1
-; CHECK: %63 = OpAccessChain %_ptr_StorageBuffer_ulong %60 %uint_0 %54
-; CHECK: %64 = OpLoad %ulong %63
-; CHECK: %65 = OpUGreaterThan %bool %64 %48
-; CHECK: OpBranchConditional %65 %56 %51
-; CHECK: %56 = OpLabel
-; CHECK: %66 = OpISub %uint %54 %uint_1
-; CHECK: %67 = OpAccessChain %_ptr_StorageBuffer_ulong %60 %uint_0 %66
-; CHECK: %68 = OpLoad %ulong %67
-; CHECK: %69 = OpISub %ulong %48 %68
-; CHECK: %70 = OpUConvert %ulong %49
-; CHECK: %71 = OpIAdd %ulong %69 %70
-; CHECK: %72 = OpAccessChain %_ptr_StorageBuffer_ulong %60 %uint_0 %uint_0
-; CHECK: %73 = OpLoad %ulong %72
-; CHECK: %74 = OpUConvert %uint %73
-; CHECK: %75 = OpISub %uint %66 %uint_1
-; CHECK: %76 = OpIAdd %uint %75 %74
-; CHECK: %77 = OpAccessChain %_ptr_StorageBuffer_ulong %60 %uint_0 %76
-; CHECK: %78 = OpLoad %ulong %77
-; CHECK: %79 = OpULessThanEqual %bool %71 %78
-; CHECK: OpReturnValue %79
-; CHECK: OpFunctionEnd
-; CHECK: %89 = OpFunction %void None %90
-; CHECK: %91 = OpFunctionParameter %uint
-; CHECK: %92 = OpFunctionParameter %uint
-; CHECK: %93 = OpFunctionParameter %uint
-; CHECK: %94 = OpFunctionParameter %uint
-; CHECK: %95 = OpLabel
-; CHECK: %101 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_0
-; CHECK: %103 = OpAtomicIAdd %uint %101 %uint_4 %uint_0 %uint_10
-; CHECK: %104 = OpIAdd %uint %103 %uint_10
-; CHECK: %105 = OpArrayLength %uint %99 1
-; CHECK: %106 = OpULessThanEqual %bool %104 %105
-; CHECK: OpSelectionMerge %107 None
-; CHECK: OpBranchConditional %106 %108 %107
-; CHECK: %108 = OpLabel
-; CHECK: %109 = OpIAdd %uint %103 %uint_0
-; CHECK: %110 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_1 %109
-; CHECK: OpStore %110 %uint_10
-; CHECK: %112 = OpIAdd %uint %103 %uint_1
-; CHECK: %113 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_1 %112
-; CHECK: OpStore %113 %uint_23
-; CHECK: %114 = OpIAdd %uint %103 %uint_2
-; CHECK: %115 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_1 %114
-; CHECK: OpStore %115 %91
-; CHECK: %117 = OpIAdd %uint %103 %uint_3
-; CHECK: %118 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_1 %117
-; CHECK: OpStore %118 %uint_4
-; CHECK: %122 = OpLoad %v4float %gl_FragCoord
-; CHECK: %124 = OpBitcast %v4uint %122
-; CHECK: %125 = OpCompositeExtract %uint %124 0
-; CHECK: %126 = OpIAdd %uint %103 %uint_4
-; CHECK: %127 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_1 %126
-; CHECK: OpStore %127 %125
-; CHECK: %128 = OpCompositeExtract %uint %124 1
-; CHECK: %130 = OpIAdd %uint %103 %uint_5
-; CHECK: %131 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_1 %130
-; CHECK: OpStore %131 %128
-; CHECK: %133 = OpIAdd %uint %103 %uint_7
-; CHECK: %134 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_1 %133
-; CHECK: OpStore %134 %92
-; CHECK: %136 = OpIAdd %uint %103 %uint_8
-; CHECK: %137 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_1 %136
-; CHECK: OpStore %137 %93
-; CHECK: %139 = OpIAdd %uint %103 %uint_9
-; CHECK: %140 = OpAccessChain %_ptr_StorageBuffer_uint %99 %uint_1 %139
-; CHECK: OpStore %140 %94
-; CHECK: OpBranch %107
-; CHECK: %107 = OpLabel
-; CHECK: OpReturn
-; CHECK: OpFunctionEnd
-)";
+  const std::string output_funcs = kSearchAndTest + kStreamWrite4Frag;
 
   SetTargetEnv(SPV_ENV_VULKAN_1_2);
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<InstBuffAddrCheckPass>(
-      defs + decorates + globals + main + output_funcs, true);
+      defs + decorates + globals + main_func + output_funcs, true);
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/opt/inst_debug_printf_test.cpp b/third_party/SPIRV-Tools/test/opt/inst_debug_printf_test.cpp
index c5fd679..6a4cbdd 100644
--- a/third_party/SPIRV-Tools/test/opt/inst_debug_printf_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/inst_debug_printf_test.cpp
@@ -1,5 +1,5 @@
-// Copyright (c) 2020 Valve Corporation
-// Copyright (c) 2020 LunarG Inc.
+// Copyright (c) 2020-2022 Valve Corporation
+// Copyright (c) 2020-2022 LunarG Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -26,6 +26,21 @@
 namespace opt {
 namespace {
 
+static const std::string kOutputDecorations = R"(
+; CHECK: OpDecorate [[output_buffer_type:%inst_printf_OutputBuffer]] Block
+; CHECK: OpMemberDecorate [[output_buffer_type]] 0 Offset 0
+; CHECK: OpMemberDecorate [[output_buffer_type]] 1 Offset 4
+; CHECK: OpMemberDecorate [[output_buffer_type]] 2 Offset 8
+; CHECK: OpDecorate [[output_buffer_var:%\w+]] DescriptorSet 7
+; CHECK: OpDecorate [[output_buffer_var]] Binding 3
+)";
+
+static const std::string kOutputGlobals = R"(
+; CHECK: [[output_buffer_type]] = OpTypeStruct %uint %uint %_runtimearr_uint
+; CHECK: [[output_ptr_type:%\w+]] = OpTypePointer StorageBuffer [[output_buffer_type]]
+; CHECK: [[output_buffer_var]] = OpVariable [[output_ptr_type]] StorageBuffer
+)";
+
 using InstDebugPrintfTest = PassTest<::testing::Test>;
 
 TEST_F(InstDebugPrintfTest, V4Float32) {
@@ -65,6 +80,7 @@
 %5 = OpString "Color is %vn"
 )";
 
+  // clang-format off
   const std::string decorates =
       R"(OpDecorate %6 DescriptorSet 0
 OpDecorate %6 Binding 1
@@ -73,11 +89,7 @@
 OpDecorate %3 Location 0
 OpDecorate %4 Location 0
 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
-; CHECK: OpDecorate %_struct_47 Block
-; CHECK: OpMemberDecorate %_struct_47 0 Offset 0
-; CHECK: OpMemberDecorate %_struct_47 1 Offset 4
-; CHECK: OpDecorate %49 DescriptorSet 7
-; CHECK: OpDecorate %49 Binding 3
+)" + kOutputDecorations + R"(
 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
 )";
 
@@ -101,15 +113,14 @@
 ; CHECK: %uint = OpTypeInt 32 0
 ; CHECK: %38 = OpTypeFunction %void %uint %uint %uint %uint %uint %uint
 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
-; CHECK: %_struct_47 = OpTypeStruct %uint %_runtimearr_uint
-; CHECK: %_ptr_StorageBuffer__struct_47 = OpTypePointer StorageBuffer %_struct_47
-; CHECK: %49 = OpVariable %_ptr_StorageBuffer__struct_47 StorageBuffer
+)" + kOutputGlobals + R"(
 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ; CHECK: %bool = OpTypeBool
 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
 ; CHECK: %v4uint = OpTypeVector %uint 4
 )";
+  // clang-format on
 
   const std::string main =
       R"(%2 = OpFunction %void None %9
@@ -129,7 +140,7 @@
 ; CHECK: %34 = OpBitcast %uint %33
 ; CHECK: %35 = OpCompositeExtract %float %25 3
 ; CHECK: %36 = OpBitcast %uint %35
-; CHECK: %101 = OpFunctionCall %void %37 %uint_36 %uint_5 %30 %32 %34 %36
+; CHECK: %101 = OpFunctionCall %void %inst_printf_stream_write_6 %uint_36 %uint_5 %30 %32 %34 %36
 ; CHECK: OpBranch %102
 ; CHECK: %102 = OpLabel
 OpStore %4 %25
@@ -137,62 +148,62 @@
 OpFunctionEnd
 )";
 
-  const std::string output_func =
-      R"(; CHECK: %37 = OpFunction %void None %38
-; CHECK: %39 = OpFunctionParameter %uint
-; CHECK: %40 = OpFunctionParameter %uint
-; CHECK: %41 = OpFunctionParameter %uint
-; CHECK: %42 = OpFunctionParameter %uint
-; CHECK: %43 = OpFunctionParameter %uint
-; CHECK: %44 = OpFunctionParameter %uint
-; CHECK: %45 = OpLabel
-; CHECK: %52 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_0
-; CHECK: %55 = OpAtomicIAdd %uint %52 %uint_4 %uint_0 %uint_12
-; CHECK: %56 = OpIAdd %uint %55 %uint_12
-; CHECK: %57 = OpArrayLength %uint %49 1
-; CHECK: %59 = OpULessThanEqual %bool %56 %57
-; CHECK: OpSelectionMerge %60 None
-; CHECK: OpBranchConditional %59 %61 %60
-; CHECK: %61 = OpLabel
-; CHECK: %62 = OpIAdd %uint %55 %uint_0
-; CHECK: %64 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %62
-; CHECK: OpStore %64 %uint_12
-; CHECK: %66 = OpIAdd %uint %55 %uint_1
-; CHECK: %67 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %66
-; CHECK: OpStore %67 %uint_23
-; CHECK: %69 = OpIAdd %uint %55 %uint_2
-; CHECK: %70 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %69
-; CHECK: OpStore %70 %39
-; CHECK: %72 = OpIAdd %uint %55 %uint_3
-; CHECK: %73 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %72
-; CHECK: OpStore %73 %uint_4
-; CHECK: %76 = OpLoad %v4float %gl_FragCoord
-; CHECK: %78 = OpBitcast %v4uint %76
-; CHECK: %79 = OpCompositeExtract %uint %78 0
-; CHECK: %80 = OpIAdd %uint %55 %uint_4
-; CHECK: %81 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %80
-; CHECK: OpStore %81 %79
-; CHECK: %82 = OpCompositeExtract %uint %78 1
-; CHECK: %83 = OpIAdd %uint %55 %uint_5
-; CHECK: %84 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %83
-; CHECK: OpStore %84 %82
-; CHECK: %86 = OpIAdd %uint %55 %uint_7
-; CHECK: %87 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %86
-; CHECK: OpStore %87 %40
-; CHECK: %89 = OpIAdd %uint %55 %uint_8
-; CHECK: %90 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %89
-; CHECK: OpStore %90 %41
-; CHECK: %92 = OpIAdd %uint %55 %uint_9
-; CHECK: %93 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %92
-; CHECK: OpStore %93 %42
-; CHECK: %95 = OpIAdd %uint %55 %uint_10
-; CHECK: %96 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %95
-; CHECK: OpStore %96 %43
-; CHECK: %98 = OpIAdd %uint %55 %uint_11
-; CHECK: %99 = OpAccessChain %_ptr_StorageBuffer_uint %49 %uint_1 %98
-; CHECK: OpStore %99 %44
-; CHECK: OpBranch %60
-; CHECK: %60 = OpLabel
+  const std::string output_func = R"(
+; CHECK: %inst_printf_stream_write_6 = OpFunction %void None %38
+; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_4:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_5:%\w+]] = OpFunctionParameter %uint
+; CHECK: [[param_6:%\w+]] = OpFunctionParameter %uint
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_1
+; CHECK: {{%\w+}} = OpAtomicIAdd %uint {{%\w+}} %uint_4 %uint_0 %uint_12
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_12
+; CHECK: {{%\w+}} = OpArrayLength %uint %inst_printf_output_buffer 2
+; CHECK: {{%\w+}} = OpULessThanEqual %bool {{%\w+}} {{%\w+}}
+; CHECK: OpSelectionMerge {{%\w+}} None
+; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_0
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_12
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_1
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_23
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_2
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_1]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord
+; CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} {{%\w+}}
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_2]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_8
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_3]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_9
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_4]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_10
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_5]]
+; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_11
+; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
+; CHECK: OpStore {{%\w+}} [[param_6]]
+; CHECK: OpBranch {{%\w+}}
+; CHECK: {{%\w+}} = OpLabel
 ; CHECK: OpReturn
 ; CHECK: OpFunctionEnd
 )";
diff --git a/third_party/SPIRV-Tools/test/opt/instruction_test.cpp b/third_party/SPIRV-Tools/test/opt/instruction_test.cpp
index dd749ab..6ea7fcc 100644
--- a/third_party/SPIRV-Tools/test/opt/instruction_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/instruction_test.cpp
@@ -39,7 +39,7 @@
 
 TEST(InstructionTest, CreateTrivial) {
   Instruction empty;
-  EXPECT_EQ(SpvOpNop, empty.opcode());
+  EXPECT_EQ(spv::Op::OpNop, empty.opcode());
   EXPECT_EQ(0u, empty.type_id());
   EXPECT_EQ(0u, empty.result_id());
   EXPECT_EQ(0u, empty.NumOperands());
@@ -51,8 +51,8 @@
 
 TEST(InstructionTest, CreateWithOpcodeAndNoOperands) {
   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
-  Instruction inst(&context, SpvOpReturn);
-  EXPECT_EQ(SpvOpReturn, inst.opcode());
+  Instruction inst(&context, spv::Op::OpReturn);
+  EXPECT_EQ(spv::Op::OpReturn, inst.opcode());
   EXPECT_EQ(0u, inst.type_id());
   EXPECT_EQ(0u, inst.result_id());
   EXPECT_EQ(0u, inst.NumOperands());
@@ -81,8 +81,8 @@
 }
 
 // The words for an OpTypeInt for 32-bit signed integer resulting in Id 44.
-uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(SpvOpTypeInt), 44,
-                                      32, 1};
+uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(spv::Op::OpTypeInt),
+                                      44, 32, 1};
 // The operands that would be parsed from kSampleInstructionWords
 spv_parsed_operand_t kSampleParsedOperands[] = {
     {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
@@ -91,18 +91,19 @@
 };
 
 // A valid parse of kSampleParsedOperands.
-spv_parsed_instruction_t kSampleParsedInstruction = {kSampleInstructionWords,
-                                                     uint16_t(4),
-                                                     uint16_t(SpvOpTypeInt),
-                                                     SPV_EXT_INST_TYPE_NONE,
-                                                     0,   // type id
-                                                     44,  // result id
-                                                     kSampleParsedOperands,
-                                                     3};
+spv_parsed_instruction_t kSampleParsedInstruction = {
+    kSampleInstructionWords,
+    uint16_t(4),
+    uint16_t(spv::Op::OpTypeInt),
+    SPV_EXT_INST_TYPE_NONE,
+    0,   // type id
+    44,  // result id
+    kSampleParsedOperands,
+    3};
 
 // The words for an OpAccessChain instruction.
 uint32_t kSampleAccessChainInstructionWords[] = {
-    (7 << 16) | uint32_t(SpvOpAccessChain), 100, 101, 102, 103, 104, 105};
+    (7 << 16) | uint32_t(spv::Op::OpAccessChain), 100, 101, 102, 103, 104, 105};
 
 // The operands that would be parsed from kSampleAccessChainInstructionWords.
 spv_parsed_operand_t kSampleAccessChainOperands[] = {
@@ -118,7 +119,7 @@
 spv_parsed_instruction_t kSampleAccessChainInstruction = {
     kSampleAccessChainInstructionWords,
     uint16_t(7),
-    uint16_t(SpvOpAccessChain),
+    uint16_t(spv::Op::OpAccessChain),
     SPV_EXT_INST_TYPE_NONE,
     100,  // type id
     101,  // result id
@@ -127,7 +128,7 @@
 
 // The words for an OpControlBarrier instruction.
 uint32_t kSampleControlBarrierInstructionWords[] = {
-    (4 << 16) | uint32_t(SpvOpControlBarrier), 100, 101, 102};
+    (4 << 16) | uint32_t(spv::Op::OpControlBarrier), 100, 101, 102};
 
 // The operands that would be parsed from kSampleControlBarrierInstructionWords.
 spv_parsed_operand_t kSampleControlBarrierOperands[] = {
@@ -141,7 +142,7 @@
 spv_parsed_instruction_t kSampleControlBarrierInstruction = {
     kSampleControlBarrierInstructionWords,
     uint16_t(4),
-    uint16_t(SpvOpControlBarrier),
+    uint16_t(spv::Op::OpControlBarrier),
     SPV_EXT_INST_TYPE_NONE,
     0,  // type id
     0,  // result id
@@ -151,7 +152,7 @@
 TEST(InstructionTest, CreateWithOpcodeAndOperands) {
   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
   Instruction inst(&context, kSampleParsedInstruction);
-  EXPECT_EQ(SpvOpTypeInt, inst.opcode());
+  EXPECT_EQ(spv::Op::OpTypeInt, inst.opcode());
   EXPECT_EQ(0u, inst.type_id());
   EXPECT_EQ(44u, inst.result_id());
   EXPECT_EQ(3u, inst.NumOperands());
diff --git a/third_party/SPIRV-Tools/test/opt/ir_builder.cpp b/third_party/SPIRV-Tools/test/opt/ir_builder.cpp
index cb234e0..e04e781 100644
--- a/third_party/SPIRV-Tools/test/opt/ir_builder.cpp
+++ b/third_party/SPIRV-Tools/test/opt/ir_builder.cpp
@@ -201,7 +201,7 @@
     // TODO(1841): Handle id overflow.
     fn.begin().InsertBefore(std::unique_ptr<BasicBlock>(
         new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
-            context.get(), SpvOpLabel, 0, context->TakeNextId(), {})))));
+            context.get(), spv::Op::OpLabel, 0, context->TakeNextId(), {})))));
     BasicBlock& bb_true = *fn.begin();
     {
       InstructionBuilder builder(context.get(), &*bb_true.begin());
@@ -211,7 +211,7 @@
     // TODO(1841): Handle id overflow.
     fn.begin().InsertBefore(std::unique_ptr<BasicBlock>(
         new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
-            context.get(), SpvOpLabel, 0, context->TakeNextId(), {})))));
+            context.get(), spv::Op::OpLabel, 0, context->TakeNextId(), {})))));
     BasicBlock& bb_cond = *fn.begin();
 
     InstructionBuilder builder(context.get(), &bb_cond);
diff --git a/third_party/SPIRV-Tools/test/opt/ir_context_test.cpp b/third_party/SPIRV-Tools/test/opt/ir_context_test.cpp
index ece0479..86a3f45 100644
--- a/third_party/SPIRV-Tools/test/opt/ir_context_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/ir_context_test.cpp
@@ -229,12 +229,12 @@
 
   // Make sure all of the name are removed.
   for (auto& inst : context->debugs2()) {
-    EXPECT_EQ(inst.opcode(), SpvOpNop);
+    EXPECT_EQ(inst.opcode(), spv::Op::OpNop);
   }
 
   // Make sure all of the decorations are removed.
   for (auto& inst : context->annotations()) {
-    EXPECT_EQ(inst.opcode(), SpvOpNop);
+    EXPECT_EQ(inst.opcode(), spv::Op::OpNop);
   }
 }
 
@@ -276,17 +276,17 @@
 
   // Check the OpDecorate instruction
   auto inst = context->annotation_begin();
-  EXPECT_EQ(inst->opcode(), SpvOpDecorate);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpDecorate);
   EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
 
   // Check the OpDecorationGroup Instruction
   ++inst;
-  EXPECT_EQ(inst->opcode(), SpvOpDecorationGroup);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpDecorationGroup);
   EXPECT_EQ(inst->result_id(), 3);
 
   // Check that %5 is no longer part of the group.
   ++inst;
-  EXPECT_EQ(inst->opcode(), SpvOpGroupDecorate);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpGroupDecorate);
   EXPECT_EQ(inst->NumInOperands(), 2);
   EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
   EXPECT_EQ(inst->GetSingleWordInOperand(1), 4);
@@ -340,12 +340,12 @@
 
   // Check the OpDecorationGroup Instruction
   auto inst = context->annotation_begin();
-  EXPECT_EQ(inst->opcode(), SpvOpDecorationGroup);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpDecorationGroup);
   EXPECT_EQ(inst->result_id(), 3);
 
   // Check that %5 is no longer part of the group.
   ++inst;
-  EXPECT_EQ(inst->opcode(), SpvOpGroupDecorate);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpGroupDecorate);
   EXPECT_EQ(inst->NumInOperands(), 2);
   EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
   EXPECT_EQ(inst->GetSingleWordInOperand(1), 4);
@@ -1147,40 +1147,6 @@
   dbg_decl = ctx->get_def_use_mgr()->GetDef(25);
   EXPECT_EQ(dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex),
             20);
-
-  // No DebugValue should be added because result id '26' is not used for
-  // DebugDeclare.
-  ctx->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(dbg_decl, 26, 22,
-                                                             dbg_decl, nullptr);
-  EXPECT_EQ(dbg_decl->NextNode()->opcode(), SpvOpReturn);
-
-  // DebugValue should be added because result id '20' is used for DebugDeclare.
-  ctx->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(dbg_decl, 20, 22,
-                                                             dbg_decl, nullptr);
-  EXPECT_EQ(dbg_decl->NextNode()->GetOpenCL100DebugOpcode(),
-            OpenCLDebugInfo100DebugValue);
-
-  // Replace all uses of result it '20' with '26'
-  EXPECT_EQ(dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex),
-            20);
-  EXPECT_TRUE(ctx->ReplaceAllUsesWith(20, 26));
-  EXPECT_EQ(dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex),
-            26);
-
-  // No DebugValue should be added because result id '20' is not used for
-  // DebugDeclare.
-  ctx->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(dbg_decl, 20, 7,
-                                                             dbg_decl, nullptr);
-  Instruction* dbg_value = dbg_decl->NextNode();
-  EXPECT_EQ(dbg_value->GetOpenCL100DebugOpcode(), OpenCLDebugInfo100DebugValue);
-  EXPECT_EQ(dbg_value->GetSingleWordOperand(kDebugValueOperandValueIndex), 22);
-
-  // DebugValue should be added because result id '26' is used for DebugDeclare.
-  ctx->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(dbg_decl, 26, 7,
-                                                             dbg_decl, nullptr);
-  dbg_value = dbg_decl->NextNode();
-  EXPECT_EQ(dbg_value->GetOpenCL100DebugOpcode(), OpenCLDebugInfo100DebugValue);
-  EXPECT_EQ(dbg_value->GetSingleWordOperand(kDebugValueOperandValueIndex), 7);
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/opt/ir_loader_test.cpp b/third_party/SPIRV-Tools/test/opt/ir_loader_test.cpp
index ccdd032..45104f4 100644
--- a/third_party/SPIRV-Tools/test/opt/ir_loader_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/ir_loader_test.cpp
@@ -244,10 +244,10 @@
     auto& lines = def_use_mgr->GetDef(check.id)->dbg_line_insts();
     for (uint32_t i = 0; i < check.line_numbers.size(); ++i) {
       if (check.line_numbers[i] == kNoLine) {
-        EXPECT_EQ(lines[i].opcode(), SpvOpNoLine);
+        EXPECT_EQ(lines[i].opcode(), spv::Op::OpNoLine);
         continue;
       }
-      EXPECT_EQ(lines[i].opcode(), SpvOpLine);
+      EXPECT_EQ(lines[i].opcode(), spv::Op::OpLine);
       EXPECT_EQ(lines[i].GetSingleWordOperand(kOpLineOperandLineIndex),
                 check.line_numbers[i]);
     }
@@ -286,9 +286,10 @@
   spvtools::opt::analysis::DefUseManager* def_use_mgr =
       context->get_def_use_mgr();
 
-  std::vector<SpvOp> opcodes;
+  std::vector<spv::Op> opcodes;
   for (auto* inst = def_use_mgr->GetDef(1);
-       inst && (inst->opcode() != SpvOpFunctionEnd); inst = inst->NextNode()) {
+       inst && (inst->opcode() != spv::Op::OpFunctionEnd);
+       inst = inst->NextNode()) {
     inst->ForEachInst(
         [&opcodes](spvtools::opt::Instruction* sub_inst) {
           opcodes.push_back(sub_inst->opcode());
@@ -296,9 +297,9 @@
         true);
   }
 
-  EXPECT_THAT(opcodes,
-              ContainerEq(std::vector<SpvOp>{SpvOpFAdd, SpvOpLine, SpvOpFMul,
-                                             SpvOpFSub, SpvOpReturn}));
+  EXPECT_THAT(opcodes, ContainerEq(std::vector<spv::Op>{
+                           spv::Op::OpFAdd, spv::Op::OpLine, spv::Op::OpFMul,
+                           spv::Op::OpFSub, spv::Op::OpReturn}));
 }
 
 TEST(IrBuilder, BuildModule_WithExtraLines_IsDefault) {
@@ -333,9 +334,10 @@
   spvtools::opt::analysis::DefUseManager* def_use_mgr =
       context->get_def_use_mgr();
 
-  std::vector<SpvOp> opcodes;
+  std::vector<spv::Op> opcodes;
   for (auto* inst = def_use_mgr->GetDef(1);
-       inst && (inst->opcode() != SpvOpFunctionEnd); inst = inst->NextNode()) {
+       inst && (inst->opcode() != spv::Op::OpFunctionEnd);
+       inst = inst->NextNode()) {
     inst->ForEachInst(
         [&opcodes](spvtools::opt::Instruction* sub_inst) {
           opcodes.push_back(sub_inst->opcode());
@@ -343,9 +345,10 @@
         true);
   }
 
-  EXPECT_THAT(opcodes, ContainerEq(std::vector<SpvOp>{
-                           SpvOpFAdd, SpvOpLine, SpvOpFMul, SpvOpLine,
-                           SpvOpFSub, SpvOpLine, SpvOpReturn}));
+  EXPECT_THAT(opcodes, ContainerEq(std::vector<spv::Op>{
+                           spv::Op::OpFAdd, spv::Op::OpLine, spv::Op::OpFMul,
+                           spv::Op::OpLine, spv::Op::OpFSub, spv::Op::OpLine,
+                           spv::Op::OpReturn}));
 }
 
 TEST(IrBuilder, ConsumeDebugInfoInst) {
@@ -1297,8 +1300,9 @@
 
   const auto opundef_count = std::count_if(
       context->module()->types_values_begin(),
-      context->module()->types_values_end(),
-      [](const Instruction& inst) { return inst.opcode() == SpvOpUndef; });
+      context->module()->types_values_end(), [](const Instruction& inst) {
+        return inst.opcode() == spv::Op::OpUndef;
+      });
   EXPECT_EQ(3, opundef_count);
 
   std::vector<uint32_t> binary;
diff --git a/third_party/SPIRV-Tools/test/opt/local_access_chain_convert_test.cpp b/third_party/SPIRV-Tools/test/opt/local_access_chain_convert_test.cpp
index 6f5021c..07fb537 100644
--- a/third_party/SPIRV-Tools/test/opt/local_access_chain_convert_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/local_access_chain_convert_test.cpp
@@ -1316,6 +1316,38 @@
   SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
                                                      true);
 }
+
+TEST_F(LocalAccessChainConvertTest, NegativeIndex) {
+  // The access chain has a negative index and should not be converted because
+  // the extract instruction cannot hold a negative number.
+  const std::string assembly =
+      R"(OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %2 "main"
+OpExecutionMode %2 OriginUpperLeft
+%void = OpTypeVoid
+%4 = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%uint = OpTypeInt 32 0
+%uint_3808428041 = OpConstant %uint 3808428041
+%_arr_int_uint_3808428041 = OpTypeArray %int %uint_3808428041
+%_ptr_Function__arr_int_uint_3808428041 = OpTypePointer Function %_arr_int_uint_3808428041
+%_ptr_Function_int = OpTypePointer Function %int
+%int_n1272971256 = OpConstant %int -1272971256
+%2 = OpFunction %void None %4
+%12 = OpLabel
+%13 = OpVariable %_ptr_Function__arr_int_uint_3808428041 Function
+%14 = OpAccessChain %_ptr_Function_int %13 %int_n1272971256
+%15 = OpLoad %int %14
+OpReturn
+OpFunctionEnd
+)";
+
+  SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
+                                                     true);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //    Assorted vector and matrix types
diff --git a/third_party/SPIRV-Tools/test/opt/local_single_store_elim_test.cpp b/third_party/SPIRV-Tools/test/opt/local_single_store_elim_test.cpp
index 5d910c4..8f43a11 100644
--- a/third_party/SPIRV-Tools/test/opt/local_single_store_elim_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/local_single_store_elim_test.cpp
@@ -1494,19 +1494,19 @@
          %56 = OpLoad %v4float %in_var_COLOR
 ;CHECK:      DebugNoScope
 ;CHECK-NOT:  OpLine
-;CHECK:      [[pos:%\w+]] = OpLoad %v4float %in_var_POSITION
-;CHECK:      [[color:%\w+]] = OpLoad %v4float %in_var_COLOR
-
                OpLine %7 7 23
                OpStore %param_var_color %56
                OpNoLine
          %93 = OpExtInst %void %1 DebugScope %48
          %73 = OpExtInst %void %1 DebugDeclare %53 %param_var_pos %52
          %74 = OpExtInst %void %1 DebugDeclare %51 %param_var_color %52
+;CHECK:      [[pos:%\w+]] = OpLoad %v4float %in_var_POSITION
 ;CHECK:      OpLine [[file:%\w+]] 6 23
-;CHECK-NEXT: {{%\w+}} = OpExtInst %void {{%\w+}} DebugValue [[dbg_pos]] [[pos]] [[empty_expr:%\w+]]
+;CHECK:      {{%\w+}} = OpExtInst %void {{%\w+}} DebugValue [[dbg_pos]] [[pos]] [[empty_expr:%\w+]]
+;CHECK:      [[color:%\w+]] = OpLoad %v4float %in_var_COLOR
 ;CHECK:      OpLine [[file]] 7 23
-;CHECK-NEXT: {{%\w+}} = OpExtInst %void {{%\w+}} DebugValue [[dbg_color]] [[color]] [[empty_expr]]
+;CHECK:      {{%\w+}} = OpExtInst %void {{%\w+}} DebugValue [[dbg_color]] [[color]] [[empty_expr]]
+;CHECK:      OpLine [[file]] 9 3
 
          %94 = OpExtInst %void %1 DebugScope %49
                OpLine %7 9 3
@@ -1529,6 +1529,227 @@
   SinglePassRunAndMatch<LocalSingleStoreElimPass>(text, false);
 }
 
+TEST_F(LocalSingleStoreElimTest, DebugValuesForAllLocalsAndParams) {
+  // Texture2D g_tColor;
+  //
+  // SamplerState g_sAniso;
+  //
+  // struct PS_INPUT
+  // {
+  //     float2 vTextureCoords : TEXCOORD2 ;
+  // } ;
+  //
+  // struct PS_OUTPUT
+  // {
+  //     float4 vColor : SV_Target0 ;
+  // } ;
+  //
+  // void do_sample ( in float2 tc, out float4 c ) {
+  //     c = g_tColor . Sample ( g_sAniso , tc ) ;
+  // }
+  //
+  // PS_OUTPUT MainPs ( PS_INPUT i )
+  // {
+  //     PS_OUTPUT ps_output ;
+  //     float4 color;
+  //
+  //     do_sample ( i . vTextureCoords . xy , color ) ;
+  //     ps_output . vColor = color;
+  //     return ps_output ;
+  // }
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "OpenCL.DebugInfo.100"
+;CHECK:      [[set:%\w+]] = OpExtInstImport "OpenCL.DebugInfo.100"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %MainPs "MainPs" %in_var_TEXCOORD2 %out_var_SV_Target0 %g_tColor %g_sAniso
+               OpExecutionMode %MainPs OriginUpperLeft
+          %7 = OpString "foo2.frag"
+         %21 = OpString "float"
+         %27 = OpString "PS_INPUT"
+         %31 = OpString "vTextureCoords"
+         %34 = OpString "PS_OUTPUT"
+         %38 = OpString "vColor"
+         %40 = OpString "do_sample"
+         %41 = OpString ""
+         %45 = OpString "c"
+         %47 = OpString "tc"
+         %50 = OpString "MainPs"
+         %54 = OpString "color"
+         %56 = OpString "ps_output"
+         %59 = OpString "i"
+         %62 = OpString "@type.sampler"
+         %63 = OpString "type.sampler"
+         %65 = OpString "g_sAniso"
+         %67 = OpString "@type.2d.image"
+         %68 = OpString "type.2d.image"
+         %70 = OpString "TemplateParam"
+         %73 = OpString "g_tColor"
+;CHECK:      [[str_c:%\w+]] = OpString "c"
+;CHECK:      [[str_tc:%\w+]] = OpString "tc"
+;CHECK:      [[str_color:%\w+]] = OpString "color"
+;CHECK:      [[str_ps_output:%\w+]] = OpString "ps_output"
+;CHECK:      [[str_i:%\w+]] = OpString "i"
+               OpName %type_2d_image "type.2d.image"
+               OpName %g_tColor "g_tColor"
+               OpName %type_sampler "type.sampler"
+               OpName %g_sAniso "g_sAniso"
+               OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
+               OpName %out_var_SV_Target0 "out.var.SV_Target0"
+               OpName %MainPs "MainPs"
+               OpName %PS_INPUT "PS_INPUT"
+               OpMemberName %PS_INPUT 0 "vTextureCoords"
+               OpName %PS_OUTPUT "PS_OUTPUT"
+               OpMemberName %PS_OUTPUT 0 "vColor"
+               OpName %type_sampled_image "type.sampled.image"
+               OpDecorate %in_var_TEXCOORD2 Location 0
+               OpDecorate %out_var_SV_Target0 Location 0
+               OpDecorate %g_tColor DescriptorSet 0
+               OpDecorate %g_tColor Binding 0
+               OpDecorate %g_sAniso DescriptorSet 0
+               OpDecorate %g_sAniso Binding 1
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+       %uint = OpTypeInt 32 0
+    %uint_32 = OpConstant %uint 32
+      %float = OpTypeFloat 32
+%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
+%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
+%type_sampler = OpTypeSampler
+%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
+    %v2float = OpTypeVector %float 2
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+       %void = OpTypeVoid
+    %uint_64 = OpConstant %uint 64
+     %uint_0 = OpConstant %uint 0
+   %uint_128 = OpConstant %uint 128
+         %75 = OpTypeFunction %void
+   %PS_INPUT = OpTypeStruct %v2float
+%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
+  %PS_OUTPUT = OpTypeStruct %v4float
+         %85 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
+%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+        %105 = OpTypeFunction %void %_ptr_Function_v2float %_ptr_Function_v4float
+%type_sampled_image = OpTypeSampledImage %type_2d_image
+   %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
+   %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
+%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
+        %145 = OpExtInst %void %1 DebugOperation Deref
+         %61 = OpExtInst %void %1 DebugInfoNone
+         %58 = OpExtInst %void %1 DebugExpression
+         %23 = OpExtInst %void %1 DebugTypeBasic %21 %uint_32 Float
+         %24 = OpExtInst %void %1 DebugTypeVector %23 2
+         %25 = OpExtInst %void %1 DebugSource %7
+         %26 = OpExtInst %void %1 DebugCompilationUnit 1 4 %25 HLSL
+         %29 = OpExtInst %void %1 DebugTypeComposite %27 Structure %25 5 8 %26 %27 %uint_64 FlagIsProtected|FlagIsPrivate %30
+         %30 = OpExtInst %void %1 DebugTypeMember %31 %24 %25 7 12 %29 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
+         %33 = OpExtInst %void %1 DebugTypeVector %23 4
+         %36 = OpExtInst %void %1 DebugTypeComposite %34 Structure %25 10 8 %26 %34 %uint_128 FlagIsProtected|FlagIsPrivate %37
+         %37 = OpExtInst %void %1 DebugTypeMember %38 %33 %25 12 12 %36 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
+         %39 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %void %24 %33
+         %42 = OpExtInst %void %1 DebugFunction %40 %39 %25 15 1 %26 %41 FlagIsProtected|FlagIsPrivate 15 %61
+         %44 = OpExtInst %void %1 DebugLexicalBlock %25 15 47 %42
+         %46 = OpExtInst %void %1 DebugLocalVariable %45 %33 %25 15 43 %42 FlagIsLocal 2
+         %48 = OpExtInst %void %1 DebugLocalVariable %47 %24 %25 15 28 %42 FlagIsLocal 1
+         %49 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %36 %29
+         %51 = OpExtInst %void %1 DebugFunction %50 %49 %25 19 1 %26 %41 FlagIsProtected|FlagIsPrivate 20 %61
+         %53 = OpExtInst %void %1 DebugLexicalBlock %25 20 1 %51
+         %55 = OpExtInst %void %1 DebugLocalVariable %54 %33 %25 22 12 %53 FlagIsLocal
+         %57 = OpExtInst %void %1 DebugLocalVariable %56 %36 %25 21 15 %53 FlagIsLocal
+         %60 = OpExtInst %void %1 DebugLocalVariable %59 %29 %25 19 29 %51 FlagIsLocal 1
+         %64 = OpExtInst %void %1 DebugTypeComposite %62 Structure %25 0 0 %26 %63 %61 FlagIsProtected|FlagIsPrivate
+         %66 = OpExtInst %void %1 DebugGlobalVariable %65 %64 %25 3 14 %26 %65 %g_sAniso FlagIsDefinition
+         %69 = OpExtInst %void %1 DebugTypeComposite %67 Class %25 0 0 %26 %68 %61 FlagIsProtected|FlagIsPrivate
+         %71 = OpExtInst %void %1 DebugTypeTemplateParameter %70 %33 %61 %25 0 0
+         %72 = OpExtInst %void %1 DebugTypeTemplate %69 %71
+         %74 = OpExtInst %void %1 DebugGlobalVariable %73 %72 %25 1 11 %26 %73 %g_tColor FlagIsDefinition
+        %142 = OpExtInst %void %1 DebugInlinedAt 24 %53
+        %144 = OpExtInst %void %1 DebugExpression %145
+        %155 = OpExtInst %void %1 DebugExpression %145
+;CHECK:      [[var_c:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_c]]
+;CHECK:      [[var_tc:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_tc]]
+;CHECK:      [[var_color:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_color]]
+;CHECK:      [[var_ps_output:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_ps_output]]
+;CHECK:      [[var_i:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_i]]
+     %MainPs = OpFunction %void None %75
+         %76 = OpLabel
+        %153 = OpVariable %_ptr_Function_v2float Function
+        %149 = OpVariable %_ptr_Function_v4float Function
+        %157 = OpExtInst %void %1 DebugScope %53
+        %143 = OpVariable %_ptr_Function_v4float Function
+        %121 = OpVariable %_ptr_Function_v4float Function
+        %122 = OpVariable %_ptr_Function_v2float Function
+        %158 = OpExtInst %void %1 DebugScope %51
+               OpLine %7 19 29
+        %156 = OpExtInst %void %1 DebugValue %60 %153 %155 %int_0
+        %159 = OpExtInst %void %1 DebugScope %53
+               OpLine %7 21 15
+        %146 = OpExtInst %void %1 DebugValue %57 %143 %144 %int_0
+               OpNoLine
+        %160 = OpExtInst %void %1 DebugNoScope
+         %80 = OpLoad %v2float %in_var_TEXCOORD2
+         %81 = OpCompositeConstruct %PS_INPUT %80
+        %154 = OpCompositeExtract %v2float %81 0
+               OpStore %153 %154
+        %161 = OpExtInst %void %1 DebugScope %53
+               OpLine %7 22 12
+        %127 = OpExtInst %void %1 DebugDeclare %55 %121 %58
+               OpLine %7 24 17
+        %129 = OpLoad %v2float %153
+               OpStore %122 %129
+        %162 = OpExtInst %void %1 DebugScope %42 %142
+               OpLine %7 15 28
+        %135 = OpExtInst %void %1 DebugDeclare %48 %122 %58
+               OpLine %7 15 43
+        %136 = OpExtInst %void %1 DebugDeclare %46 %121 %58
+        %163 = OpExtInst %void %1 DebugScope %44 %142
+               OpLine %7 16 9
+        %137 = OpLoad %type_2d_image %g_tColor
+               OpLine %7 16 29
+        %138 = OpLoad %type_sampler %g_sAniso
+               OpLine %7 16 40
+        %139 = OpLoad %v2float %122
+               OpLine %7 16 9
+        %140 = OpSampledImage %type_sampled_image %137 %138
+        %141 = OpImageSampleImplicitLod %v4float %140 %139 None
+               OpLine %7 16 5
+               OpStore %121 %141
+        %164 = OpExtInst %void %1 DebugScope %53
+               OpLine %7 25 26
+        %131 = OpLoad %v4float %121
+               OpLine %7 25 5
+               OpStore %143 %131
+               OpLine %7 26 12
+        %147 = OpLoad %v4float %143
+        %148 = OpCompositeConstruct %PS_OUTPUT %147
+               OpLine %7 26 5
+        %150 = OpCompositeExtract %v4float %148 0
+               OpStore %149 %150
+               OpNoLine
+        %165 = OpExtInst %void %1 DebugNoScope
+        %151 = OpLoad %v4float %149
+        %152 = OpCompositeConstruct %PS_OUTPUT %151
+         %84 = OpCompositeExtract %v4float %152 0
+               OpStore %out_var_SV_Target0 %84
+               OpLine %7 27 1
+               OpReturn
+               OpFunctionEnd
+;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_i]]
+;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_tc]]
+;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_c]]
+;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_color]]
+;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_ps_output]]
+  )";
+
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<LocalSingleStoreElimPass>(text, false);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //    Other types
diff --git a/third_party/SPIRV-Tools/test/opt/local_ssa_elim_test.cpp b/third_party/SPIRV-Tools/test/opt/local_ssa_elim_test.cpp
index 4b7542f..45006ca 100644
--- a/third_party/SPIRV-Tools/test/opt/local_ssa_elim_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/local_ssa_elim_test.cpp
@@ -2978,6 +2978,7 @@
 
 ; CHECK:      OpExtInst %void [[ext]] DebugScope [[dbg_main]]
 ; CHECK:      OpStore %f %float_0
+; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_x]] %float_0
 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
 ; CHECK-NEXT: OpStore %i %int_0
 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] %int_0
@@ -4251,6 +4252,1210 @@
   SinglePassRunAndCheck<SSARewritePass>(text, text, false);
 }
 
+TEST_F(LocalSSAElimTest, MissingDebugValue) {
+  // Make sure DebugValue for final fragcolor assignment is generated.
+
+  const std::string text =
+      R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+               OpExtension "SPV_KHR_non_semantic_info"
+          %1 = OpExtInstImport "GLSL.std.450"
+          %2 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %in_var_TEXCOORD0 %out_var_SV_TARGET %textureposition %samplerposition %textureNormal %samplerNormal %textureAlbedo %samplerAlbedo %textureShadowMap %samplerShadowMap %ubo
+               OpExecutionMode %main OriginUpperLeft
+         %15 = OpString "d2.frag"
+         %55 = OpString "float"
+         %63 = OpString "// Copyright 2020 Google LLC
+
+Texture2D textureposition : register(t1);
+SamplerState samplerposition : register(s1);
+Texture2D textureNormal : register(t2);
+SamplerState samplerNormal : register(s2);
+Texture2D textureAlbedo : register(t3);
+SamplerState samplerAlbedo : register(s3);
+// Depth from the light's point of view
+//layout (binding = 5) uniform sampler2DShadow samplerShadowMap;
+Texture2DArray textureShadowMap : register(t5);
+SamplerState samplerShadowMap : register(s5);
+
+#define LIGHT_COUNT 3
+#define SHADOW_FACTOR 0.25
+#define AMBIENT_LIGHT 0.1
+#define USE_PCF
+
+struct Light
+{
+	float4 position;
+	float4 target;
+	float4 color;
+	float4x4 viewMatrix;
+};
+
+struct UBO
+{
+	float4 viewPos;
+	Light lights[LIGHT_COUNT];
+	int useShadows;
+	int displayDebugTarget;
+};
+
+cbuffer ubo : register(b4) { UBO ubo; }
+
+float textureProj(float4 P, float layer, float2 offset)
+{
+	float shadow = 1.0;
+	float4 shadowCoord = P / P.w;
+	shadowCoord.xy = shadowCoord.xy * 0.5 + 0.5;
+
+	if (shadowCoord.z > -1.0 && shadowCoord.z < 1.0)
+	{
+		float dist = textureShadowMap.Sample(samplerShadowMap, float3(shadowCoord.xy + offset, layer)).r;
+		if (shadowCoord.w > 0.0 && dist < shadowCoord.z)
+		{
+			shadow = SHADOW_FACTOR;
+		}
+	}
+	return shadow;
+}
+
+float filterPCF(float4 sc, float layer)
+{
+	int2 texDim; int elements; int levels;
+	textureShadowMap.GetDimensions(0, texDim.x, texDim.y, elements, levels);
+	float scale = 1.5;
+	float dx = scale * 1.0 / float(texDim.x);
+	float dy = scale * 1.0 / float(texDim.y);
+
+	float shadowFactor = 0.0;
+	int count = 0;
+	int range = 1;
+
+	for (int x = -range; x <= range; x++)
+	{
+		for (int y = -range; y <= range; y++)
+		{
+			shadowFactor += textureProj(sc, layer, float2(dx*x, dy*y));
+			count++;
+		}
+
+	}
+	return shadowFactor / count;
+}
+
+float3 shadow(float3 fragcolor, float3 fragPos) {
+	for (int i = 0; i < LIGHT_COUNT; ++i)
+	{
+		float4 shadowClip = mul(ubo.lights[i].viewMatrix, float4(fragPos.xyz, 1.0));
+
+		float shadowFactor;
+		#ifdef USE_PCF
+			shadowFactor= filterPCF(shadowClip, i);
+		#else
+			shadowFactor = textureProj(shadowClip, i, float2(0.0, 0.0));
+		#endif
+
+		fragcolor *= shadowFactor;
+	}
+	return fragcolor;
+}
+
+float4 main([[vk::location(0)]] float2 inUV : TEXCOORD0) : SV_TARGET
+{
+	// Get G-Buffer values
+	float3 fragPos = textureposition.Sample(samplerposition, inUV).rgb;
+	float3 normal = textureNormal.Sample(samplerNormal, inUV).rgb;
+	float4 albedo = textureAlbedo.Sample(samplerAlbedo, inUV);
+
+	// Ambient part
+	float3 fragcolor  = albedo.rgb * AMBIENT_LIGHT;
+
+	float3 N = normalize(normal);
+
+	for(int i = 0; i < LIGHT_COUNT; ++i)
+	{
+		// Vector to light
+		float3 L = ubo.lights[i].position.xyz - fragPos;
+		// Distance from light to fragment position
+		float dist = length(L);
+		L = normalize(L);
+
+		// Viewer to fragment
+		float3 V = ubo.viewPos.xyz - fragPos;
+		V = normalize(V);
+
+		float lightCosInnerAngle = cos(radians(15.0));
+		float lightCosOuterAngle = cos(radians(25.0));
+		float lightRange = 100.0;
+
+		// Direction vector from source to target
+		float3 dir = normalize(ubo.lights[i].position.xyz - ubo.lights[i].target.xyz);
+
+		// Dual cone spot light with smooth transition between inner and outer angle
+		float cosDir = dot(L, dir);
+		float spotEffect = smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir);
+		float heightAttenuation = smoothstep(lightRange, 0.0f, dist);
+
+		// Diffuse lighting
+		float NdotL = max(0.0, dot(N, L));
+		float3 diff = NdotL.xxx;
+
+		// Specular lighting
+		float3 R = reflect(-L, N);
+		float NdotR = max(0.0, dot(R, V));
+		float3 spec = (pow(NdotR, 16.0) * albedo.a * 2.5).xxx;
+
+		fragcolor += float3((diff + spec) * spotEffect * heightAttenuation) * ubo.lights[i].color.rgb * albedo.rgb;
+	}
+
+	// Shadow calculations in a separate pass
+	if (ubo.useShadows > 0)
+	{
+		fragcolor = shadow(fragcolor, fragPos);
+	}
+
+	return float4(fragcolor, 1);
+}
+"
+         %68 = OpString "textureProj"
+         %69 = OpString ""
+         %78 = OpString "dist"
+         %82 = OpString "shadowCoord"
+         %85 = OpString "shadow"
+         %89 = OpString "offset"
+         %92 = OpString "layer"
+         %95 = OpString "P"
+         %99 = OpString "filterPCF"
+        %108 = OpString "int"
+        %110 = OpString "y"
+        %114 = OpString "x"
+        %118 = OpString "range"
+        %122 = OpString "count"
+        %125 = OpString "shadowFactor"
+        %128 = OpString "dy"
+        %131 = OpString "dx"
+        %134 = OpString "scale"
+        %137 = OpString "levels"
+        %141 = OpString "elements"
+        %145 = OpString "texDim"
+        %150 = OpString "sc"
+        %162 = OpString "shadowClip"
+        %166 = OpString "i"
+        %169 = OpString "fragPos"
+        %171 = OpString "fragcolor"
+        %175 = OpString "main"
+        %184 = OpString "spec"
+        %187 = OpString "NdotR"
+        %190 = OpString "R"
+        %193 = OpString "diff"
+        %196 = OpString "NdotL"
+        %199 = OpString "heightAttenuation"
+        %202 = OpString "spotEffect"
+        %205 = OpString "cosDir"
+        %208 = OpString "dir"
+        %211 = OpString "lightRange"
+        %214 = OpString "lightCosOuterAngle"
+        %217 = OpString "lightCosInnerAngle"
+        %220 = OpString "V"
+        %225 = OpString "L"
+        %230 = OpString "N"
+        %235 = OpString "albedo"
+        %238 = OpString "normal"
+        %244 = OpString "inUV"
+        %246 = OpString "viewPos"
+        %249 = OpString "position"
+        %252 = OpString "target"
+        %254 = OpString "color"
+        %259 = OpString "viewMatrix"
+        %263 = OpString "Light"
+        %267 = OpString "lights"
+        %271 = OpString "useShadows"
+        %275 = OpString "displayDebugTarget"
+        %278 = OpString "UBO"
+        %282 = OpString "ubo"
+        %285 = OpString "type.ubo"
+        %289 = OpString "@type.sampler"
+        %290 = OpString "type.sampler"
+        %292 = OpString "samplerShadowMap"
+        %295 = OpString "@type.2d.image.array"
+        %296 = OpString "type.2d.image.array"
+        %298 = OpString "TemplateParam"
+        %301 = OpString "textureShadowMap"
+        %304 = OpString "samplerAlbedo"
+        %306 = OpString "@type.2d.image"
+        %307 = OpString "type.2d.image"
+        %311 = OpString "textureAlbedo"
+        %313 = OpString "samplerNormal"
+        %315 = OpString "textureNormal"
+        %317 = OpString "samplerposition"
+        %319 = OpString "textureposition"
+               OpName %type_2d_image "type.2d.image"
+               OpName %textureposition "textureposition"
+               OpName %type_sampler "type.sampler"
+               OpName %samplerposition "samplerposition"
+               OpName %textureNormal "textureNormal"
+               OpName %samplerNormal "samplerNormal"
+               OpName %textureAlbedo "textureAlbedo"
+               OpName %samplerAlbedo "samplerAlbedo"
+               OpName %type_2d_image_array "type.2d.image.array"
+               OpName %textureShadowMap "textureShadowMap"
+               OpName %samplerShadowMap "samplerShadowMap"
+               OpName %type_ubo "type.ubo"
+               OpMemberName %type_ubo 0 "ubo"
+               OpName %UBO "UBO"
+               OpMemberName %UBO 0 "viewPos"
+               OpMemberName %UBO 1 "lights"
+               OpMemberName %UBO 2 "useShadows"
+               OpMemberName %UBO 3 "displayDebugTarget"
+               OpName %Light "Light"
+               OpMemberName %Light 0 "position"
+               OpMemberName %Light 1 "target"
+               OpMemberName %Light 2 "color"
+               OpMemberName %Light 3 "viewMatrix"
+               OpName %ubo "ubo"
+               OpName %in_var_TEXCOORD0 "in.var.TEXCOORD0"
+               OpName %out_var_SV_TARGET "out.var.SV_TARGET"
+               OpName %main "main"
+               OpName %param_var_inUV "param.var.inUV"
+               OpName %type_sampled_image "type.sampled.image"
+               OpName %type_sampled_image_0 "type.sampled.image"
+               OpDecorate %in_var_TEXCOORD0 Location 0
+               OpDecorate %out_var_SV_TARGET Location 0
+               OpDecorate %textureposition DescriptorSet 0
+               OpDecorate %textureposition Binding 1
+               OpDecorate %samplerposition DescriptorSet 0
+               OpDecorate %samplerposition Binding 1
+               OpDecorate %textureNormal DescriptorSet 0
+               OpDecorate %textureNormal Binding 2
+               OpDecorate %samplerNormal DescriptorSet 0
+               OpDecorate %samplerNormal Binding 2
+               OpDecorate %textureAlbedo DescriptorSet 0
+               OpDecorate %textureAlbedo Binding 3
+               OpDecorate %samplerAlbedo DescriptorSet 0
+               OpDecorate %samplerAlbedo Binding 3
+               OpDecorate %textureShadowMap DescriptorSet 0
+               OpDecorate %textureShadowMap Binding 5
+               OpDecorate %samplerShadowMap DescriptorSet 0
+               OpDecorate %samplerShadowMap Binding 5
+               OpDecorate %ubo DescriptorSet 0
+               OpDecorate %ubo Binding 4
+               OpMemberDecorate %Light 0 Offset 0
+               OpMemberDecorate %Light 1 Offset 16
+               OpMemberDecorate %Light 2 Offset 32
+               OpMemberDecorate %Light 3 Offset 48
+               OpMemberDecorate %Light 3 MatrixStride 16
+               OpMemberDecorate %Light 3 RowMajor
+               OpDecorate %_arr_Light_uint_3 ArrayStride 112
+               OpMemberDecorate %UBO 0 Offset 0
+               OpMemberDecorate %UBO 1 Offset 16
+               OpMemberDecorate %UBO 2 Offset 352
+               OpMemberDecorate %UBO 3 Offset 356
+               OpMemberDecorate %type_ubo 0 Offset 0
+               OpDecorate %type_ubo Block
+)"
+      R"(   %float = OpTypeFloat 32
+%float_0_100000001 = OpConstant %float 0.100000001
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+      %int_3 = OpConstant %int 3
+      %int_1 = OpConstant %int 1
+   %float_15 = OpConstant %float 15
+   %float_25 = OpConstant %float 25
+  %float_100 = OpConstant %float 100
+    %float_0 = OpConstant %float 0
+   %float_16 = OpConstant %float 16
+  %float_2_5 = OpConstant %float 2.5
+      %int_2 = OpConstant %int 2
+    %float_1 = OpConstant %float 1
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+  %float_1_5 = OpConstant %float 1.5
+  %float_0_5 = OpConstant %float 0.5
+    %v2float = OpTypeVector %float 2
+         %35 = OpConstantComposite %v2float %float_0_5 %float_0_5
+   %float_n1 = OpConstant %float -1
+ %float_0_25 = OpConstant %float 0.25
+    %uint_32 = OpConstant %uint 32
+%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
+%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
+%type_sampler = OpTypeSampler
+%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
+%type_2d_image_array = OpTypeImage %float 2D 2 1 0 1 Unknown
+%_ptr_UniformConstant_type_2d_image_array = OpTypePointer UniformConstant %type_2d_image_array
+    %v4float = OpTypeVector %float 4
+     %uint_3 = OpConstant %uint 3
+%mat4v4float = OpTypeMatrix %v4float 4
+      %Light = OpTypeStruct %v4float %v4float %v4float %mat4v4float
+%_arr_Light_uint_3 = OpTypeArray %Light %uint_3
+        %UBO = OpTypeStruct %v4float %_arr_Light_uint_3 %int %int
+   %type_ubo = OpTypeStruct %UBO
+%_ptr_Uniform_type_ubo = OpTypePointer Uniform %type_ubo
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+       %void = OpTypeVoid
+     %uint_4 = OpConstant %uint 4
+     %uint_2 = OpConstant %uint 2
+     %uint_1 = OpConstant %uint 1
+     %uint_5 = OpConstant %uint 5
+    %uint_37 = OpConstant %uint 37
+    %uint_38 = OpConstant %uint 38
+    %uint_44 = OpConstant %uint 44
+    %uint_47 = OpConstant %uint 47
+    %uint_45 = OpConstant %uint 45
+     %uint_9 = OpConstant %uint 9
+    %uint_40 = OpConstant %uint 40
+    %uint_39 = OpConstant %uint 39
+     %uint_8 = OpConstant %uint 8
+    %uint_49 = OpConstant %uint 49
+    %uint_35 = OpConstant %uint 35
+    %uint_26 = OpConstant %uint 26
+    %uint_54 = OpConstant %uint 54
+    %uint_55 = OpConstant %uint 55
+    %uint_67 = OpConstant %uint 67
+    %uint_69 = OpConstant %uint 69
+    %uint_68 = OpConstant %uint 68
+    %uint_12 = OpConstant %uint 12
+    %uint_66 = OpConstant %uint 66
+    %uint_11 = OpConstant %uint 11
+    %uint_64 = OpConstant %uint 64
+     %uint_6 = OpConstant %uint 6
+    %uint_63 = OpConstant %uint 63
+    %uint_62 = OpConstant %uint 62
+    %uint_60 = OpConstant %uint 60
+    %uint_59 = OpConstant %uint 59
+    %uint_58 = OpConstant %uint 58
+    %uint_56 = OpConstant %uint 56
+    %uint_33 = OpConstant %uint 33
+    %uint_19 = OpConstant %uint 19
+     %uint_7 = OpConstant %uint 7
+    %uint_34 = OpConstant %uint 34
+    %uint_24 = OpConstant %uint 24
+    %uint_78 = OpConstant %uint 78
+    %uint_80 = OpConstant %uint 80
+    %uint_83 = OpConstant %uint 83
+    %uint_81 = OpConstant %uint 81
+    %uint_10 = OpConstant %uint 10
+    %uint_79 = OpConstant %uint 79
+    %uint_22 = OpConstant %uint 22
+    %uint_95 = OpConstant %uint 95
+    %uint_96 = OpConstant %uint 96
+   %uint_145 = OpConstant %uint 145
+   %uint_108 = OpConstant %uint 108
+   %uint_138 = OpConstant %uint 138
+   %uint_137 = OpConstant %uint 137
+   %uint_136 = OpConstant %uint 136
+   %uint_133 = OpConstant %uint 133
+   %uint_132 = OpConstant %uint 132
+   %uint_129 = OpConstant %uint 129
+   %uint_128 = OpConstant %uint 128
+   %uint_127 = OpConstant %uint 127
+   %uint_124 = OpConstant %uint 124
+   %uint_121 = OpConstant %uint 121
+   %uint_120 = OpConstant %uint 120
+   %uint_119 = OpConstant %uint 119
+   %uint_116 = OpConstant %uint 116
+   %uint_112 = OpConstant %uint 112
+   %uint_110 = OpConstant %uint 110
+   %uint_107 = OpConstant %uint 107
+   %uint_105 = OpConstant %uint 105
+   %uint_103 = OpConstant %uint 103
+   %uint_100 = OpConstant %uint 100
+    %uint_99 = OpConstant %uint 99
+    %uint_98 = OpConstant %uint 98
+    %uint_29 = OpConstant %uint 29
+    %uint_21 = OpConstant %uint 21
+   %uint_256 = OpConstant %uint 256
+    %uint_23 = OpConstant %uint 23
+   %uint_384 = OpConstant %uint 384
+   %uint_512 = OpConstant %uint 512
+   %uint_896 = OpConstant %uint 896
+  %uint_2688 = OpConstant %uint 2688
+    %uint_30 = OpConstant %uint 30
+  %uint_2816 = OpConstant %uint 2816
+    %uint_31 = OpConstant %uint 31
+  %uint_2848 = OpConstant %uint 2848
+  %uint_2880 = OpConstant %uint 2880
+    %uint_27 = OpConstant %uint 27
+  %uint_2944 = OpConstant %uint 2944
+    %uint_14 = OpConstant %uint 14
+    %uint_16 = OpConstant %uint 16
+        %321 = OpTypeFunction %void
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+   %uint_150 = OpConstant %uint 150
+    %v3float = OpTypeVector %float 3
+%_ptr_Function_v3float = OpTypePointer Function %v3float
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Function_int = OpTypePointer Function %int
+%_ptr_Function_float = OpTypePointer Function %float
+    %uint_42 = OpConstant %uint 42
+%type_sampled_image = OpTypeSampledImage %type_2d_image
+    %uint_65 = OpConstant %uint 65
+    %uint_18 = OpConstant %uint 18
+    %uint_13 = OpConstant %uint 13
+    %uint_15 = OpConstant %uint 15
+    %uint_17 = OpConstant %uint 17
+       %bool = OpTypeBool
+    %uint_25 = OpConstant %uint 25
+%_ptr_Uniform_UBO = OpTypePointer Uniform %UBO
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+    %uint_28 = OpConstant %uint 28
+    %uint_43 = OpConstant %uint 43
+   %uint_113 = OpConstant %uint 113
+   %uint_117 = OpConstant %uint 117
+    %uint_46 = OpConstant %uint 46
+    %uint_76 = OpConstant %uint 76
+    %uint_53 = OpConstant %uint 53
+    %uint_73 = OpConstant %uint 73
+    %uint_48 = OpConstant %uint 48
+   %uint_140 = OpConstant %uint 140
+    %uint_52 = OpConstant %uint 52
+    %uint_93 = OpConstant %uint 93
+    %uint_87 = OpConstant %uint 87
+   %uint_106 = OpConstant %uint 106
+    %uint_36 = OpConstant %uint 36
+   %uint_144 = OpConstant %uint 144
+%_ptr_Uniform_int = OpTypePointer Uniform %int
+   %uint_146 = OpConstant %uint 146
+   %uint_147 = OpConstant %uint 147
+   %uint_149 = OpConstant %uint 149
+    %uint_41 = OpConstant %uint 41
+%_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
+    %uint_77 = OpConstant %uint 77
+    %uint_85 = OpConstant %uint 85
+    %uint_90 = OpConstant %uint 90
+    %uint_92 = OpConstant %uint 92
+      %v2int = OpTypeVector %int 2
+%_ptr_Function_v2int = OpTypePointer Function %v2int
+    %uint_57 = OpConstant %uint 57
+     %v3uint = OpTypeVector %uint 3
+    %uint_72 = OpConstant %uint 72
+    %uint_70 = OpConstant %uint 70
+    %uint_50 = OpConstant %uint 50
+    %uint_61 = OpConstant %uint 61
+    %uint_71 = OpConstant %uint 71
+    %uint_75 = OpConstant %uint 75
+    %uint_82 = OpConstant %uint 82
+%type_sampled_image_0 = OpTypeSampledImage %type_2d_image_array
+    %uint_51 = OpConstant %uint 51
+%textureposition = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
+%samplerposition = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%textureNormal = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
+%samplerNormal = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%textureAlbedo = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
+%samplerAlbedo = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+%textureShadowMap = OpVariable %_ptr_UniformConstant_type_2d_image_array UniformConstant
+%samplerShadowMap = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
+        %ubo = OpVariable %_ptr_Uniform_type_ubo Uniform
+%in_var_TEXCOORD0 = OpVariable %_ptr_Input_v2float Input
+%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output
+  %uint_1792 = OpConstant %uint 1792
+  %uint_1869 = OpConstant %uint 1869
+  %uint_2060 = OpConstant %uint 2060
+        %288 = OpExtInst %void %2 DebugInfoNone
+        %243 = OpExtInst %void %2 DebugExpression
+         %57 = OpExtInst %void %2 DebugTypeBasic %55 %uint_32 %uint_3 %uint_0
+         %58 = OpExtInst %void %2 DebugTypeVector %57 %uint_4
+         %60 = OpExtInst %void %2 DebugTypeVector %57 %uint_2
+         %62 = OpExtInst %void %2 DebugTypeFunction %uint_3 %57 %58 %57 %60
+         %64 = OpExtInst %void %2 DebugSource %15 %63
+         %65 = OpExtInst %void %2 DebugCompilationUnit %uint_1 %uint_4 %64 %uint_5
+         %70 = OpExtInst %void %2 DebugFunction %68 %62 %64 %uint_37 %uint_1 %65 %69 %uint_3 %uint_38
+         %73 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_38 %uint_1 %70
+         %74 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_44 %uint_2 %73
+         %76 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_47 %uint_3 %74
+         %79 = OpExtInst %void %2 DebugLocalVariable %78 %57 %64 %uint_45 %uint_9 %74 %uint_4
+         %83 = OpExtInst %void %2 DebugLocalVariable %82 %58 %64 %uint_40 %uint_9 %73 %uint_4
+         %86 = OpExtInst %void %2 DebugLocalVariable %85 %57 %64 %uint_39 %uint_8 %73 %uint_4
+         %90 = OpExtInst %void %2 DebugLocalVariable %89 %60 %64 %uint_37 %uint_49 %70 %uint_4 %uint_3
+         %93 = OpExtInst %void %2 DebugLocalVariable %92 %57 %64 %uint_37 %uint_35 %70 %uint_4 %uint_2
+         %96 = OpExtInst %void %2 DebugLocalVariable %95 %58 %64 %uint_37 %uint_26 %70 %uint_4 %uint_1
+         %98 = OpExtInst %void %2 DebugTypeFunction %uint_3 %57 %58 %57
+        %100 = OpExtInst %void %2 DebugFunction %99 %98 %64 %uint_54 %uint_1 %65 %69 %uint_3 %uint_55
+        %103 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_55 %uint_1 %100
+        %104 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_67 %uint_2 %103
+        %106 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_69 %uint_3 %104
+        %109 = OpExtInst %void %2 DebugTypeBasic %108 %uint_32 %uint_4 %uint_0
+        %111 = OpExtInst %void %2 DebugLocalVariable %110 %109 %64 %uint_68 %uint_12 %104 %uint_4
+        %115 = OpExtInst %void %2 DebugLocalVariable %114 %109 %64 %uint_66 %uint_11 %103 %uint_4
+        %119 = OpExtInst %void %2 DebugLocalVariable %118 %109 %64 %uint_64 %uint_6 %103 %uint_4
+        %123 = OpExtInst %void %2 DebugLocalVariable %122 %109 %64 %uint_63 %uint_6 %103 %uint_4
+        %126 = OpExtInst %void %2 DebugLocalVariable %125 %57 %64 %uint_62 %uint_8 %103 %uint_4
+        %129 = OpExtInst %void %2 DebugLocalVariable %128 %57 %64 %uint_60 %uint_8 %103 %uint_4
+        %132 = OpExtInst %void %2 DebugLocalVariable %131 %57 %64 %uint_59 %uint_8 %103 %uint_4
+        %135 = OpExtInst %void %2 DebugLocalVariable %134 %57 %64 %uint_58 %uint_8 %103 %uint_4
+        %138 = OpExtInst %void %2 DebugLocalVariable %137 %109 %64 %uint_56 %uint_33 %103 %uint_4
+        %142 = OpExtInst %void %2 DebugLocalVariable %141 %109 %64 %uint_56 %uint_19 %103 %uint_4
+        %144 = OpExtInst %void %2 DebugTypeVector %109 %uint_2
+        %146 = OpExtInst %void %2 DebugLocalVariable %145 %144 %64 %uint_56 %uint_7 %103 %uint_4
+        %148 = OpExtInst %void %2 DebugLocalVariable %92 %57 %64 %uint_54 %uint_34 %100 %uint_4 %uint_2
+        %151 = OpExtInst %void %2 DebugLocalVariable %150 %58 %64 %uint_54 %uint_24 %100 %uint_4 %uint_1
+        %153 = OpExtInst %void %2 DebugTypeVector %57 %uint_3
+        %154 = OpExtInst %void %2 DebugTypeFunction %uint_3 %153 %153 %153
+        %155 = OpExtInst %void %2 DebugFunction %85 %154 %64 %uint_78 %uint_1 %65 %69 %uint_3 %uint_78
+        %157 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_78 %uint_49 %155
+        %158 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_80 %uint_2 %157
+        %160 = OpExtInst %void %2 DebugLocalVariable %125 %57 %64 %uint_83 %uint_9 %158 %uint_4
+        %163 = OpExtInst %void %2 DebugLocalVariable %162 %58 %64 %uint_81 %uint_10 %158 %uint_4
+        %167 = OpExtInst %void %2 DebugLocalVariable %166 %109 %64 %uint_79 %uint_11 %157 %uint_4
+        %170 = OpExtInst %void %2 DebugLocalVariable %169 %153 %64 %uint_78 %uint_40 %155 %uint_4 %uint_2
+        %172 = OpExtInst %void %2 DebugLocalVariable %171 %153 %64 %uint_78 %uint_22 %155 %uint_4 %uint_1
+        %174 = OpExtInst %void %2 DebugTypeFunction %uint_3 %58 %60
+        %176 = OpExtInst %void %2 DebugFunction %175 %174 %64 %uint_95 %uint_1 %65 %69 %uint_3 %uint_96
+        %179 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_96 %uint_1 %176
+        %180 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_145 %uint_2 %179
+        %182 = OpExtInst %void %2 DebugLexicalBlock %64 %uint_108 %uint_2 %179
+        %185 = OpExtInst %void %2 DebugLocalVariable %184 %153 %64 %uint_138 %uint_10 %182 %uint_4
+        %188 = OpExtInst %void %2 DebugLocalVariable %187 %57 %64 %uint_137 %uint_9 %182 %uint_4
+        %191 = OpExtInst %void %2 DebugLocalVariable %190 %153 %64 %uint_136 %uint_10 %182 %uint_4
+        %194 = OpExtInst %void %2 DebugLocalVariable %193 %153 %64 %uint_133 %uint_10 %182 %uint_4
+        %197 = OpExtInst %void %2 DebugLocalVariable %196 %57 %64 %uint_132 %uint_9 %182 %uint_4
+        %200 = OpExtInst %void %2 DebugLocalVariable %199 %57 %64 %uint_129 %uint_9 %182 %uint_4
+        %203 = OpExtInst %void %2 DebugLocalVariable %202 %57 %64 %uint_128 %uint_9 %182 %uint_4
+        %206 = OpExtInst %void %2 DebugLocalVariable %205 %57 %64 %uint_127 %uint_9 %182 %uint_4
+        %209 = OpExtInst %void %2 DebugLocalVariable %208 %153 %64 %uint_124 %uint_10 %182 %uint_4
+        %212 = OpExtInst %void %2 DebugLocalVariable %211 %57 %64 %uint_121 %uint_9 %182 %uint_4
+        %215 = OpExtInst %void %2 DebugLocalVariable %214 %57 %64 %uint_120 %uint_9 %182 %uint_4
+        %218 = OpExtInst %void %2 DebugLocalVariable %217 %57 %64 %uint_119 %uint_9 %182 %uint_4
+        %221 = OpExtInst %void %2 DebugLocalVariable %220 %153 %64 %uint_116 %uint_10 %182 %uint_4
+        %223 = OpExtInst %void %2 DebugLocalVariable %78 %57 %64 %uint_112 %uint_9 %182 %uint_4
+        %226 = OpExtInst %void %2 DebugLocalVariable %225 %153 %64 %uint_110 %uint_10 %182 %uint_4
+        %228 = OpExtInst %void %2 DebugLocalVariable %166 %109 %64 %uint_107 %uint_10 %179 %uint_4
+        %231 = OpExtInst %void %2 DebugLocalVariable %230 %153 %64 %uint_105 %uint_9 %179 %uint_4
+        %233 = OpExtInst %void %2 DebugLocalVariable %171 %153 %64 %uint_103 %uint_9 %179 %uint_4
+        %236 = OpExtInst %void %2 DebugLocalVariable %235 %58 %64 %uint_100 %uint_9 %179 %uint_4
+        %239 = OpExtInst %void %2 DebugLocalVariable %238 %153 %64 %uint_99 %uint_9 %179 %uint_4
+        %241 = OpExtInst %void %2 DebugLocalVariable %169 %153 %64 %uint_98 %uint_9 %179 %uint_4
+        %245 = OpExtInst %void %2 DebugLocalVariable %244 %60 %64 %uint_95 %uint_40 %176 %uint_4 %uint_1
+)"
+      R"(     %247 = OpExtInst %void %2 DebugTypeMember %246 %58 %64 %uint_29 %uint_9 %uint_0 %uint_128 %uint_3
+        %250 = OpExtInst %void %2 DebugTypeMember %249 %58 %64 %uint_21 %uint_9 %uint_0 %uint_128 %uint_3
+        %253 = OpExtInst %void %2 DebugTypeMember %252 %58 %64 %uint_22 %uint_9 %uint_128 %uint_128 %uint_3
+        %256 = OpExtInst %void %2 DebugTypeMember %254 %58 %64 %uint_23 %uint_9 %uint_256 %uint_128 %uint_3
+        %258 = OpExtInst %void %2 DebugTypeArray %57 %uint_4 %uint_4
+        %262 = OpExtInst %void %2 DebugTypeMember %259 %258 %64 %uint_24 %uint_11 %uint_384 %uint_512 %uint_3
+        %265 = OpExtInst %void %2 DebugTypeComposite %263 %uint_1 %64 %uint_19 %uint_8 %65 %263 %uint_896 %uint_3 %250 %253 %256 %262
+        %266 = OpExtInst %void %2 DebugTypeArray %265 %uint_3
+        %269 = OpExtInst %void %2 DebugTypeMember %267 %266 %64 %uint_30 %uint_8 %uint_128 %uint_2688 %uint_3
+        %273 = OpExtInst %void %2 DebugTypeMember %271 %109 %64 %uint_31 %uint_6 %uint_2816 %uint_32 %uint_3
+        %277 = OpExtInst %void %2 DebugTypeMember %275 %109 %64 %uint_32 %uint_6 %uint_2848 %uint_32 %uint_3
+        %280 = OpExtInst %void %2 DebugTypeComposite %278 %uint_1 %64 %uint_27 %uint_8 %65 %278 %uint_2880 %uint_3 %247 %269 %273 %277
+        %284 = OpExtInst %void %2 DebugTypeMember %282 %280 %64 %uint_35 %uint_34 %uint_0 %uint_2944 %uint_3
+        %286 = OpExtInst %void %2 DebugTypeComposite %285 %uint_1 %64 %uint_35 %uint_9 %65 %285 %uint_2944 %uint_3 %284
+        %287 = OpExtInst %void %2 DebugGlobalVariable %282 %286 %64 %uint_35 %uint_9 %65 %282 %ubo %uint_8
+        %291 = OpExtInst %void %2 DebugTypeComposite %289 %uint_1 %64 %uint_0 %uint_0 %65 %290 %288 %uint_3
+        %293 = OpExtInst %void %2 DebugGlobalVariable %292 %291 %64 %uint_12 %uint_14 %65 %292 %samplerShadowMap %uint_8
+        %297 = OpExtInst %void %2 DebugTypeComposite %295 %uint_0 %64 %uint_0 %uint_0 %65 %296 %288 %uint_3
+        %299 = OpExtInst %void %2 DebugTypeTemplateParameter %298 %58 %288 %64 %uint_0 %uint_0
+        %300 = OpExtInst %void %2 DebugTypeTemplate %297 %299
+        %302 = OpExtInst %void %2 DebugGlobalVariable %301 %300 %64 %uint_11 %uint_16 %65 %301 %textureShadowMap %uint_8
+        %305 = OpExtInst %void %2 DebugGlobalVariable %304 %291 %64 %uint_8 %uint_14 %65 %304 %samplerAlbedo %uint_8
+        %308 = OpExtInst %void %2 DebugTypeComposite %306 %uint_0 %64 %uint_0 %uint_0 %65 %307 %288 %uint_3
+        %309 = OpExtInst %void %2 DebugTypeTemplateParameter %298 %58 %288 %64 %uint_0 %uint_0
+        %310 = OpExtInst %void %2 DebugTypeTemplate %308 %309
+        %312 = OpExtInst %void %2 DebugGlobalVariable %311 %310 %64 %uint_7 %uint_11 %65 %311 %textureAlbedo %uint_8
+        %314 = OpExtInst %void %2 DebugGlobalVariable %313 %291 %64 %uint_6 %uint_14 %65 %313 %samplerNormal %uint_8
+        %316 = OpExtInst %void %2 DebugGlobalVariable %315 %310 %64 %uint_5 %uint_11 %65 %315 %textureNormal %uint_8
+        %318 = OpExtInst %void %2 DebugGlobalVariable %317 %291 %64 %uint_4 %uint_14 %65 %317 %samplerposition %uint_8
+        %320 = OpExtInst %void %2 DebugGlobalVariable %319 %310 %64 %uint_3 %uint_11 %65 %319 %textureposition %uint_8
+       %1803 = OpExtInst %void %2 DebugInlinedAt %uint_1792 %180
+       %1885 = OpExtInst %void %2 DebugInlinedAt %uint_1869 %158 %1803
+       %2085 = OpExtInst %void %2 DebugInlinedAt %uint_2060 %106 %1885
+)"
+      R"(    %main = OpFunction %void None %321
+        %322 = OpLabel
+       %2083 = OpVariable %_ptr_Function_float Function
+       %2086 = OpVariable %_ptr_Function_v4float Function
+       %1883 = OpVariable %_ptr_Function_v2int Function
+       %1891 = OpVariable %_ptr_Function_float Function
+       %1892 = OpVariable %_ptr_Function_int Function
+       %1894 = OpVariable %_ptr_Function_int Function
+       %1895 = OpVariable %_ptr_Function_int Function
+       %1896 = OpVariable %_ptr_Function_v4float Function
+       %1801 = OpVariable %_ptr_Function_int Function
+       %1447 = OpVariable %_ptr_Function_v4float Function
+       %1448 = OpVariable %_ptr_Function_v3float Function
+       %1450 = OpVariable %_ptr_Function_int Function
+       %1451 = OpVariable %_ptr_Function_v3float Function
+       %1453 = OpVariable %_ptr_Function_v3float Function
+       %1466 = OpVariable %_ptr_Function_v3float Function
+%param_var_inUV = OpVariable %_ptr_Function_v2float Function
+        %325 = OpExtInst %void %2 DebugFunctionDefinition %176 %main
+        %326 = OpLoad %v2float %in_var_TEXCOORD0
+               OpStore %param_var_inUV %326
+       %2290 = OpExtInst %void %2 DebugScope %176
+       %1620 = OpExtInst %void %2 DebugLine %64 %uint_95 %uint_95 %uint_33 %uint_40
+       %1470 = OpExtInst %void %2 DebugDeclare %245 %param_var_inUV %243
+       %2291 = OpExtInst %void %2 DebugScope %179
+       %1621 = OpExtInst %void %2 DebugLine %64 %uint_98 %uint_98 %uint_19 %uint_19
+       %1471 = OpLoad %type_2d_image %textureposition
+       %1622 = OpExtInst %void %2 DebugLine %64 %uint_98 %uint_98 %uint_42 %uint_42
+       %1472 = OpLoad %type_sampler %samplerposition
+       %1624 = OpExtInst %void %2 DebugLine %64 %uint_98 %uint_98 %uint_19 %uint_63
+       %1474 = OpSampledImage %type_sampled_image %1471 %1472
+       %1475 = OpImageSampleImplicitLod %v4float %1474 %326 None
+       %1626 = OpExtInst %void %2 DebugLine %64 %uint_98 %uint_98 %uint_19 %uint_65
+       %1476 = OpVectorShuffle %v3float %1475 %1475 0 1 2
+       %2241 = OpExtInst %void %2 DebugLine %64 %uint_98 %uint_98 %uint_2 %uint_65
+       %2240 = OpExtInst %void %2 DebugValue %241 %1476 %243
+       %1629 = OpExtInst %void %2 DebugLine %64 %uint_99 %uint_99 %uint_18 %uint_18
+       %1478 = OpLoad %type_2d_image %textureNormal
+       %1630 = OpExtInst %void %2 DebugLine %64 %uint_99 %uint_99 %uint_39 %uint_39
+       %1479 = OpLoad %type_sampler %samplerNormal
+       %1632 = OpExtInst %void %2 DebugLine %64 %uint_99 %uint_99 %uint_18 %uint_58
+       %1481 = OpSampledImage %type_sampled_image %1478 %1479
+       %1482 = OpImageSampleImplicitLod %v4float %1481 %326 None
+       %1634 = OpExtInst %void %2 DebugLine %64 %uint_99 %uint_99 %uint_18 %uint_60
+       %1483 = OpVectorShuffle %v3float %1482 %1482 0 1 2
+       %2244 = OpExtInst %void %2 DebugLine %64 %uint_99 %uint_99 %uint_2 %uint_60
+       %2243 = OpExtInst %void %2 DebugValue %239 %1483 %243
+       %1637 = OpExtInst %void %2 DebugLine %64 %uint_100 %uint_100 %uint_18 %uint_18
+       %1485 = OpLoad %type_2d_image %textureAlbedo
+       %1638 = OpExtInst %void %2 DebugLine %64 %uint_100 %uint_100 %uint_39 %uint_39
+       %1486 = OpLoad %type_sampler %samplerAlbedo
+       %1640 = OpExtInst %void %2 DebugLine %64 %uint_100 %uint_100 %uint_18 %uint_58
+       %1488 = OpSampledImage %type_sampled_image %1485 %1486
+       %1489 = OpImageSampleImplicitLod %v4float %1488 %326 None
+       %1642 = OpExtInst %void %2 DebugLine %64 %uint_100 %uint_100 %uint_2 %uint_58
+               OpStore %1447 %1489
+       %1490 = OpExtInst %void %2 DebugDeclare %236 %1447 %243
+       %1645 = OpExtInst %void %2 DebugLine %64 %uint_103 %uint_103 %uint_22 %uint_29
+       %1492 = OpVectorShuffle %v3float %1489 %1489 0 1 2
+       %1646 = OpExtInst %void %2 DebugLine %64 %uint_103 %uint_103 %uint_22 %uint_35
+       %1493 = OpVectorTimesScalar %v3float %1492 %float_0_100000001
+       %1647 = OpExtInst %void %2 DebugLine %64 %uint_103 %uint_103 %uint_2 %uint_35
+               OpStore %1448 %1493
+       %1494 = OpExtInst %void %2 DebugDeclare %233 %1448 %243
+       %1650 = OpExtInst %void %2 DebugLine %64 %uint_105 %uint_105 %uint_13 %uint_29
+       %1496 = OpExtInst %v3float %1 Normalize %1483
+       %2247 = OpExtInst %void %2 DebugLine %64 %uint_105 %uint_105 %uint_2 %uint_29
+       %2246 = OpExtInst %void %2 DebugValue %231 %1496 %243
+       %1653 = OpExtInst %void %2 DebugLine %64 %uint_107 %uint_107 %uint_6 %uint_14
+               OpStore %1450 %int_0
+       %1498 = OpExtInst %void %2 DebugDeclare %228 %1450 %243
+       %1655 = OpExtInst %void %2 DebugLine %64 %uint_107 %uint_107 %uint_6 %uint_15
+               OpBranch %1499
+       %1499 = OpLabel
+       %2292 = OpExtInst %void %2 DebugScope %179
+       %1656 = OpExtInst %void %2 DebugLine %64 %uint_107 %uint_107 %uint_17 %uint_17
+       %1500 = OpLoad %int %1450
+       %1657 = OpExtInst %void %2 DebugLine %64 %uint_107 %uint_107 %uint_17 %uint_21
+       %1501 = OpSLessThan %bool %1500 %int_3
+       %2293 = OpExtInst %void %2 DebugNoScope
+               OpLoopMerge %1605 %1602 None
+               OpBranchConditional %1501 %1502 %1605
+       %1502 = OpLabel
+       %2294 = OpExtInst %void %2 DebugScope %182
+       %1660 = OpExtInst %void %2 DebugLine %64 %uint_110 %uint_110 %uint_25 %uint_25
+       %1503 = OpLoad %int %1450
+       %1661 = OpExtInst %void %2 DebugLine %64 %uint_110 %uint_110 %uint_14 %uint_37
+       %1504 = OpAccessChain %_ptr_Uniform_UBO %ubo %int_0
+       %1505 = OpAccessChain %_ptr_Uniform_v4float %1504 %int_1 %1503 %int_0
+       %1663 = OpExtInst %void %2 DebugLine %64 %uint_110 %uint_110 %uint_14 %uint_28
+       %1506 = OpLoad %v4float %1505
+       %1664 = OpExtInst %void %2 DebugLine %64 %uint_110 %uint_110 %uint_14 %uint_37
+       %1507 = OpVectorShuffle %v3float %1506 %1506 0 1 2
+       %1666 = OpExtInst %void %2 DebugLine %64 %uint_110 %uint_110 %uint_14 %uint_43
+       %1509 = OpFSub %v3float %1507 %1476
+       %1667 = OpExtInst %void %2 DebugLine %64 %uint_110 %uint_110 %uint_3 %uint_43
+               OpStore %1451 %1509
+       %1510 = OpExtInst %void %2 DebugDeclare %226 %1451 %243
+       %1670 = OpExtInst %void %2 DebugLine %64 %uint_112 %uint_112 %uint_16 %uint_24
+       %1512 = OpExtInst %float %1 Length %1509
+       %2250 = OpExtInst %void %2 DebugLine %64 %uint_112 %uint_112 %uint_3 %uint_24
+       %2249 = OpExtInst %void %2 DebugValue %223 %1512 %243
+       %1674 = OpExtInst %void %2 DebugLine %64 %uint_113 %uint_113 %uint_7 %uint_18
+       %1515 = OpExtInst %v3float %1 Normalize %1509
+       %1675 = OpExtInst %void %2 DebugLine %64 %uint_113 %uint_113 %uint_3 %uint_18
+               OpStore %1451 %1515
+       %1676 = OpExtInst %void %2 DebugLine %64 %uint_116 %uint_116 %uint_14 %uint_26
+       %1516 = OpAccessChain %_ptr_Uniform_UBO %ubo %int_0
+       %1517 = OpAccessChain %_ptr_Uniform_v4float %1516 %int_0
+       %1678 = OpExtInst %void %2 DebugLine %64 %uint_116 %uint_116 %uint_14 %uint_18
+       %1518 = OpLoad %v4float %1517
+       %1679 = OpExtInst %void %2 DebugLine %64 %uint_116 %uint_116 %uint_14 %uint_26
+       %1519 = OpVectorShuffle %v3float %1518 %1518 0 1 2
+       %1681 = OpExtInst %void %2 DebugLine %64 %uint_116 %uint_116 %uint_14 %uint_32
+       %1521 = OpFSub %v3float %1519 %1476
+       %1682 = OpExtInst %void %2 DebugLine %64 %uint_116 %uint_116 %uint_3 %uint_32
+               OpStore %1453 %1521
+       %1522 = OpExtInst %void %2 DebugDeclare %221 %1453 %243
+       %1685 = OpExtInst %void %2 DebugLine %64 %uint_117 %uint_117 %uint_7 %uint_18
+       %1524 = OpExtInst %v3float %1 Normalize %1521
+       %1686 = OpExtInst %void %2 DebugLine %64 %uint_117 %uint_117 %uint_3 %uint_18
+               OpStore %1453 %1524
+       %1687 = OpExtInst %void %2 DebugLine %64 %uint_119 %uint_119 %uint_34 %uint_46
+       %1525 = OpExtInst %float %1 Radians %float_15
+       %1688 = OpExtInst %void %2 DebugLine %64 %uint_119 %uint_119 %uint_30 %uint_47
+       %1526 = OpExtInst %float %1 Cos %1525
+       %2253 = OpExtInst %void %2 DebugLine %64 %uint_119 %uint_119 %uint_3 %uint_47
+       %2252 = OpExtInst %void %2 DebugValue %218 %1526 %243
+       %1691 = OpExtInst %void %2 DebugLine %64 %uint_120 %uint_120 %uint_34 %uint_46
+       %1528 = OpExtInst %float %1 Radians %float_25
+       %1692 = OpExtInst %void %2 DebugLine %64 %uint_120 %uint_120 %uint_30 %uint_47
+       %1529 = OpExtInst %float %1 Cos %1528
+       %2256 = OpExtInst %void %2 DebugLine %64 %uint_120 %uint_120 %uint_3 %uint_47
+       %2255 = OpExtInst %void %2 DebugValue %215 %1529 %243
+       %2259 = OpExtInst %void %2 DebugLine %64 %uint_121 %uint_121 %uint_3 %uint_22
+       %2258 = OpExtInst %void %2 DebugValue %212 %float_100 %243
+       %1698 = OpExtInst %void %2 DebugLine %64 %uint_124 %uint_124 %uint_26 %uint_49
+       %1533 = OpAccessChain %_ptr_Uniform_UBO %ubo %int_0
+       %1534 = OpAccessChain %_ptr_Uniform_v4float %1533 %int_1 %1503 %int_0
+       %1700 = OpExtInst %void %2 DebugLine %64 %uint_124 %uint_124 %uint_26 %uint_40
+       %1535 = OpLoad %v4float %1534
+       %1701 = OpExtInst %void %2 DebugLine %64 %uint_124 %uint_124 %uint_26 %uint_49
+       %1536 = OpVectorShuffle %v3float %1535 %1535 0 1 2
+       %1703 = OpExtInst %void %2 DebugLine %64 %uint_124 %uint_124 %uint_55 %uint_76
+       %1538 = OpAccessChain %_ptr_Uniform_UBO %ubo %int_0
+       %1539 = OpAccessChain %_ptr_Uniform_v4float %1538 %int_1 %1503 %int_1
+       %1705 = OpExtInst %void %2 DebugLine %64 %uint_124 %uint_124 %uint_55 %uint_69
+       %1540 = OpLoad %v4float %1539
+       %1706 = OpExtInst %void %2 DebugLine %64 %uint_124 %uint_124 %uint_55 %uint_76
+       %1541 = OpVectorShuffle %v3float %1540 %1540 0 1 2
+       %1707 = OpExtInst %void %2 DebugLine %64 %uint_124 %uint_124 %uint_26 %uint_76
+       %1542 = OpFSub %v3float %1536 %1541
+       %1708 = OpExtInst %void %2 DebugLine %64 %uint_124 %uint_124 %uint_16 %uint_79
+       %1543 = OpExtInst %v3float %1 Normalize %1542
+       %2262 = OpExtInst %void %2 DebugLine %64 %uint_124 %uint_124 %uint_3 %uint_79
+       %2261 = OpExtInst %void %2 DebugValue %209 %1543 %243
+       %1713 = OpExtInst %void %2 DebugLine %64 %uint_127 %uint_127 %uint_18 %uint_28
+       %1547 = OpDot %float %1515 %1543
+       %2265 = OpExtInst %void %2 DebugLine %64 %uint_127 %uint_127 %uint_3 %uint_28
+       %2264 = OpExtInst %void %2 DebugValue %206 %1547 %243
+       %1719 = OpExtInst %void %2 DebugLine %64 %uint_128 %uint_128 %uint_22 %uint_79
+       %1552 = OpExtInst %float %1 SmoothStep %1529 %1526 %1547
+       %2268 = OpExtInst %void %2 DebugLine %64 %uint_128 %uint_128 %uint_3 %uint_79
+       %2267 = OpExtInst %void %2 DebugValue %203 %1552 %243
+       %1724 = OpExtInst %void %2 DebugLine %64 %uint_129 %uint_129 %uint_29 %uint_62
+       %1556 = OpExtInst %float %1 SmoothStep %float_100 %float_0 %1512
+       %2271 = OpExtInst %void %2 DebugLine %64 %uint_129 %uint_129 %uint_3 %uint_62
+       %2270 = OpExtInst %void %2 DebugValue %200 %1556 %243
+       %1729 = OpExtInst %void %2 DebugLine %64 %uint_132 %uint_132 %uint_26 %uint_34
+       %1560 = OpDot %float %1496 %1515
+       %1730 = OpExtInst %void %2 DebugLine %64 %uint_132 %uint_132 %uint_17 %uint_35
+       %1561 = OpExtInst %float %1 FMax %float_0 %1560
+       %2274 = OpExtInst %void %2 DebugLine %64 %uint_132 %uint_132 %uint_3 %uint_35
+       %2273 = OpExtInst %void %2 DebugValue %197 %1561 %243
+       %1734 = OpExtInst %void %2 DebugLine %64 %uint_133 %uint_133 %uint_17 %uint_23
+       %1564 = OpCompositeConstruct %v3float %1561 %1561 %1561
+       %2277 = OpExtInst %void %2 DebugLine %64 %uint_133 %uint_133 %uint_3 %uint_23
+       %2276 = OpExtInst %void %2 DebugValue %194 %1564 %243
+       %1738 = OpExtInst %void %2 DebugLine %64 %uint_136 %uint_136 %uint_22 %uint_23
+       %1567 = OpFNegate %v3float %1515
+       %1740 = OpExtInst %void %2 DebugLine %64 %uint_136 %uint_136 %uint_14 %uint_27
+       %1569 = OpExtInst %v3float %1 Reflect %1567 %1496
+       %2280 = OpExtInst %void %2 DebugLine %64 %uint_136 %uint_136 %uint_3 %uint_27
+       %2279 = OpExtInst %void %2 DebugValue %191 %1569 %243
+       %1745 = OpExtInst %void %2 DebugLine %64 %uint_137 %uint_137 %uint_26 %uint_34
+       %1573 = OpDot %float %1569 %1524
+       %1746 = OpExtInst %void %2 DebugLine %64 %uint_137 %uint_137 %uint_17 %uint_35
+       %1574 = OpExtInst %float %1 FMax %float_0 %1573
+       %2283 = OpExtInst %void %2 DebugLine %64 %uint_137 %uint_137 %uint_3 %uint_35
+       %2282 = OpExtInst %void %2 DebugValue %188 %1574 %243
+       %1750 = OpExtInst %void %2 DebugLine %64 %uint_138 %uint_138 %uint_18 %uint_33
+       %1577 = OpExtInst %float %1 Pow %1574 %float_16
+       %1751 = OpExtInst %void %2 DebugLine %64 %uint_138 %uint_138 %uint_37 %uint_44
+       %1578 = OpAccessChain %_ptr_Function_float %1447 %int_3
+       %1579 = OpLoad %float %1578
+       %1753 = OpExtInst %void %2 DebugLine %64 %uint_138 %uint_138 %uint_18 %uint_44
+       %1580 = OpFMul %float %1577 %1579
+       %1754 = OpExtInst %void %2 DebugLine %64 %uint_138 %uint_138 %uint_18 %uint_48
+       %1581 = OpFMul %float %1580 %float_2_5
+       %1755 = OpExtInst %void %2 DebugLine %64 %uint_138 %uint_138 %uint_17 %uint_53
+       %1582 = OpCompositeConstruct %v3float %1581 %1581 %1581
+       %2286 = OpExtInst %void %2 DebugLine %64 %uint_138 %uint_138 %uint_3 %uint_53
+       %2285 = OpExtInst %void %2 DebugValue %185 %1582 %243
+       %1760 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_24 %uint_31
+       %1586 = OpFAdd %v3float %1564 %1582
+       %1762 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_23 %uint_39
+       %1588 = OpVectorTimesScalar %v3float %1586 %1552
+       %1764 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_23 %uint_52
+       %1590 = OpVectorTimesScalar %v3float %1588 %1556
+       %1766 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_73 %uint_93
+       %1592 = OpAccessChain %_ptr_Uniform_UBO %ubo %int_0
+       %1593 = OpAccessChain %_ptr_Uniform_v4float %1592 %int_1 %1503 %int_2
+       %1768 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_73 %uint_87
+       %1594 = OpLoad %v4float %1593
+       %1769 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_73 %uint_93
+       %1595 = OpVectorShuffle %v3float %1594 %1594 0 1 2
+       %1770 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_16 %uint_93
+       %1596 = OpFMul %v3float %1590 %1595
+       %1772 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_99 %uint_106
+       %1598 = OpVectorShuffle %v3float %1489 %1489 0 1 2
+       %1773 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_16 %uint_106
+       %1599 = OpFMul %v3float %1596 %1598
+       %1774 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_3 %uint_3
+       %1600 = OpLoad %v3float %1448
+       %1775 = OpExtInst %void %2 DebugLine %64 %uint_140 %uint_140 %uint_3 %uint_106
+       %1601 = OpFAdd %v3float %1600 %1599
+               OpStore %1448 %1601
+       %2295 = OpExtInst %void %2 DebugScope %179
+       %1777 = OpExtInst %void %2 DebugLine %64 %uint_107 %uint_107 %uint_34 %uint_36
+               OpBranch %1602
+       %1602 = OpLabel
+       %2296 = OpExtInst %void %2 DebugScope %179
+       %1778 = OpExtInst %void %2 DebugLine %64 %uint_107 %uint_107 %uint_34 %uint_36
+       %1603 = OpLoad %int %1450
+       %1604 = OpIAdd %int %1603 %int_1
+               OpStore %1450 %1604
+               OpBranch %1499
+       %1605 = OpLabel
+       %2297 = OpExtInst %void %2 DebugScope %179
+       %1782 = OpExtInst %void %2 DebugLine %64 %uint_144 %uint_144 %uint_6 %uint_10
+       %1606 = OpAccessChain %_ptr_Uniform_UBO %ubo %int_0
+       %1607 = OpAccessChain %_ptr_Uniform_int %1606 %int_2
+       %1608 = OpLoad %int %1607
+       %1785 = OpExtInst %void %2 DebugLine %64 %uint_144 %uint_144 %uint_6 %uint_23
+       %1609 = OpSGreaterThan %bool %1608 %int_0
+       %2298 = OpExtInst %void %2 DebugNoScope
+               OpSelectionMerge %1614 None
+               OpBranchConditional %1609 %1610 %1614
+)"
+      R"(    %1610 = OpLabel
+       %2299 = OpExtInst %void %2 DebugScope %180
+       %1788 = OpExtInst %void %2 DebugLine %64 %uint_146 %uint_146 %uint_22 %uint_22
+       %1611 = OpLoad %v3float %1448
+               OpStore %1466 %1611
+       %2300 = OpExtInst %void %2 DebugScope %155 %1803
+       %1842 = OpExtInst %void %2 DebugLine %64 %uint_78 %uint_78 %uint_15 %uint_22
+       %1810 = OpExtInst %void %2 DebugDeclare %172 %1466 %243
+       %2301 = OpExtInst %void %2 DebugScope %180
+       %2289 = OpExtInst %void %2 DebugLine %64 %uint_146 %uint_146 %uint_33 %uint_33
+       %2288 = OpExtInst %void %2 DebugValue %170 %1476 %243
+       %2302 = OpExtInst %void %2 DebugScope %157 %1803
+       %1844 = OpExtInst %void %2 DebugLine %64 %uint_79 %uint_79 %uint_7 %uint_15
+               OpStore %1801 %int_0
+       %1813 = OpExtInst %void %2 DebugDeclare %167 %1801 %243
+       %1846 = OpExtInst %void %2 DebugLine %64 %uint_79 %uint_79 %uint_7 %uint_16
+               OpBranch %1814
+       %1814 = OpLabel
+       %2303 = OpExtInst %void %2 DebugScope %157 %1803
+       %1847 = OpExtInst %void %2 DebugLine %64 %uint_79 %uint_79 %uint_18 %uint_18
+       %1815 = OpLoad %int %1801
+       %1848 = OpExtInst %void %2 DebugLine %64 %uint_79 %uint_79 %uint_18 %uint_22
+       %1816 = OpSLessThan %bool %1815 %int_3
+       %2304 = OpExtInst %void %2 DebugNoScope
+               OpLoopMerge %1840 %1837 None
+               OpBranchConditional %1816 %1817 %1840
+       %1817 = OpLabel
+       %2305 = OpExtInst %void %2 DebugScope %158 %1803
+       %1851 = OpExtInst %void %2 DebugLine %64 %uint_81 %uint_81 %uint_38 %uint_38
+       %1818 = OpLoad %int %1801
+       %1852 = OpExtInst %void %2 DebugLine %64 %uint_81 %uint_81 %uint_27 %uint_41
+       %1819 = OpAccessChain %_ptr_Uniform_UBO %ubo %int_0
+       %1820 = OpAccessChain %_ptr_Uniform_mat4v4float %1819 %int_1 %1818 %int_3
+       %1821 = OpLoad %mat4v4float %1820
+       %1856 = OpExtInst %void %2 DebugLine %64 %uint_81 %uint_81 %uint_60 %uint_68
+       %1823 = OpCompositeExtract %float %1476 0
+       %1824 = OpCompositeExtract %float %1476 1
+       %1825 = OpCompositeExtract %float %1476 2
+       %1859 = OpExtInst %void %2 DebugLine %64 %uint_81 %uint_81 %uint_53 %uint_76
+       %1826 = OpCompositeConstruct %v4float %1823 %1824 %1825 %float_1
+       %1860 = OpExtInst %void %2 DebugLine %64 %uint_81 %uint_81 %uint_23 %uint_77
+       %1827 = OpVectorTimesMatrix %v4float %1826 %1821
+       %2229 = OpExtInst %void %2 DebugLine %64 %uint_81 %uint_81 %uint_3 %uint_77
+       %2228 = OpExtInst %void %2 DebugValue %163 %1827 %243
+       %1867 = OpExtInst %void %2 DebugLine %64 %uint_85 %uint_85 %uint_40 %uint_40
+       %1832 = OpConvertSToF %float %1818
+       %2235 = OpExtInst %void %2 DebugLine %64 %uint_85 %uint_85 %uint_28 %uint_28
+       %2234 = OpExtInst %void %2 DebugValue %151 %1827 %243
+       %2238 = OpExtInst %void %2 DebugLine %64 %uint_85 %uint_85 %uint_40 %uint_40
+       %2237 = OpExtInst %void %2 DebugValue %148 %1832 %243
+       %2306 = OpExtInst %void %2 DebugScope %103 %1885
+       %1983 = OpExtInst %void %2 DebugLine %64 %uint_56 %uint_56 %uint_2 %uint_7
+       %1904 = OpExtInst %void %2 DebugDeclare %146 %1883 %243
+       %1986 = OpExtInst %void %2 DebugLine %64 %uint_57 %uint_57 %uint_2 %uint_2
+       %1907 = OpLoad %type_2d_image_array %textureShadowMap
+)"
+      R"(    %1987 = OpExtInst %void %2 DebugLine %64 %uint_57 %uint_57 %uint_2 %uint_72
+       %1908 = OpImageQuerySizeLod %v3uint %1907 %uint_0
+       %1909 = OpCompositeExtract %uint %1908 0
+       %1910 = OpBitcast %int %1909
+       %1911 = OpAccessChain %_ptr_Function_int %1883 %int_0
+               OpStore %1911 %1910
+       %1912 = OpCompositeExtract %uint %1908 1
+       %1913 = OpBitcast %int %1912
+       %1914 = OpAccessChain %_ptr_Function_int %1883 %int_1
+               OpStore %1914 %1913
+       %1915 = OpCompositeExtract %uint %1908 2
+       %1916 = OpBitcast %int %1915
+       %2204 = OpExtInst %void %2 DebugValue %142 %1916 %243
+       %1999 = OpExtInst %void %2 DebugLine %64 %uint_57 %uint_57 %uint_19 %uint_19
+       %1917 = OpImageQueryLevels %uint %1907
+       %2000 = OpExtInst %void %2 DebugLine %64 %uint_57 %uint_57 %uint_2 %uint_72
+       %1918 = OpBitcast %int %1917
+       %2207 = OpExtInst %void %2 DebugValue %138 %1918 %243
+       %2211 = OpExtInst %void %2 DebugLine %64 %uint_58 %uint_58 %uint_2 %uint_16
+       %2210 = OpExtInst %void %2 DebugValue %135 %float_1_5 %243
+       %2005 = OpExtInst %void %2 DebugLine %64 %uint_59 %uint_59 %uint_13 %uint_21
+       %1921 = OpFMul %float %float_1_5 %float_1
+       %2006 = OpExtInst %void %2 DebugLine %64 %uint_59 %uint_59 %uint_33 %uint_40
+       %1922 = OpAccessChain %_ptr_Function_int %1883 %int_0
+       %1923 = OpLoad %int %1922
+       %1924 = OpConvertSToF %float %1923
+       %2009 = OpExtInst %void %2 DebugLine %64 %uint_59 %uint_59 %uint_13 %uint_41
+       %1925 = OpFDiv %float %1921 %1924
+       %2214 = OpExtInst %void %2 DebugLine %64 %uint_59 %uint_59 %uint_2 %uint_41
+       %2213 = OpExtInst %void %2 DebugValue %132 %1925 %243
+       %2013 = OpExtInst %void %2 DebugLine %64 %uint_60 %uint_60 %uint_13 %uint_21
+       %1928 = OpFMul %float %float_1_5 %float_1
+       %2014 = OpExtInst %void %2 DebugLine %64 %uint_60 %uint_60 %uint_33 %uint_40
+       %1929 = OpAccessChain %_ptr_Function_int %1883 %int_1
+       %1930 = OpLoad %int %1929
+       %1931 = OpConvertSToF %float %1930
+       %2017 = OpExtInst %void %2 DebugLine %64 %uint_60 %uint_60 %uint_13 %uint_41
+       %1932 = OpFDiv %float %1928 %1931
+       %2217 = OpExtInst %void %2 DebugLine %64 %uint_60 %uint_60 %uint_2 %uint_41
+       %2216 = OpExtInst %void %2 DebugValue %129 %1932 %243
+       %2020 = OpExtInst %void %2 DebugLine %64 %uint_62 %uint_62 %uint_2 %uint_23
+               OpStore %1891 %float_0
+       %1934 = OpExtInst %void %2 DebugDeclare %126 %1891 %243
+       %2022 = OpExtInst %void %2 DebugLine %64 %uint_63 %uint_63 %uint_2 %uint_14
+               OpStore %1892 %int_0
+       %1935 = OpExtInst %void %2 DebugDeclare %123 %1892 %243
+       %2220 = OpExtInst %void %2 DebugLine %64 %uint_64 %uint_64 %uint_2 %uint_14
+       %2219 = OpExtInst %void %2 DebugValue %119 %int_1 %243
+       %2027 = OpExtInst %void %2 DebugLine %64 %uint_66 %uint_66 %uint_15 %uint_16
+       %1938 = OpSNegate %int %int_1
+       %2028 = OpExtInst %void %2 DebugLine %64 %uint_66 %uint_66 %uint_7 %uint_16
+               OpStore %1894 %1938
+       %1939 = OpExtInst %void %2 DebugDeclare %115 %1894 %243
+       %2030 = OpExtInst %void %2 DebugLine %64 %uint_66 %uint_66 %uint_7 %uint_21
+               OpBranch %1940
+       %1940 = OpLabel
+       %2307 = OpExtInst %void %2 DebugScope %103 %1885
+       %2031 = OpExtInst %void %2 DebugLine %64 %uint_66 %uint_66 %uint_23 %uint_23
+       %1941 = OpLoad %int %1894
+       %2033 = OpExtInst %void %2 DebugLine %64 %uint_66 %uint_66 %uint_23 %uint_28
+       %1943 = OpSLessThanEqual %bool %1941 %int_1
+       %2308 = OpExtInst %void %2 DebugNoScope
+               OpLoopMerge %1976 %1973 None
+               OpBranchConditional %1943 %1944 %1976
+       %1944 = OpLabel
+       %2309 = OpExtInst %void %2 DebugScope %104 %1885
+       %2037 = OpExtInst %void %2 DebugLine %64 %uint_68 %uint_68 %uint_16 %uint_17
+       %1946 = OpSNegate %int %int_1
+       %2038 = OpExtInst %void %2 DebugLine %64 %uint_68 %uint_68 %uint_8 %uint_17
+               OpStore %1895 %1946
+       %1947 = OpExtInst %void %2 DebugDeclare %111 %1895 %243
+       %2040 = OpExtInst %void %2 DebugLine %64 %uint_68 %uint_68 %uint_8 %uint_22
+               OpBranch %1948
+       %1948 = OpLabel
+       %2310 = OpExtInst %void %2 DebugScope %104 %1885
+       %2041 = OpExtInst %void %2 DebugLine %64 %uint_68 %uint_68 %uint_24 %uint_24
+       %1949 = OpLoad %int %1895
+       %2043 = OpExtInst %void %2 DebugLine %64 %uint_68 %uint_68 %uint_24 %uint_29
+       %1951 = OpSLessThanEqual %bool %1949 %int_1
+       %2311 = OpExtInst %void %2 DebugNoScope
+               OpLoopMerge %1972 %1969 None
+               OpBranchConditional %1951 %1952 %1972
+       %1952 = OpLabel
+       %2312 = OpExtInst %void %2 DebugScope %106 %1885
+       %2047 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_32 %uint_32
+               OpStore %1896 %1827
+       %2051 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_53 %uint_53
+       %1956 = OpLoad %int %1894
+       %1957 = OpConvertSToF %float %1956
+       %2053 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_50 %uint_53
+       %1958 = OpFMul %float %1925 %1957
+       %2055 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_59 %uint_59
+       %1960 = OpLoad %int %1895
+       %1961 = OpConvertSToF %float %1960
+       %2057 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_56 %uint_59
+       %1962 = OpFMul %float %1932 %1961
+       %2058 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_43 %uint_60
+       %1963 = OpCompositeConstruct %v2float %1958 %1962
+       %2313 = OpExtInst %void %2 DebugScope %70 %2085
+       %2141 = OpExtInst %void %2 DebugLine %64 %uint_37 %uint_37 %uint_19 %uint_26
+       %2090 = OpExtInst %void %2 DebugDeclare %96 %1896 %243
+       %2314 = OpExtInst %void %2 DebugScope %106 %1885
+       %2223 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_36 %uint_36
+       %2222 = OpExtInst %void %2 DebugValue %93 %1832 %243
+       %2226 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_43 %uint_60
+       %2225 = OpExtInst %void %2 DebugValue %90 %1963 %243
+       %2315 = OpExtInst %void %2 DebugScope %73 %2085
+       %2144 = OpExtInst %void %2 DebugLine %64 %uint_39 %uint_39 %uint_2 %uint_17
+               OpStore %2083 %float_1
+       %2094 = OpExtInst %void %2 DebugDeclare %86 %2083 %243
+       %2147 = OpExtInst %void %2 DebugLine %64 %uint_40 %uint_40 %uint_27 %uint_29
+       %2096 = OpAccessChain %_ptr_Function_float %1896 %int_3
+       %2097 = OpLoad %float %2096
+       %2098 = OpCompositeConstruct %v4float %2097 %2097 %2097 %2097
+       %2150 = OpExtInst %void %2 DebugLine %64 %uint_40 %uint_40 %uint_23 %uint_29
+       %2099 = OpFDiv %v4float %1827 %2098
+       %2151 = OpExtInst %void %2 DebugLine %64 %uint_40 %uint_40 %uint_2 %uint_29
+               OpStore %2086 %2099
+       %2100 = OpExtInst %void %2 DebugDeclare %83 %2086 %243
+       %2154 = OpExtInst %void %2 DebugLine %64 %uint_41 %uint_41 %uint_19 %uint_31
+       %2102 = OpVectorShuffle %v2float %2099 %2099 0 1
+       %2155 = OpExtInst %void %2 DebugLine %64 %uint_41 %uint_41 %uint_19 %uint_36
+       %2103 = OpVectorTimesScalar %v2float %2102 %float_0_5
+       %2156 = OpExtInst %void %2 DebugLine %64 %uint_41 %uint_41 %uint_19 %uint_42
+       %2104 = OpFAdd %v2float %2103 %35
+       %2158 = OpExtInst %void %2 DebugLine %64 %uint_41 %uint_41 %uint_2 %uint_42
+       %2106 = OpVectorShuffle %v4float %2099 %2104 4 5 2 3
+               OpStore %2086 %2106
+       %2160 = OpExtInst %void %2 DebugLine %64 %uint_43 %uint_43 %uint_6 %uint_18
+       %2107 = OpAccessChain %_ptr_Function_float %2086 %int_2
+       %2108 = OpLoad %float %2107
+       %2162 = OpExtInst %void %2 DebugLine %64 %uint_43 %uint_43 %uint_6 %uint_23
+       %2109 = OpFOrdGreaterThan %bool %2108 %float_n1
+       %2163 = OpExtInst %void %2 DebugLine %64 %uint_43 %uint_43 %uint_30 %uint_42
+       %2110 = OpAccessChain %_ptr_Function_float %2086 %int_2
+       %2111 = OpLoad %float %2110
+       %2165 = OpExtInst %void %2 DebugLine %64 %uint_43 %uint_43 %uint_30 %uint_46
+       %2112 = OpFOrdLessThan %bool %2111 %float_1
+       %2166 = OpExtInst %void %2 DebugLine %64 %uint_43 %uint_43 %uint_6 %uint_46
+       %2113 = OpLogicalAnd %bool %2109 %2112
+       %2316 = OpExtInst %void %2 DebugNoScope
+               OpSelectionMerge %2139 None
+               OpBranchConditional %2113 %2114 %2139
+       %2114 = OpLabel
+       %2317 = OpExtInst %void %2 DebugScope %74 %2085
+       %2169 = OpExtInst %void %2 DebugLine %64 %uint_45 %uint_45 %uint_16 %uint_16
+       %2115 = OpLoad %type_2d_image_array %textureShadowMap
+       %2170 = OpExtInst %void %2 DebugLine %64 %uint_45 %uint_45 %uint_40 %uint_40
+       %2116 = OpLoad %type_sampler %samplerShadowMap
+       %2171 = OpExtInst %void %2 DebugLine %64 %uint_45 %uint_45 %uint_65 %uint_65
+       %2117 = OpLoad %v4float %2086
+       %2172 = OpExtInst %void %2 DebugLine %64 %uint_45 %uint_45 %uint_65 %uint_77
+       %2118 = OpVectorShuffle %v2float %2117 %2117 0 1
+       %2174 = OpExtInst %void %2 DebugLine %64 %uint_45 %uint_45 %uint_65 %uint_82
+       %2120 = OpFAdd %v2float %2118 %1963
+       %2122 = OpCompositeExtract %float %2120 0
+       %2123 = OpCompositeExtract %float %2120 1
+       %2178 = OpExtInst %void %2 DebugLine %64 %uint_45 %uint_45 %uint_58 %uint_95
+       %2124 = OpCompositeConstruct %v3float %2122 %2123 %1832
+       %2179 = OpExtInst %void %2 DebugLine %64 %uint_45 %uint_45 %uint_16 %uint_96
+       %2125 = OpSampledImage %type_sampled_image_0 %2115 %2116
+       %2126 = OpImageSampleImplicitLod %v4float %2125 %2124 None
+       %2181 = OpExtInst %void %2 DebugLine %64 %uint_45 %uint_45 %uint_16 %uint_98
+       %2127 = OpCompositeExtract %float %2126 0
+       %2202 = OpExtInst %void %2 DebugLine %64 %uint_45 %uint_45 %uint_3 %uint_98
+       %2201 = OpExtInst %void %2 DebugValue %79 %2127 %243
+       %2184 = OpExtInst %void %2 DebugLine %64 %uint_46 %uint_46 %uint_7 %uint_19
+       %2129 = OpAccessChain %_ptr_Function_float %2086 %int_3
+       %2130 = OpLoad %float %2129
+       %2186 = OpExtInst %void %2 DebugLine %64 %uint_46 %uint_46 %uint_7 %uint_23
+       %2131 = OpFOrdGreaterThan %bool %2130 %float_0
+       %2188 = OpExtInst %void %2 DebugLine %64 %uint_46 %uint_46 %uint_37 %uint_49
+       %2133 = OpAccessChain %_ptr_Function_float %2086 %int_2
+       %2134 = OpLoad %float %2133
+       %2190 = OpExtInst %void %2 DebugLine %64 %uint_46 %uint_46 %uint_30 %uint_49
+       %2135 = OpFOrdLessThan %bool %2127 %2134
+       %2191 = OpExtInst %void %2 DebugLine %64 %uint_46 %uint_46 %uint_7 %uint_49
+       %2136 = OpLogicalAnd %bool %2131 %2135
+       %2318 = OpExtInst %void %2 DebugNoScope
+               OpSelectionMerge %2138 None
+               OpBranchConditional %2136 %2137 %2138
+       %2137 = OpLabel
+       %2319 = OpExtInst %void %2 DebugScope %76 %2085
+       %2194 = OpExtInst %void %2 DebugLine %64 %uint_48 %uint_48 %uint_4 %uint_13
+               OpStore %2083 %float_0_25
+       %2320 = OpExtInst %void %2 DebugScope %74 %2085
+       %2195 = OpExtInst %void %2 DebugLine %64 %uint_49 %uint_49 %uint_3 %uint_3
+               OpBranch %2138
+       %2138 = OpLabel
+       %2321 = OpExtInst %void %2 DebugScope %73 %2085
+       %2196 = OpExtInst %void %2 DebugLine %64 %uint_50 %uint_50 %uint_2 %uint_2
+               OpBranch %2139
+       %2139 = OpLabel
+       %2322 = OpExtInst %void %2 DebugScope %73 %2085
+       %2197 = OpExtInst %void %2 DebugLine %64 %uint_51 %uint_51 %uint_9 %uint_9
+       %2140 = OpLoad %float %2083
+       %2323 = OpExtInst %void %2 DebugScope %106 %1885
+       %2061 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_4 %uint_4
+       %1965 = OpLoad %float %1891
+       %2062 = OpExtInst %void %2 DebugLine %64 %uint_70 %uint_70 %uint_4 %uint_61
+       %1966 = OpFAdd %float %1965 %2140
+               OpStore %1891 %1966
+       %2064 = OpExtInst %void %2 DebugLine %64 %uint_71 %uint_71 %uint_4 %uint_9
+       %1967 = OpLoad %int %1892
+       %1968 = OpIAdd %int %1967 %int_1
+               OpStore %1892 %1968
+       %2324 = OpExtInst %void %2 DebugScope %104 %1885
+       %2067 = OpExtInst %void %2 DebugLine %64 %uint_68 %uint_68 %uint_36 %uint_37
+               OpBranch %1969
+       %1969 = OpLabel
+       %2325 = OpExtInst %void %2 DebugScope %104 %1885
+       %2068 = OpExtInst %void %2 DebugLine %64 %uint_68 %uint_68 %uint_36 %uint_37
+       %1970 = OpLoad %int %1895
+       %1971 = OpIAdd %int %1970 %int_1
+               OpStore %1895 %1971
+               OpBranch %1948
+       %1972 = OpLabel
+       %2326 = OpExtInst %void %2 DebugScope %103 %1885
+       %2072 = OpExtInst %void %2 DebugLine %64 %uint_66 %uint_66 %uint_35 %uint_36
+               OpBranch %1973
+       %1973 = OpLabel
+       %2327 = OpExtInst %void %2 DebugScope %103 %1885
+       %2073 = OpExtInst %void %2 DebugLine %64 %uint_66 %uint_66 %uint_35 %uint_36
+       %1974 = OpLoad %int %1894
+       %1975 = OpIAdd %int %1974 %int_1
+               OpStore %1894 %1975
+               OpBranch %1940
+       %1976 = OpLabel
+       %2328 = OpExtInst %void %2 DebugScope %103 %1885
+       %2077 = OpExtInst %void %2 DebugLine %64 %uint_75 %uint_75 %uint_9 %uint_9
+       %1977 = OpLoad %float %1891
+       %2078 = OpExtInst %void %2 DebugLine %64 %uint_75 %uint_75 %uint_24 %uint_24
+       %1978 = OpLoad %int %1892
+       %1979 = OpConvertSToF %float %1978
+       %2080 = OpExtInst %void %2 DebugLine %64 %uint_75 %uint_75 %uint_9 %uint_24
+       %1980 = OpFDiv %float %1977 %1979
+       %2329 = OpExtInst %void %2 DebugScope %158 %1803
+       %2232 = OpExtInst %void %2 DebugLine %64 %uint_85 %uint_85 %uint_4 %uint_41
+       %2231 = OpExtInst %void %2 DebugValue %160 %1980 %243
+       %1872 = OpExtInst %void %2 DebugLine %64 %uint_90 %uint_90 %uint_3 %uint_3
+       %1835 = OpLoad %v3float %1466
+       %1873 = OpExtInst %void %2 DebugLine %64 %uint_90 %uint_90 %uint_3 %uint_16
+       %1836 = OpVectorTimesScalar %v3float %1835 %1980
+               OpStore %1466 %1836
+       %2330 = OpExtInst %void %2 DebugScope %157 %1803
+       %1875 = OpExtInst %void %2 DebugLine %64 %uint_79 %uint_79 %uint_35 %uint_37
+               OpBranch %1837
+       %1837 = OpLabel
+       %2331 = OpExtInst %void %2 DebugScope %157 %1803
+       %1876 = OpExtInst %void %2 DebugLine %64 %uint_79 %uint_79 %uint_35 %uint_37
+       %1838 = OpLoad %int %1801
+       %1839 = OpIAdd %int %1838 %int_1
+               OpStore %1801 %1839
+               OpBranch %1814
+       %1840 = OpLabel
+       %2332 = OpExtInst %void %2 DebugScope %157 %1803
+       %1880 = OpExtInst %void %2 DebugLine %64 %uint_92 %uint_92 %uint_9 %uint_9
+       %1841 = OpLoad %v3float %1466
+       %2333 = OpExtInst %void %2 DebugScope %180
+       %1793 = OpExtInst %void %2 DebugLine %64 %uint_146 %uint_146 %uint_3 %uint_40
+               OpStore %1448 %1841
+       %2334 = OpExtInst %void %2 DebugScope %179
+       %1794 = OpExtInst %void %2 DebugLine %64 %uint_147 %uint_147 %uint_2 %uint_2
+               OpBranch %1614
+       %1614 = OpLabel
+;CHECK:      %1614 = OpLabel
+;CHECK-NEXT: [[phi:%\w+]] = OpPhi 
+;CHECK-NEXT: {{%\w+}} = OpExtInst %void {{%\w+}} DebugValue %233
+       %2335 = OpExtInst %void %2 DebugScope %179
+       %1795 = OpExtInst %void %2 DebugLine %64 %uint_149 %uint_149 %uint_16 %uint_16
+       %1615 = OpLoad %v3float %1448
+       %1616 = OpCompositeExtract %float %1615 0
+       %1617 = OpCompositeExtract %float %1615 1
+       %1618 = OpCompositeExtract %float %1615 2
+       %1799 = OpExtInst %void %2 DebugLine %64 %uint_149 %uint_149 %uint_9 %uint_28
+       %1619 = OpCompositeConstruct %v4float %1616 %1617 %1618 %float_1
+       %2336 = OpExtInst %void %2 DebugNoLine
+       %2337 = OpExtInst %void %2 DebugNoScope
+               OpStore %out_var_SV_TARGET %1619
+        %329 = OpExtInst %void %2 DebugLine %64 %uint_150 %uint_150 %uint_1 %uint_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<SSARewritePass>(text, true);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //    No optimization in the presence of
diff --git a/third_party/SPIRV-Tools/test/opt/loop_optimizations/dependence_analysis.cpp b/third_party/SPIRV-Tools/test/opt/loop_optimizations/dependence_analysis.cpp
index 8aeb20a..42d9acb 100644
--- a/third_party/SPIRV-Tools/test/opt/loop_optimizations/dependence_analysis.cpp
+++ b/third_party/SPIRV-Tools/test/opt/loop_optimizations/dependence_analysis.cpp
@@ -135,7 +135,7 @@
   const Instruction* store[4];
   int stores_found = 0;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 13)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
@@ -292,7 +292,7 @@
   const Instruction* store[4];
   int stores_found = 0;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 22)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
@@ -528,7 +528,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 17)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -601,7 +601,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 68)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -922,7 +922,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 29)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -978,7 +978,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 114)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -1420,7 +1420,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 29)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1441,7 +1441,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 54)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1463,7 +1463,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 75)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1484,7 +1484,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 99)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1506,7 +1506,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 121)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1527,7 +1527,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 142)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1549,7 +1549,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 162)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1570,7 +1570,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 183)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1846,7 +1846,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 19)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -1914,7 +1914,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 54)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -1981,7 +1981,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 84)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -2049,7 +2049,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 111)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -2210,7 +2210,7 @@
   const Instruction* store[6];
   int stores_found = 0;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 11)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
@@ -2443,7 +2443,7 @@
     const Instruction* store[1];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 25)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -2479,7 +2479,7 @@
     const Instruction* store[1];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 56)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -2790,12 +2790,12 @@
   ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
 
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       load[loads_found] = &inst;
       ++loads_found;
     }
@@ -3080,12 +3080,12 @@
   ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
 
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       load[loads_found] = &inst;
       ++loads_found;
     }
@@ -3461,11 +3461,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
@@ -3502,11 +3502,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
@@ -3534,11 +3534,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
@@ -3569,11 +3569,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
@@ -3611,11 +3611,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
diff --git a/third_party/SPIRV-Tools/test/opt/loop_optimizations/dependence_analysis_helpers.cpp b/third_party/SPIRV-Tools/test/opt/loop_optimizations/dependence_analysis_helpers.cpp
index 715cf54..aabf478 100644
--- a/third_party/SPIRV-Tools/test/opt/loop_optimizations/dependence_analysis_helpers.cpp
+++ b/third_party/SPIRV-Tools/test/opt/loop_optimizations/dependence_analysis_helpers.cpp
@@ -172,7 +172,7 @@
     const Instruction* store[1] = {nullptr};
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 16)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -199,7 +199,7 @@
     const Instruction* store[1] = {nullptr};
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 47)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -1495,7 +1495,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -1576,7 +1576,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 65)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -1655,7 +1655,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 96)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -1734,7 +1734,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 126)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2067,7 +2067,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2148,7 +2148,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 66)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2229,7 +2229,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 96)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2310,7 +2310,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 127)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2705,7 +2705,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 35)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2784,7 +2784,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 90)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2863,7 +2863,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 139)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2942,7 +2942,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 188)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
diff --git a/third_party/SPIRV-Tools/test/opt/loop_optimizations/peeling.cpp b/third_party/SPIRV-Tools/test/opt/loop_optimizations/peeling.cpp
index 10d8add..4ff7a5a 100644
--- a/third_party/SPIRV-Tools/test/opt/loop_optimizations/peeling.cpp
+++ b/third_party/SPIRV-Tools/test/opt/loop_optimizations/peeling.cpp
@@ -765,7 +765,7 @@
     EXPECT_EQ(ld.NumLoops(), 1u);
 
     Instruction* loop_count = context->get_def_use_mgr()->GetDef(16);
-    EXPECT_EQ(loop_count->opcode(), SpvOpLoad);
+    EXPECT_EQ(loop_count->opcode(), spv::Op::OpLoad);
 
     LoopPeeling peel(&*ld.begin(), loop_count);
     EXPECT_TRUE(peel.CanPeelLoop());
@@ -817,7 +817,7 @@
     EXPECT_EQ(ld.NumLoops(), 1u);
 
     Instruction* loop_count = context->get_def_use_mgr()->GetDef(16);
-    EXPECT_EQ(loop_count->opcode(), SpvOpLoad);
+    EXPECT_EQ(loop_count->opcode(), spv::Op::OpLoad);
 
     LoopPeeling peel(&*ld.begin(), loop_count);
     EXPECT_TRUE(peel.CanPeelLoop());
@@ -1090,7 +1090,7 @@
     EXPECT_EQ(ld.NumLoops(), 1u);
 
     Instruction* loop_count = context->get_def_use_mgr()->GetDef(15);
-    EXPECT_EQ(loop_count->opcode(), SpvOpLoad);
+    EXPECT_EQ(loop_count->opcode(), spv::Op::OpLoad);
 
     LoopPeeling peel(&*ld.begin(), loop_count);
     EXPECT_TRUE(peel.CanPeelLoop());
@@ -1142,7 +1142,7 @@
     EXPECT_EQ(ld.NumLoops(), 1u);
 
     Instruction* loop_count = context->get_def_use_mgr()->GetDef(15);
-    EXPECT_EQ(loop_count->opcode(), SpvOpLoad);
+    EXPECT_EQ(loop_count->opcode(), spv::Op::OpLoad);
 
     LoopPeeling peel(&*ld.begin(), loop_count);
     EXPECT_TRUE(peel.CanPeelLoop());
diff --git a/third_party/SPIRV-Tools/test/opt/loop_optimizations/peeling_pass.cpp b/third_party/SPIRV-Tools/test/opt/loop_optimizations/peeling_pass.cpp
index 284ad83..1b5a12d 100644
--- a/third_party/SPIRV-Tools/test/opt/loop_optimizations/peeling_pass.cpp
+++ b/third_party/SPIRV-Tools/test/opt/loop_optimizations/peeling_pass.cpp
@@ -30,27 +30,27 @@
  public:
   // Generic routine to run the loop peeling pass and check
   LoopPeelingPass::LoopPeelingStats AssembleAndRunPeelingTest(
-      const std::string& text_head, const std::string& text_tail, SpvOp opcode,
-      const std::string& res_id, const std::string& op1,
+      const std::string& text_head, const std::string& text_tail,
+      spv::Op opcode, const std::string& res_id, const std::string& op1,
       const std::string& op2) {
     std::string opcode_str;
     switch (opcode) {
-      case SpvOpSLessThan:
+      case spv::Op::OpSLessThan:
         opcode_str = "OpSLessThan";
         break;
-      case SpvOpSGreaterThan:
+      case spv::Op::OpSGreaterThan:
         opcode_str = "OpSGreaterThan";
         break;
-      case SpvOpSLessThanEqual:
+      case spv::Op::OpSLessThanEqual:
         opcode_str = "OpSLessThanEqual";
         break;
-      case SpvOpSGreaterThanEqual:
+      case spv::Op::OpSGreaterThanEqual:
         opcode_str = "OpSGreaterThanEqual";
         break;
-      case SpvOpIEqual:
+      case spv::Op::OpIEqual:
         opcode_str = "OpIEqual";
         break;
-      case SpvOpINotEqual:
+      case spv::Op::OpINotEqual:
         opcode_str = "OpINotEqual";
         break;
       default:
@@ -69,9 +69,9 @@
 
   // Generic routine to run the loop peeling pass and check
   LoopPeelingPass::LoopPeelingStats RunPeelingTest(
-      const std::string& text_head, const std::string& text_tail, SpvOp opcode,
-      const std::string& res_id, const std::string& op1, const std::string& op2,
-      size_t nb_of_loops) {
+      const std::string& text_head, const std::string& text_tail,
+      spv::Op opcode, const std::string& res_id, const std::string& op1,
+      const std::string& op2, size_t nb_of_loops) {
     LoopPeelingPass::LoopPeelingStats stats = AssembleAndRunPeelingTest(
         text_head, text_tail, opcode, res_id, op1, op2);
 
@@ -86,7 +86,7 @@
       std::vector<std::pair<LoopPeelingPass::PeelDirection, uint32_t>>;
 
   void BuildAndCheckTrace(const std::string& text_head,
-                          const std::string& text_tail, SpvOp opcode,
+                          const std::string& text_tail, spv::Op opcode,
                           const std::string& res_id, const std::string& op1,
                           const std::string& op2,
                           const PeelTraceType& expected_peel_trace,
@@ -203,7 +203,7 @@
                OpFunctionEnd
   )";
 
-  auto run_test = [&text_head, &text_tail, this](SpvOp opcode,
+  auto run_test = [&text_head, &text_tail, this](spv::Op opcode,
                                                  const std::string& op1,
                                                  const std::string& op2) {
     auto stats =
@@ -225,7 +225,7 @@
     SCOPED_TRACE("Peel before iv < 4");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%32", "%int_4");
+        run_test(spv::Op::OpSLessThan, "%32", "%int_4");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -233,7 +233,7 @@
     SCOPED_TRACE("Peel before 4 > iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%int_4", "%32");
+        run_test(spv::Op::OpSGreaterThan, "%int_4", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -241,7 +241,7 @@
     SCOPED_TRACE("Peel before iv < 5");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%32", "%int_5");
+        run_test(spv::Op::OpSLessThan, "%32", "%int_5");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -249,7 +249,7 @@
     SCOPED_TRACE("Peel before 5 > iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%int_5", "%32");
+        run_test(spv::Op::OpSGreaterThan, "%int_5", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -259,7 +259,7 @@
     SCOPED_TRACE("Peel after iv < 16");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%32", "%int_16");
+        run_test(spv::Op::OpSLessThan, "%32", "%int_16");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -267,7 +267,7 @@
     SCOPED_TRACE("Peel after 16 > iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%int_16", "%32");
+        run_test(spv::Op::OpSGreaterThan, "%int_16", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -275,7 +275,7 @@
     SCOPED_TRACE("Peel after iv < 17");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%32", "%int_17");
+        run_test(spv::Op::OpSLessThan, "%32", "%int_17");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -283,7 +283,7 @@
     SCOPED_TRACE("Peel after 17 > iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%int_17", "%32");
+        run_test(spv::Op::OpSGreaterThan, "%int_17", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -294,7 +294,7 @@
     SCOPED_TRACE("Peel before iv > 5");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%32", "%int_5");
+        run_test(spv::Op::OpSGreaterThan, "%32", "%int_5");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -302,7 +302,7 @@
     SCOPED_TRACE("Peel before 5 < iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%int_5", "%32");
+        run_test(spv::Op::OpSLessThan, "%int_5", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -310,7 +310,7 @@
     SCOPED_TRACE("Peel before iv > 4");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%32", "%int_4");
+        run_test(spv::Op::OpSGreaterThan, "%32", "%int_4");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -318,7 +318,7 @@
     SCOPED_TRACE("Peel before 4 < iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%int_4", "%32");
+        run_test(spv::Op::OpSLessThan, "%int_4", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -328,7 +328,7 @@
     SCOPED_TRACE("Peel after iv > 16");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%32", "%int_16");
+        run_test(spv::Op::OpSGreaterThan, "%32", "%int_16");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -336,7 +336,7 @@
     SCOPED_TRACE("Peel after 16 < iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%int_16", "%32");
+        run_test(spv::Op::OpSLessThan, "%int_16", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -344,7 +344,7 @@
     SCOPED_TRACE("Peel after iv > 17");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%32", "%int_17");
+        run_test(spv::Op::OpSGreaterThan, "%32", "%int_17");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -352,7 +352,7 @@
     SCOPED_TRACE("Peel after 17 < iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%int_17", "%32");
+        run_test(spv::Op::OpSLessThan, "%int_17", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -363,7 +363,7 @@
     SCOPED_TRACE("Peel before iv <= 4");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%32", "%int_4");
+        run_test(spv::Op::OpSLessThanEqual, "%32", "%int_4");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -371,7 +371,7 @@
     SCOPED_TRACE("Peel before 4 => iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%int_4", "%32");
+        run_test(spv::Op::OpSGreaterThanEqual, "%int_4", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -379,7 +379,7 @@
     SCOPED_TRACE("Peel before iv <= 3");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%32", "%int_3");
+        run_test(spv::Op::OpSLessThanEqual, "%32", "%int_3");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -387,7 +387,7 @@
     SCOPED_TRACE("Peel before 3 => iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%int_3", "%32");
+        run_test(spv::Op::OpSGreaterThanEqual, "%int_3", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -397,7 +397,7 @@
     SCOPED_TRACE("Peel after iv <= 16");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%32", "%int_16");
+        run_test(spv::Op::OpSLessThanEqual, "%32", "%int_16");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -405,7 +405,7 @@
     SCOPED_TRACE("Peel after 16 => iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%int_16", "%32");
+        run_test(spv::Op::OpSGreaterThanEqual, "%int_16", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -413,7 +413,7 @@
     SCOPED_TRACE("Peel after iv <= 15");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%32", "%int_15");
+        run_test(spv::Op::OpSLessThanEqual, "%32", "%int_15");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -421,7 +421,7 @@
     SCOPED_TRACE("Peel after 15 => iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%int_15", "%32");
+        run_test(spv::Op::OpSGreaterThanEqual, "%int_15", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -432,7 +432,7 @@
     SCOPED_TRACE("Peel before iv >= 5");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%32", "%int_5");
+        run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_5");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -440,7 +440,7 @@
     SCOPED_TRACE("Peel before 35 >= iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%int_5", "%32");
+        run_test(spv::Op::OpSLessThanEqual, "%int_5", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -448,7 +448,7 @@
     SCOPED_TRACE("Peel before iv >= 4");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%32", "%int_4");
+        run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_4");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -456,7 +456,7 @@
     SCOPED_TRACE("Peel before 4 <= iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%int_4", "%32");
+        run_test(spv::Op::OpSLessThanEqual, "%int_4", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -466,7 +466,7 @@
     SCOPED_TRACE("Peel after iv >= 17");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%32", "%int_17");
+        run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_17");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -474,7 +474,7 @@
     SCOPED_TRACE("Peel after 17 <= iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%int_17", "%32");
+        run_test(spv::Op::OpSLessThanEqual, "%int_17", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -482,7 +482,7 @@
     SCOPED_TRACE("Peel after iv >= 16");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%32", "%int_16");
+        run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_16");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -490,7 +490,7 @@
     SCOPED_TRACE("Peel after 16 <= iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%int_16", "%32");
+        run_test(spv::Op::OpSLessThanEqual, "%int_16", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -501,7 +501,7 @@
     SCOPED_TRACE("Peel before iv == 1");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpIEqual, "%32", "%int_1");
+        run_test(spv::Op::OpIEqual, "%32", "%int_1");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -509,7 +509,7 @@
     SCOPED_TRACE("Peel before 1 == iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpIEqual, "%int_1", "%32");
+        run_test(spv::Op::OpIEqual, "%int_1", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -519,7 +519,7 @@
     SCOPED_TRACE("Peel after iv == 19");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpIEqual, "%32", "%int_19");
+        run_test(spv::Op::OpIEqual, "%32", "%int_19");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -527,7 +527,7 @@
     SCOPED_TRACE("Peel after 19 == iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpIEqual, "%int_19", "%32");
+        run_test(spv::Op::OpIEqual, "%int_19", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -538,7 +538,7 @@
     SCOPED_TRACE("Peel before iv != 1");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpINotEqual, "%32", "%int_1");
+        run_test(spv::Op::OpINotEqual, "%32", "%int_1");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -546,7 +546,7 @@
     SCOPED_TRACE("Peel before 1 != iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpINotEqual, "%int_1", "%32");
+        run_test(spv::Op::OpINotEqual, "%int_1", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -556,7 +556,7 @@
     SCOPED_TRACE("Peel after iv != 19");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpINotEqual, "%32", "%int_19");
+        run_test(spv::Op::OpINotEqual, "%32", "%int_19");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -564,7 +564,7 @@
     SCOPED_TRACE("Peel after 19 != iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpINotEqual, "%int_19", "%32");
+        run_test(spv::Op::OpINotEqual, "%int_19", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -573,7 +573,7 @@
   {
     SCOPED_TRACE("No Peel: 20 => iv");
 
-    auto stats = RunPeelingTest(text_head, text_tail, SpvOpSLessThanEqual,
+    auto stats = RunPeelingTest(text_head, text_tail, spv::Op::OpSLessThanEqual,
                                 "%22", "%int_20", "%32", 1);
 
     EXPECT_EQ(stats.peeled_loops_.size(), 0u);
@@ -673,7 +673,7 @@
   )";
 
   auto run_test = [&text_head, &text_tail, this](
-                      SpvOp opcode, const std::string& op1,
+                      spv::Op opcode, const std::string& op1,
                       const std::string& op2,
                       const PeelTraceType& expected_peel_trace) {
     BuildAndCheckTrace(text_head, text_tail, opcode, "%22", op1, op2,
@@ -685,13 +685,13 @@
   {
     SCOPED_TRACE("Peel before iv < 3");
 
-    run_test(SpvOpSLessThan, "%38", "%int_3",
+    run_test(spv::Op::OpSLessThan, "%38", "%int_3",
              {{LoopPeelingPass::PeelDirection::kBefore, 3u}});
   }
   {
     SCOPED_TRACE("Peel before 3 > iv");
 
-    run_test(SpvOpSGreaterThan, "%int_3", "%38",
+    run_test(spv::Op::OpSGreaterThan, "%int_3", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 3u}});
   }
 
@@ -699,13 +699,13 @@
   {
     SCOPED_TRACE("Peel after iv < 8");
 
-    run_test(SpvOpSLessThan, "%38", "%int_8",
+    run_test(spv::Op::OpSLessThan, "%38", "%int_8",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
   {
     SCOPED_TRACE("Peel after 8 > iv");
 
-    run_test(SpvOpSGreaterThan, "%int_8", "%38",
+    run_test(spv::Op::OpSGreaterThan, "%int_8", "%38",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
 
@@ -714,13 +714,13 @@
   {
     SCOPED_TRACE("Peel before iv > 2");
 
-    run_test(SpvOpSGreaterThan, "%38", "%int_2",
+    run_test(spv::Op::OpSGreaterThan, "%38", "%int_2",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
   {
     SCOPED_TRACE("Peel before 2 < iv");
 
-    run_test(SpvOpSLessThan, "%int_2", "%38",
+    run_test(spv::Op::OpSLessThan, "%int_2", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
 
@@ -728,13 +728,13 @@
   {
     SCOPED_TRACE("Peel after iv > 7");
 
-    run_test(SpvOpSGreaterThan, "%38", "%int_7",
+    run_test(spv::Op::OpSGreaterThan, "%38", "%int_7",
              {{LoopPeelingPass::PeelDirection::kAfter, 3u}});
   }
   {
     SCOPED_TRACE("Peel after 7 < iv");
 
-    run_test(SpvOpSLessThan, "%int_7", "%38",
+    run_test(spv::Op::OpSLessThan, "%int_7", "%38",
              {{LoopPeelingPass::PeelDirection::kAfter, 3u}});
   }
 
@@ -743,13 +743,13 @@
   {
     SCOPED_TRACE("Peel before iv <= 1");
 
-    run_test(SpvOpSLessThanEqual, "%38", "%int_1",
+    run_test(spv::Op::OpSLessThanEqual, "%38", "%int_1",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
   {
     SCOPED_TRACE("Peel before 1 => iv");
 
-    run_test(SpvOpSGreaterThanEqual, "%int_1", "%38",
+    run_test(spv::Op::OpSGreaterThanEqual, "%int_1", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
 
@@ -757,13 +757,13 @@
   {
     SCOPED_TRACE("Peel after iv <= 7");
 
-    run_test(SpvOpSLessThanEqual, "%38", "%int_7",
+    run_test(spv::Op::OpSLessThanEqual, "%38", "%int_7",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
   {
     SCOPED_TRACE("Peel after 7 => iv");
 
-    run_test(SpvOpSGreaterThanEqual, "%int_7", "%38",
+    run_test(spv::Op::OpSGreaterThanEqual, "%int_7", "%38",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
 
@@ -772,13 +772,13 @@
   {
     SCOPED_TRACE("Peel before iv >= 2");
 
-    run_test(SpvOpSGreaterThanEqual, "%38", "%int_2",
+    run_test(spv::Op::OpSGreaterThanEqual, "%38", "%int_2",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
   {
     SCOPED_TRACE("Peel before 2 <= iv");
 
-    run_test(SpvOpSLessThanEqual, "%int_2", "%38",
+    run_test(spv::Op::OpSLessThanEqual, "%int_2", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
 
@@ -786,13 +786,13 @@
   {
     SCOPED_TRACE("Peel after iv >= 8");
 
-    run_test(SpvOpSGreaterThanEqual, "%38", "%int_8",
+    run_test(spv::Op::OpSGreaterThanEqual, "%38", "%int_8",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
   {
     SCOPED_TRACE("Peel after 8 <= iv");
 
-    run_test(SpvOpSLessThanEqual, "%int_8", "%38",
+    run_test(spv::Op::OpSLessThanEqual, "%int_8", "%38",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
   // Test EQ
@@ -800,13 +800,13 @@
   {
     SCOPED_TRACE("Peel before iv == 0");
 
-    run_test(SpvOpIEqual, "%38", "%int_0",
+    run_test(spv::Op::OpIEqual, "%38", "%int_0",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
   {
     SCOPED_TRACE("Peel before 0 == iv");
 
-    run_test(SpvOpIEqual, "%int_0", "%38",
+    run_test(spv::Op::OpIEqual, "%int_0", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
 
@@ -814,13 +814,13 @@
   {
     SCOPED_TRACE("Peel after iv == 9");
 
-    run_test(SpvOpIEqual, "%38", "%int_9",
+    run_test(spv::Op::OpIEqual, "%38", "%int_9",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
   {
     SCOPED_TRACE("Peel after 9 == iv");
 
-    run_test(SpvOpIEqual, "%int_9", "%38",
+    run_test(spv::Op::OpIEqual, "%int_9", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
 
@@ -829,13 +829,13 @@
   {
     SCOPED_TRACE("Peel before iv != 0");
 
-    run_test(SpvOpINotEqual, "%38", "%int_0",
+    run_test(spv::Op::OpINotEqual, "%38", "%int_0",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
   {
     SCOPED_TRACE("Peel before 0 != iv");
 
-    run_test(SpvOpINotEqual, "%int_0", "%38",
+    run_test(spv::Op::OpINotEqual, "%int_0", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
 
@@ -843,13 +843,13 @@
   {
     SCOPED_TRACE("Peel after iv != 9");
 
-    run_test(SpvOpINotEqual, "%38", "%int_9",
+    run_test(spv::Op::OpINotEqual, "%38", "%int_9",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
   {
     SCOPED_TRACE("Peel after 9 != iv");
 
-    run_test(SpvOpINotEqual, "%int_9", "%38",
+    run_test(spv::Op::OpINotEqual, "%int_9", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
 }
@@ -952,7 +952,7 @@
 
   auto run_test =
       [&text_head, &text_tail, this](
-          SpvOp opcode, const std::string& op1, const std::string& op2,
+          spv::Op opcode, const std::string& op1, const std::string& op2,
           const PeelTraceType& expected_peel_trace, size_t nb_of_loops) {
         BuildAndCheckTrace(text_head, text_tail, opcode, "%30", op1, op2,
                            expected_peel_trace, nb_of_loops);
@@ -963,7 +963,7 @@
     SCOPED_TRACE("Peel before iv_i < 3");
 
     // Expect peel before by a factor of 3 and 4 loops at the end.
-    run_test(SpvOpSLessThan, "%42", "%int_3",
+    run_test(spv::Op::OpSLessThan, "%42", "%int_3",
              {{LoopPeelingPass::PeelDirection::kBefore, 3u}}, 4);
   }
   // Peeling outer loop after by a factor of 3.
@@ -971,7 +971,7 @@
     SCOPED_TRACE("Peel after iv_i < 7");
 
     // Expect peel after by a factor of 3 and 4 loops at the end.
-    run_test(SpvOpSLessThan, "%42", "%int_7",
+    run_test(spv::Op::OpSLessThan, "%42", "%int_7",
              {{LoopPeelingPass::PeelDirection::kAfter, 3u}}, 4);
   }
 
@@ -980,7 +980,7 @@
     SCOPED_TRACE("Peel before iv_j < 3");
 
     // Expect peel before by a factor of 3 and 3 loops at the end.
-    run_test(SpvOpSLessThan, "%46", "%int_3",
+    run_test(spv::Op::OpSLessThan, "%46", "%int_3",
              {{LoopPeelingPass::PeelDirection::kBefore, 3u}}, 3);
   }
   // Peeling inner loop after by a factor of 3.
@@ -988,7 +988,7 @@
     SCOPED_TRACE("Peel after iv_j < 7");
 
     // Expect peel after by a factor of 3 and 3 loops at the end.
-    run_test(SpvOpSLessThan, "%46", "%int_7",
+    run_test(spv::Op::OpSLessThan, "%46", "%int_7",
              {{LoopPeelingPass::PeelDirection::kAfter, 3u}}, 3);
   }
 
@@ -997,7 +997,7 @@
     SCOPED_TRACE("No peel");
 
     // Expect no peeling and 2 loops at the end.
-    run_test(SpvOpSLessThan, "%46", "%42", {}, 2);
+    run_test(spv::Op::OpSLessThan, "%46", "%42", {}, 2);
   }
 
   // Could do a peeling of 3, but the goes over the threshold.
@@ -1007,7 +1007,7 @@
     size_t current_threshold = LoopPeelingPass::GetLoopPeelingThreshold();
     LoopPeelingPass::SetLoopPeelingThreshold(1u);
     // Expect no peeling and 2 loops at the end.
-    run_test(SpvOpSLessThan, "%46", "%int_7", {}, 2);
+    run_test(spv::Op::OpSLessThan, "%46", "%int_7", {}, 2);
     LoopPeelingPass::SetLoopPeelingThreshold(current_threshold);
   }
 }
diff --git a/third_party/SPIRV-Tools/test/opt/module_test.cpp b/third_party/SPIRV-Tools/test/opt/module_test.cpp
index 17a1365..33dc05f 100644
--- a/third_party/SPIRV-Tools/test/opt/module_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/module_test.cpp
@@ -324,7 +324,7 @@
   std::unordered_set<uint32_t> non_semantic_ids;
   context->module()->ForEachInst(
       [&non_semantic_ids](const Instruction* inst) {
-        if (inst->opcode() == SpvOpExtInst) {
+        if (inst->opcode() == spv::Op::OpExtInst) {
           non_semantic_ids.insert(inst->result_id());
         }
       },
diff --git a/third_party/SPIRV-Tools/test/opt/pass_manager_test.cpp b/third_party/SPIRV-Tools/test/opt/pass_manager_test.cpp
index 4f36d5b..ec11069 100644
--- a/third_party/SPIRV-Tools/test/opt/pass_manager_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/pass_manager_test.cpp
@@ -144,8 +144,8 @@
 
   const char* name() const override { return "AppendTypeVoidInstPass"; }
   Status Process() override {
-    auto inst = MakeUnique<Instruction>(context(), SpvOpTypeVoid, 0, result_id_,
-                                        std::vector<Operand>{});
+    auto inst = MakeUnique<Instruction>(context(), spv::Op::OpTypeVoid, 0,
+                                        result_id_, std::vector<Operand>{});
     context()->AddType(std::move(inst));
     return Status::SuccessWithChange;
   }
diff --git a/third_party/SPIRV-Tools/test/opt/pass_remove_duplicates_test.cpp b/third_party/SPIRV-Tools/test/opt/pass_remove_duplicates_test.cpp
index 887fdfd..ac87db1 100644
--- a/third_party/SPIRV-Tools/test/opt/pass_remove_duplicates_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/pass_remove_duplicates_test.cpp
@@ -91,7 +91,7 @@
   std::string GetErrorMessage() const { return error_message_; }
 
   std::string ToText(const std::vector<Instruction*>& inst) {
-    std::vector<uint32_t> binary = {SpvMagicNumber, 0x10200, 0u, 2u, 0u};
+    std::vector<uint32_t> binary = {spv::MagicNumber, 0x10200, 0u, 2u, 0u};
     for (const Instruction* i : inst)
       i->ToBinaryWithoutAttachedDebugInsts(&binary);
     std::string text;
diff --git a/third_party/SPIRV-Tools/test/opt/propagator_test.cpp b/third_party/SPIRV-Tools/test/opt/propagator_test.cpp
index fb8e487..76211a5 100644
--- a/third_party/SPIRV-Tools/test/opt/propagator_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/propagator_test.cpp
@@ -107,11 +107,11 @@
 
   const auto visit_fn = [this](Instruction* instr, BasicBlock** dest_bb) {
     *dest_bb = nullptr;
-    if (instr->opcode() == SpvOpStore) {
+    if (instr->opcode() == spv::Op::OpStore) {
       uint32_t lhs_id = instr->GetSingleWordOperand(0);
       uint32_t rhs_id = instr->GetSingleWordOperand(1);
       Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id);
-      if (rhs_def->opcode() == SpvOpConstant) {
+      if (rhs_def->opcode() == spv::Op::OpConstant) {
         uint32_t val = rhs_def->GetSingleWordOperand(2);
         values_[lhs_id] = val;
         return SSAPropagator::kInteresting;
@@ -175,15 +175,15 @@
   const auto visit_fn = [this, &phi_instr](Instruction* instr,
                                            BasicBlock** dest_bb) {
     *dest_bb = nullptr;
-    if (instr->opcode() == SpvOpLoad) {
+    if (instr->opcode() == spv::Op::OpLoad) {
       uint32_t rhs_id = instr->GetSingleWordOperand(2);
       Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id);
-      if (rhs_def->opcode() == SpvOpConstant) {
+      if (rhs_def->opcode() == spv::Op::OpConstant) {
         uint32_t val = rhs_def->GetSingleWordOperand(2);
         values_[instr->result_id()] = val;
         return SSAPropagator::kInteresting;
       }
-    } else if (instr->opcode() == SpvOpPhi) {
+    } else if (instr->opcode() == spv::Op::OpPhi) {
       phi_instr = instr;
       SSAPropagator::PropStatus retval;
       for (uint32_t i = 2; i < instr->NumOperands(); i += 2) {
diff --git a/third_party/SPIRV-Tools/test/opt/scalar_analysis.cpp b/third_party/SPIRV-Tools/test/opt/scalar_analysis.cpp
index df2aa8f..14f82af 100644
--- a/third_party/SPIRV-Tools/test/opt/scalar_analysis.cpp
+++ b/third_party/SPIRV-Tools/test/opt/scalar_analysis.cpp
@@ -109,10 +109,10 @@
   const Instruction* store = nullptr;
   const Instruction* load = nullptr;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 11)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store = &inst;
     }
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       load = &inst;
     }
   }
@@ -236,7 +236,7 @@
 
   const Instruction* load = nullptr;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 28)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       load = &inst;
     }
   }
@@ -352,7 +352,7 @@
 
   const Instruction* load = nullptr;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 21)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad && inst.result_id() == 33) {
+    if (inst.opcode() == spv::Op::OpLoad && inst.result_id() == 33) {
       load = &inst;
     }
   }
@@ -506,11 +506,11 @@
   int store_count = 0;
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 22)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       loads[load_count] = &inst;
       ++load_count;
     }
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       stores[store_count] = &inst;
       ++store_count;
     }
@@ -745,11 +745,11 @@
   int store_count = 0;
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 31)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       loads[load_count] = &inst;
       ++load_count;
     }
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       stores[store_count] = &inst;
       ++store_count;
     }
@@ -880,7 +880,7 @@
   int load_count = 0;
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 29)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       loads[load_count] = &inst;
       ++load_count;
     }
@@ -1025,10 +1025,10 @@
   std::vector<const Instruction*> stores{};
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       loads.push_back(&inst);
     }
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       stores.push_back(&inst);
     }
   }
@@ -1194,7 +1194,7 @@
   std::vector<const Instruction*> phis{};
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 21)) {
-    if (inst.opcode() == SpvOp::SpvOpPhi) {
+    if (inst.opcode() == spv::Op::OpPhi) {
       phis.push_back(&inst);
     }
   }
diff --git a/third_party/SPIRV-Tools/test/opt/type_manager_test.cpp b/third_party/SPIRV-Tools/test/opt/type_manager_test.cpp
index df216bc..eebc50d 100644
--- a/third_party/SPIRV-Tools/test/opt/type_manager_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/type_manager_test.cpp
@@ -98,15 +98,19 @@
   types.emplace_back(new Matrix(v3f32, 4));
 
   // Images
-  types.emplace_back(new Image(s32, SpvDim2D, 0, 0, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
+  types.emplace_back(new Image(s32, spv::Dim::Dim2D, 0, 0, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
   auto* image1 = types.back().get();
-  types.emplace_back(new Image(s32, SpvDim2D, 0, 1, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
-  types.emplace_back(new Image(s32, SpvDim3D, 0, 1, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
-  types.emplace_back(new Image(voidt, SpvDim3D, 0, 1, 0, 1, SpvImageFormatRg8,
-                               SpvAccessQualifierReadWrite));
+  types.emplace_back(new Image(s32, spv::Dim::Dim2D, 0, 1, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new Image(s32, spv::Dim::Dim3D, 0, 1, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new Image(voidt, spv::Dim::Dim3D, 0, 1, 0, 1,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadWrite));
   auto* image2 = types.back().get();
 
   // Sampler
@@ -140,9 +144,9 @@
   types.emplace_back(new Opaque("world"));
 
   // Pointer
-  types.emplace_back(new Pointer(f32, SpvStorageClassInput));
-  types.emplace_back(new Pointer(sts32f32, SpvStorageClassFunction));
-  types.emplace_back(new Pointer(a42f32, SpvStorageClassFunction));
+  types.emplace_back(new Pointer(f32, spv::StorageClass::Input));
+  types.emplace_back(new Pointer(sts32f32, spv::StorageClass::Function));
+  types.emplace_back(new Pointer(a42f32, spv::StorageClass::Function));
 
   // Function
   types.emplace_back(new Function(voidt, {}));
@@ -158,11 +162,11 @@
 
   // Pipe, Forward Pointer, PipeStorage, NamedBarrier, AccelerationStructureNV,
   // CooperativeMatrixNV
-  types.emplace_back(new Pipe(SpvAccessQualifierReadWrite));
-  types.emplace_back(new Pipe(SpvAccessQualifierReadOnly));
-  types.emplace_back(new ForwardPointer(1, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(2, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(2, SpvStorageClassUniform));
+  types.emplace_back(new Pipe(spv::AccessQualifier::ReadWrite));
+  types.emplace_back(new Pipe(spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new ForwardPointer(1, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(2, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(2, spv::StorageClass::Uniform));
   types.emplace_back(new PipeStorage());
   types.emplace_back(new NamedBarrier());
   types.emplace_back(new AccelerationStructureNV());
@@ -814,22 +818,22 @@
   EXPECT_NE(context, nullptr);
 
   Integer u32(32, false);
-  Pointer u32Ptr(&u32, SpvStorageClassFunction);
+  Pointer u32Ptr(&u32, spv::StorageClass::Function);
   Struct st({&u32});
-  Pointer stPtr(&st, SpvStorageClassInput);
+  Pointer stPtr(&st, spv::StorageClass::Input);
 
   auto pair = context->get_type_mgr()->GetTypeAndPointerType(
-      3u, SpvStorageClassFunction);
+      3u, spv::StorageClass::Function);
   ASSERT_EQ(nullptr, pair.first);
   ASSERT_EQ(nullptr, pair.second);
 
   pair = context->get_type_mgr()->GetTypeAndPointerType(
-      1u, SpvStorageClassFunction);
+      1u, spv::StorageClass::Function);
   ASSERT_TRUE(pair.first->IsSame(&u32));
   ASSERT_TRUE(pair.second->IsSame(&u32Ptr));
 
-  pair =
-      context->get_type_mgr()->GetTypeAndPointerType(2u, SpvStorageClassInput);
+  pair = context->get_type_mgr()->GetTypeAndPointerType(
+      2u, spv::StorageClass::Input);
   ASSERT_TRUE(pair.first->IsSame(&st));
   ASSERT_TRUE(pair.second->IsSame(&stPtr));
 }
@@ -1155,7 +1159,7 @@
                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   EXPECT_NE(context, nullptr);
 
-  context->get_type_mgr()->FindPointerToType(1, SpvStorageClassFunction);
+  context->get_type_mgr()->FindPointerToType(1, spv::StorageClass::Function);
   Match(text, context.get());
 }
 
@@ -1180,7 +1184,7 @@
                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   EXPECT_NE(context, nullptr);
 
-  context->get_type_mgr()->FindPointerToType(2, SpvStorageClassFunction);
+  context->get_type_mgr()->FindPointerToType(2, spv::StorageClass::Function);
   Match(text, context.get());
 }
 
diff --git a/third_party/SPIRV-Tools/test/opt/types_test.cpp b/third_party/SPIRV-Tools/test/opt/types_test.cpp
index 552ad97..4352b7c 100644
--- a/third_party/SPIRV-Tools/test/opt/types_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/types_test.cpp
@@ -34,9 +34,9 @@
     u32_t_ = MakeUnique<Integer>(32, false);
     f64_t_ = MakeUnique<Float>(64);
     v3u32_t_ = MakeUnique<Vector>(u32_t_.get(), 3);
-    image_t_ =
-        MakeUnique<Image>(f64_t_.get(), SpvDim2D, 1, 1, 0, 0, SpvImageFormatR16,
-                          SpvAccessQualifierReadWrite);
+    image_t_ = MakeUnique<Image>(f64_t_.get(), spv::Dim::Dim2D, 1, 1, 0, 0,
+                                 spv::ImageFormat::R16,
+                                 spv::AccessQualifier::ReadWrite);
   }
 
   // Element types to be used for constructing other types for testing.
@@ -72,9 +72,9 @@
 TestMultipleInstancesOfTheSameType(Float, 64)
 TestMultipleInstancesOfTheSameType(Vector, u32_t_.get(), 3)
 TestMultipleInstancesOfTheSameType(Matrix, v3u32_t_.get(), 4)
-TestMultipleInstancesOfTheSameType(Image, f64_t_.get(), SpvDimCube, 0, 0, 1, 1,
-                                   SpvImageFormatRgb10A2,
-                                   SpvAccessQualifierWriteOnly)
+TestMultipleInstancesOfTheSameType(Image, f64_t_.get(), spv::Dim::Cube, 0, 0, 1, 1,
+                                   spv::ImageFormat::Rgb10A2,
+                                   spv::AccessQualifier::WriteOnly)
 TestMultipleInstancesOfTheSameType(Sampler)
 TestMultipleInstancesOfTheSameType(SampledImage, image_t_.get())
 // There are three classes of arrays, based on the kinds of length information
@@ -98,15 +98,15 @@
 TestMultipleInstancesOfTheSameType(Struct, std::vector<const Type*>{
                                                u32_t_.get(), f64_t_.get()})
 TestMultipleInstancesOfTheSameType(Opaque, "testing rocks")
-TestMultipleInstancesOfTheSameType(Pointer, u32_t_.get(), SpvStorageClassInput)
+TestMultipleInstancesOfTheSameType(Pointer, u32_t_.get(), spv::StorageClass::Input)
 TestMultipleInstancesOfTheSameType(Function, u32_t_.get(),
                                    {f64_t_.get(), f64_t_.get()})
 TestMultipleInstancesOfTheSameType(Event)
 TestMultipleInstancesOfTheSameType(DeviceEvent)
 TestMultipleInstancesOfTheSameType(ReserveId)
 TestMultipleInstancesOfTheSameType(Queue)
-TestMultipleInstancesOfTheSameType(Pipe, SpvAccessQualifierReadWrite)
-TestMultipleInstancesOfTheSameType(ForwardPointer, 10, SpvStorageClassUniform)
+TestMultipleInstancesOfTheSameType(Pipe, spv::AccessQualifier::ReadWrite)
+TestMultipleInstancesOfTheSameType(ForwardPointer, 10, spv::StorageClass::Uniform)
 TestMultipleInstancesOfTheSameType(PipeStorage)
 TestMultipleInstancesOfTheSameType(NamedBarrier)
 TestMultipleInstancesOfTheSameType(AccelerationStructureNV)
@@ -119,8 +119,8 @@
   std::vector<std::unique_ptr<Type>> types;
 
   // Forward Pointer
-  types.emplace_back(new ForwardPointer(10000, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(20000, SpvStorageClassInput));
+  types.emplace_back(new ForwardPointer(10000, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(20000, spv::StorageClass::Input));
 
   // Void, Bool
   types.emplace_back(new Void());
@@ -155,15 +155,19 @@
   types.emplace_back(new Matrix(v3f32, 4));
 
   // Images
-  types.emplace_back(new Image(s32, SpvDim2D, 0, 0, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
+  types.emplace_back(new Image(s32, spv::Dim::Dim2D, 0, 0, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
   auto* image1 = types.back().get();
-  types.emplace_back(new Image(s32, SpvDim2D, 0, 1, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
-  types.emplace_back(new Image(s32, SpvDim3D, 0, 1, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
-  types.emplace_back(new Image(voidt, SpvDim3D, 0, 1, 0, 1, SpvImageFormatRg8,
-                               SpvAccessQualifierReadWrite));
+  types.emplace_back(new Image(s32, spv::Dim::Dim2D, 0, 1, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new Image(s32, spv::Dim::Dim3D, 0, 1, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new Image(voidt, spv::Dim::Dim3D, 0, 1, 0, 1,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadWrite));
   auto* image2 = types.back().get();
 
   // Sampler
@@ -218,10 +222,10 @@
   types.emplace_back(new Opaque("world"));
 
   // Pointer
-  types.emplace_back(new Pointer(f32, SpvStorageClassInput));
-  types.emplace_back(new Pointer(sts32f32, SpvStorageClassFunction));
-  types.emplace_back(new Pointer(a42f32, SpvStorageClassFunction));
-  types.emplace_back(new Pointer(voidt, SpvStorageClassFunction));
+  types.emplace_back(new Pointer(f32, spv::StorageClass::Input));
+  types.emplace_back(new Pointer(sts32f32, spv::StorageClass::Function));
+  types.emplace_back(new Pointer(a42f32, spv::StorageClass::Function));
+  types.emplace_back(new Pointer(voidt, spv::StorageClass::Function));
 
   // Function
   types.emplace_back(new Function(voidt, {}));
@@ -236,11 +240,11 @@
   types.emplace_back(new Queue());
 
   // Pipe, Forward Pointer, PipeStorage, NamedBarrier
-  types.emplace_back(new Pipe(SpvAccessQualifierReadWrite));
-  types.emplace_back(new Pipe(SpvAccessQualifierReadOnly));
-  types.emplace_back(new ForwardPointer(1, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(2, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(2, SpvStorageClassUniform));
+  types.emplace_back(new Pipe(spv::AccessQualifier::ReadWrite));
+  types.emplace_back(new Pipe(spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new ForwardPointer(1, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(2, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(2, spv::StorageClass::Uniform));
   types.emplace_back(new PipeStorage());
   types.emplace_back(new NamedBarrier());
 
diff --git a/third_party/SPIRV-Tools/test/reduce/reducer_test.cpp b/third_party/SPIRV-Tools/test/reduce/reducer_test.cpp
index 276aedc..019e14e 100644
--- a/third_party/SPIRV-Tools/test/reduce/reducer_test.cpp
+++ b/third_party/SPIRV-Tools/test/reduce/reducer_test.cpp
@@ -222,7 +222,7 @@
 }
 
 bool InterestingWhileOpcodeExists(const std::vector<uint32_t>& binary,
-                                  uint32_t opcode, uint32_t count, bool dump) {
+                                  spv::Op opcode, uint32_t count, bool dump) {
   if (dump) {
     std::stringstream ss;
     ss << "temp_" << count << ".spv";
@@ -238,7 +238,7 @@
         &*function.begin(),
         [opcode, &interesting](opt::BasicBlock* block) -> void {
           for (auto& inst : *block) {
-            if (inst.opcode() == opcode) {
+            if (inst.opcode() == spv::Op(opcode)) {
               interesting = true;
               break;
             }
@@ -253,12 +253,12 @@
 
 bool InterestingWhileIMulReachable(const std::vector<uint32_t>& binary,
                                    uint32_t count) {
-  return InterestingWhileOpcodeExists(binary, SpvOpIMul, count, false);
+  return InterestingWhileOpcodeExists(binary, spv::Op::OpIMul, count, false);
 }
 
 bool InterestingWhileSDivReachable(const std::vector<uint32_t>& binary,
                                    uint32_t count) {
-  return InterestingWhileOpcodeExists(binary, SpvOpSDiv, count, false);
+  return InterestingWhileOpcodeExists(binary, spv::Op::OpSDiv, count, false);
 }
 
 // The shader below was derived from the following GLSL, and optimized.
diff --git a/third_party/SPIRV-Tools/test/reduce/validation_during_reduction_test.cpp b/third_party/SPIRV-Tools/test/reduce/validation_during_reduction_test.cpp
index d864344..8cf14a3 100644
--- a/third_party/SPIRV-Tools/test/reduce/validation_during_reduction_test.cpp
+++ b/third_party/SPIRV-Tools/test/reduce/validation_during_reduction_test.cpp
@@ -67,7 +67,7 @@
 
   bool PreconditionHolds() override {
     Instruction* first_instruction = &*function_->begin()[0].begin();
-    return first_instruction->opcode() == SpvOpVariable;
+    return first_instruction->opcode() == spv::Op::OpVariable;
   }
 
  protected:
@@ -75,7 +75,7 @@
     // Duplicate the first OpVariable instruction.
 
     Instruction* first_instruction = &*function_->begin()[0].begin();
-    assert(first_instruction->opcode() == SpvOpVariable &&
+    assert(first_instruction->opcode() == spv::Op::OpVariable &&
            "Expected first instruction to be OpVariable");
     IRContext* context = first_instruction->context();
     Instruction* cloned_instruction = first_instruction->Clone(context);
@@ -105,7 +105,7 @@
     std::vector<std::unique_ptr<ReductionOpportunity>> result;
     for (auto& function : *context->module()) {
       Instruction* first_instruction = &*function.begin()[0].begin();
-      if (first_instruction->opcode() == SpvOpVariable) {
+      if (first_instruction->opcode() == spv::Op::OpVariable) {
         result.push_back(
             MakeUnique<OpVariableDuplicatorReductionOpportunity>(&function));
       }
@@ -523,7 +523,7 @@
                OpFunctionEnd
   )";
 
-  spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
+  spv_target_env env = SPV_ENV_VULKAN_1_0;
   std::vector<uint32_t> binary_in;
   SpirvTools t(env);
 
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.annotation_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.annotation_test.cpp
index 76776de..826812b 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.annotation_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.annotation_test.cpp
@@ -41,7 +41,7 @@
 
 using OpDecorateSimpleTest =
     spvtest::TextToBinaryTestBase<::testing::TestWithParam<
-        std::tuple<spv_target_env, EnumCase<SpvDecoration>>>>;
+        std::tuple<spv_target_env, EnumCase<spv::Decoration>>>>;
 
 TEST_P(OpDecorateSimpleTest, AnySimpleDecoration) {
   // This string should assemble, but should not validate.
@@ -51,7 +51,7 @@
     input << " " << operand;
   input << std::endl;
   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
-              Eq(MakeInstruction(SpvOpDecorate,
+              Eq(MakeInstruction(spv::Op::OpDecorate,
                                  {1, uint32_t(std::get<1>(GetParam()).value())},
                                  std::get<1>(GetParam()).operands())));
   // Also check disassembly.
@@ -64,7 +64,7 @@
 // Like above, but parameters to the decoration are IDs.
 using OpDecorateSimpleIdTest =
     spvtest::TextToBinaryTestBase<::testing::TestWithParam<
-        std::tuple<spv_target_env, EnumCase<SpvDecoration>>>>;
+        std::tuple<spv_target_env, EnumCase<spv::Decoration>>>>;
 
 TEST_P(OpDecorateSimpleIdTest, AnySimpleDecoration) {
   // This string should assemble, but should not validate.
@@ -74,7 +74,7 @@
     input << " %" << operand;
   input << std::endl;
   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
-              Eq(MakeInstruction(SpvOpDecorateId,
+              Eq(MakeInstruction(spv::Op::OpDecorateId,
                                  {1, uint32_t(std::get<1>(GetParam()).value())},
                                  std::get<1>(GetParam()).operands())));
   // Also check disassembly.
@@ -84,11 +84,11 @@
       Eq(input.str()));
 }
 
-#define CASE(NAME) SpvDecoration##NAME, #NAME
+#define CASE(NAME) spv::Decoration::NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryDecorateSimple, OpDecorateSimpleTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCase<SpvDecoration>>{
+            ValuesIn(std::vector<EnumCase<spv::Decoration>>{
                 // The operand literal values are arbitrarily chosen,
                 // but there are the right number of them.
                 {CASE(RelaxedPrecision), {}},
@@ -134,23 +134,24 @@
 
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleV11, OpDecorateSimpleTest,
                          Combine(Values(SPV_ENV_UNIVERSAL_1_1),
-                                 Values(EnumCase<SpvDecoration>{
+                                 Values(EnumCase<spv::Decoration>{
                                      CASE(MaxByteOffset), {128}})));
 
-INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleV14, OpDecorateSimpleTest,
-                         Combine(Values(SPV_ENV_UNIVERSAL_1_4),
-                                 ValuesIn(std::vector<EnumCase<SpvDecoration>>{
-                                     {CASE(Uniform), {}},
-                                 })));
+INSTANTIATE_TEST_SUITE_P(
+    TextToBinaryDecorateSimpleV14, OpDecorateSimpleTest,
+    Combine(Values(SPV_ENV_UNIVERSAL_1_4),
+            ValuesIn(std::vector<EnumCase<spv::Decoration>>{
+                {CASE(Uniform), {}},
+            })));
 
-INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleIdV14,
-                         OpDecorateSimpleIdTest,
-                         Combine(Values(SPV_ENV_UNIVERSAL_1_4),
-                                 ValuesIn(std::vector<EnumCase<SpvDecoration>>{
-                                     // In 1.4, UniformId decoration takes a
-                                     // scope Id.
-                                     {CASE(UniformId), {1}},
-                                 })));
+INSTANTIATE_TEST_SUITE_P(
+    TextToBinaryDecorateSimpleIdV14, OpDecorateSimpleIdTest,
+    Combine(Values(SPV_ENV_UNIVERSAL_1_4),
+            ValuesIn(std::vector<EnumCase<spv::Decoration>>{
+                // In 1.4, UniformId decoration takes a
+                // scope Id.
+                {CASE(UniformId), {1}},
+            })));
 #undef CASE
 
 TEST_F(OpDecorateSimpleTest, WrongDecoration) {
@@ -195,14 +196,14 @@
   const std::string input =
       "OpDecorate %1 " + GetParam().enum_name + " " + GetParam().name;
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpDecorate, {1, GetParam().enum_value,
-                                                 GetParam().value})));
+              Eq(MakeInstruction(spv::Op::OpDecorate, {1, GetParam().enum_value,
+                                                       GetParam().value})));
 }
 
 // Test OpDecorate BuiltIn.
 // clang-format off
 #define CASE(NAME) \
-  { SpvBuiltIn##NAME, #NAME, SpvDecorationBuiltIn, "BuiltIn" }
+  { uint32_t(spv::BuiltIn::NAME), #NAME, uint32_t(spv::Decoration::BuiltIn), "BuiltIn" }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateBuiltIn, OpDecorateEnumTest,
                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
                             CASE(Position),
@@ -260,7 +261,7 @@
 // Test OpDecorate FuncParamAttr
 // clang-format off
 #define CASE(NAME) \
-  { SpvFunctionParameterAttribute##NAME, #NAME, SpvDecorationFuncParamAttr, "FuncParamAttr" }
+  { uint32_t(spv::FunctionParameterAttribute::NAME), #NAME, uint32_t(spv::Decoration::FuncParamAttr), "FuncParamAttr" }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFuncParamAttr, OpDecorateEnumTest,
                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
                             CASE(Zext),
@@ -283,7 +284,7 @@
 // Test OpDecorate FPRoundingMode
 // clang-format off
 #define CASE(NAME) \
-  { SpvFPRoundingMode##NAME, #NAME, SpvDecorationFPRoundingMode, "FPRoundingMode" }
+  { uint32_t(spv::FPRoundingMode::NAME), #NAME, uint32_t(spv::Decoration::FPRoundingMode), "FPRoundingMode" }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFPRoundingMode, OpDecorateEnumTest,
                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
                             CASE(RTE),
@@ -306,15 +307,15 @@
 
 // clang-format off
 #define CASE(ENUM,NAME) \
-  { SpvFPFastMathMode##ENUM, #NAME, SpvDecorationFPFastMathMode, "FPFastMathMode" }
+  { uint32_t(spv::FPFastMathModeMask::ENUM), #NAME, uint32_t(spv::Decoration::FPFastMathMode), "FPFastMathMode" }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFPFastMathMode, OpDecorateEnumTest,
                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
                             CASE(MaskNone, None),
-                            CASE(NotNaNMask, NotNaN),
-                            CASE(NotInfMask, NotInf),
-                            CASE(NSZMask, NSZ),
-                            CASE(AllowRecipMask, AllowRecip),
-                            CASE(FastMask, Fast),
+                            CASE(NotNaN, NotNaN),
+                            CASE(NotInf, NotInf),
+                            CASE(NSZ, NSZ),
+                            CASE(AllowRecip, AllowRecip),
+                            CASE(Fast, Fast),
                       }));
 #undef CASE
 // clang-format on
@@ -323,13 +324,13 @@
   // Sample a single combination.  This ensures we've integrated
   // the instruction parsing logic with spvTextParseMask.
   const std::string input = "OpDecorate %1 FPFastMathMode NotNaN|NotInf|NSZ";
-  const uint32_t expected_enum = SpvDecorationFPFastMathMode;
-  const uint32_t expected_mask = SpvFPFastMathModeNotNaNMask |
-                                 SpvFPFastMathModeNotInfMask |
-                                 SpvFPFastMathModeNSZMask;
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpDecorate, {1, expected_enum, expected_mask})));
+  const uint32_t expected_enum = uint32_t(spv::Decoration::FPFastMathMode);
+  const uint32_t expected_mask = uint32_t(spv::FPFastMathModeMask::NotNaN) |
+                                 uint32_t(spv::FPFastMathModeMask::NotInf) |
+                                 uint32_t(spv::FPFastMathModeMask::NSZ);
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpDecorate,
+                                 {1, expected_enum, expected_mask})));
 }
 
 TEST_F(OpDecorateEnumTest, WrongFPFastMathMode) {
@@ -355,7 +356,8 @@
   const std::string input = "OpDecorate %1 LinkageAttributes \"" +
                             GetParam().external_name + "\" " +
                             GetParam().linkage_type_name;
-  std::vector<uint32_t> expected_operands{1, SpvDecorationLinkageAttributes};
+  std::vector<uint32_t> expected_operands{
+      1, uint32_t(spv::Decoration::LinkageAttributes)};
   std::vector<uint32_t> encoded_external_name =
       MakeVector(GetParam().external_name);
   expected_operands.insert(expected_operands.end(),
@@ -363,11 +365,11 @@
                            encoded_external_name.end());
   expected_operands.push_back(GetParam().linkage_type_value);
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpDecorate, expected_operands)));
+              Eq(MakeInstruction(spv::Op::OpDecorate, expected_operands)));
 }
 
 // clang-format off
-#define CASE(ENUM) SpvLinkageType##ENUM, #ENUM
+#define CASE(ENUM) uint32_t(spv::LinkageType::ENUM), #ENUM
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateLinkage, OpDecorateLinkageTest,
                         ::testing::ValuesIn(std::vector<DecorateLinkageCase>{
                             { CASE(Import), "a" },
@@ -387,13 +389,13 @@
 
 TEST_F(TextToBinaryTest, GroupMemberDecorateGoodOneTarget) {
   EXPECT_THAT(CompiledInstructions("OpGroupMemberDecorate %group %id0 42"),
-              Eq(MakeInstruction(SpvOpGroupMemberDecorate, {1, 2, 42})));
+              Eq(MakeInstruction(spv::Op::OpGroupMemberDecorate, {1, 2, 42})));
 }
 
 TEST_F(TextToBinaryTest, GroupMemberDecorateGoodTwoTargets) {
   EXPECT_THAT(
       CompiledInstructions("OpGroupMemberDecorate %group %id0 96 %id1 42"),
-      Eq(MakeInstruction(SpvOpGroupMemberDecorate, {1, 2, 96, 3, 42})));
+      Eq(MakeInstruction(spv::Op::OpGroupMemberDecorate, {1, 2, 96, 3, 42})));
 }
 
 TEST_F(TextToBinaryTest, GroupMemberDecorateMissingGroupId) {
@@ -443,7 +445,7 @@
 
 using OpMemberDecorateSimpleTest =
     spvtest::TextToBinaryTestBase<::testing::TestWithParam<
-        std::tuple<spv_target_env, EnumCase<SpvDecoration>>>>;
+        std::tuple<spv_target_env, EnumCase<spv::Decoration>>>>;
 
 TEST_P(OpMemberDecorateSimpleTest, AnySimpleDecoration) {
   // This string should assemble, but should not validate.
@@ -454,7 +456,7 @@
   input << std::endl;
   EXPECT_THAT(
       CompiledInstructions(input.str(), std::get<0>(GetParam())),
-      Eq(MakeInstruction(SpvOpMemberDecorate,
+      Eq(MakeInstruction(spv::Op::OpMemberDecorate,
                          {1, 42, uint32_t(std::get<1>(GetParam()).value())},
                          std::get<1>(GetParam()).operands())));
   // Also check disassembly.
@@ -464,11 +466,11 @@
       Eq(input.str()));
 }
 
-#define CASE(NAME) SpvDecoration##NAME, #NAME
+#define CASE(NAME) spv::Decoration::NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryDecorateSimple, OpMemberDecorateSimpleTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCase<SpvDecoration>>{
+            ValuesIn(std::vector<EnumCase<spv::Decoration>>{
                 // The operand literal values are arbitrarily chosen,
                 // but there are the right number of them.
                 {CASE(RelaxedPrecision), {}},
@@ -515,7 +517,7 @@
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryDecorateSimpleV11, OpMemberDecorateSimpleTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
-            Values(EnumCase<SpvDecoration>{CASE(MaxByteOffset), {128}})));
+            Values(EnumCase<spv::Decoration>{CASE(MaxByteOffset), {128}})));
 #undef CASE
 
 TEST_F(OpMemberDecorateSimpleTest, WrongDecoration) {
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.barrier_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.barrier_test.cpp
index f1cb4fbe..380cacb 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.barrier_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.barrier_test.cpp
@@ -37,7 +37,7 @@
 TEST_F(OpMemoryBarrier, Good) {
   const std::string input = "OpMemoryBarrier %1 %2\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpMemoryBarrier, {1, 2})));
+              Eq(MakeInstruction(spv::Op::OpMemoryBarrier, {1, 2})));
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
@@ -89,7 +89,7 @@
   EXPECT_THAT(
       CompiledInstructions("OpMemoryNamedBarrier %bar %scope %semantics",
                            SPV_ENV_UNIVERSAL_1_0),
-      ElementsAre(spvOpcodeMake(4, SpvOpMemoryNamedBarrier), _, _, _));
+      ElementsAre(spvOpcodeMake(4, spv::Op::OpMemoryNamedBarrier), _, _, _));
 }
 
 TEST_F(NamedMemoryBarrierTest, ArgumentCount) {
@@ -107,7 +107,7 @@
   EXPECT_THAT(
       CompiledInstructions("OpMemoryNamedBarrier %bar %scope %semantics",
                            SPV_ENV_UNIVERSAL_1_1),
-      ElementsAre(spvOpcodeMake(4, SpvOpMemoryNamedBarrier), _, _, _));
+      ElementsAre(spvOpcodeMake(4, spv::Op::OpMemoryNamedBarrier), _, _, _));
   EXPECT_THAT(
       CompileFailure("OpMemoryNamedBarrier %bar %scope %semantics %extra",
                      SPV_ENV_UNIVERSAL_1_1),
@@ -128,7 +128,7 @@
 TEST_F(TypeNamedBarrierTest, OpcodeAssemblesInV10) {
   EXPECT_THAT(
       CompiledInstructions("%t = OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_0),
-      ElementsAre(spvOpcodeMake(2, SpvOpTypeNamedBarrier), _));
+      ElementsAre(spvOpcodeMake(2, spv::Op::OpTypeNamedBarrier), _));
 }
 
 TEST_F(TypeNamedBarrierTest, ArgumentCount) {
@@ -137,7 +137,7 @@
                  "found 'OpTypeNamedBarrier'."));
   EXPECT_THAT(
       CompiledInstructions("%t = OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_1),
-      ElementsAre(spvOpcodeMake(2, SpvOpTypeNamedBarrier), _));
+      ElementsAre(spvOpcodeMake(2, spv::Op::OpTypeNamedBarrier), _));
   EXPECT_THAT(
       CompileFailure("%t = OpTypeNamedBarrier 1 2 3", SPV_ENV_UNIVERSAL_1_1),
       Eq("Expected <opcode> or <result-id> at the beginning of an instruction, "
@@ -150,7 +150,8 @@
   EXPECT_THAT(
       CompiledInstructions("%bar = OpNamedBarrierInitialize %type %count",
                            SPV_ENV_UNIVERSAL_1_0),
-      ElementsAre(spvOpcodeMake(4, SpvOpNamedBarrierInitialize), _, _, _));
+      ElementsAre(spvOpcodeMake(4, spv::Op::OpNamedBarrierInitialize), _, _,
+                  _));
 }
 
 TEST_F(NamedBarrierInitializeTest, ArgumentCount) {
@@ -165,7 +166,8 @@
   EXPECT_THAT(
       CompiledInstructions("%bar = OpNamedBarrierInitialize %type %count",
                            SPV_ENV_UNIVERSAL_1_1),
-      ElementsAre(spvOpcodeMake(4, SpvOpNamedBarrierInitialize), _, _, _));
+      ElementsAre(spvOpcodeMake(4, spv::Op::OpNamedBarrierInitialize), _, _,
+                  _));
   EXPECT_THAT(
       CompileFailure("%bar = OpNamedBarrierInitialize %type %count \"extra\"",
                      SPV_ENV_UNIVERSAL_1_1),
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.constant_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.constant_test.cpp
index 7ab4ca5..bc5cd06 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.constant_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.constant_test.cpp
@@ -35,21 +35,21 @@
 // Test Sampler Addressing Mode enum values
 
 using SamplerAddressingModeTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvSamplerAddressingMode>>>;
+    ::testing::TestWithParam<EnumCase<spv::SamplerAddressingMode>>>;
 
 TEST_P(SamplerAddressingModeTest, AnySamplerAddressingMode) {
   const std::string input =
       "%result = OpConstantSampler %type " + GetParam().name() + " 0 Nearest";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpConstantSampler,
-                                 {1, 2, GetParam().value(), 0, 0})));
+              Eq(MakeInstruction(spv::Op::OpConstantSampler,
+                                 {1, 2, uint32_t(GetParam().value()), 0, 0})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvSamplerAddressingMode##NAME, #NAME }
+#define CASE(NAME) { spv::SamplerAddressingMode::NAME, #NAME }
 INSTANTIATE_TEST_SUITE_P(
     TextToBinarySamplerAddressingMode, SamplerAddressingModeTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvSamplerAddressingMode>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::SamplerAddressingMode>>{
         CASE(None),
         CASE(ClampToEdge),
         CASE(Clamp),
@@ -67,21 +67,21 @@
 // Test Sampler Filter Mode enum values
 
 using SamplerFilterModeTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvSamplerFilterMode>>>;
+    ::testing::TestWithParam<EnumCase<spv::SamplerFilterMode>>>;
 
 TEST_P(SamplerFilterModeTest, AnySamplerFilterMode) {
   const std::string input =
       "%result = OpConstantSampler %type Clamp 0 " + GetParam().name();
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpConstantSampler,
-                                 {1, 2, 2, 0, GetParam().value()})));
+              Eq(MakeInstruction(spv::Op::OpConstantSampler,
+                                 {1, 2, 2, 0, uint32_t(GetParam().value())})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvSamplerFilterMode##NAME, #NAME}
+#define CASE(NAME) { spv::SamplerFilterMode::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     TextToBinarySamplerFilterMode, SamplerFilterModeTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvSamplerFilterMode>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::SamplerFilterMode>>{
         CASE(Nearest),
         CASE(Linear),
     }));
@@ -119,119 +119,119 @@
     ::testing::ValuesIn(std::vector<ConstantTestCase>{
       // Check 16 bits
       {"OpTypeInt 16 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x1234})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234})})},
       {"OpTypeInt 16 0", "0x8000",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x8000})})},
       {"OpTypeInt 16 0", "0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 16 0", "65535",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 65535})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 65535})})},
       {"OpTypeInt 16 0", "0xffff",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 65535})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 65535})})},
       {"OpTypeInt 16 1", "0x8000", // Test sign extension.
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffff8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffff8000})})},
       {"OpTypeInt 16 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32)})})},
       {"OpTypeInt 16 1", "0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 16 1", "-0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 16 1", "-0x0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 16 1", "-32768",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32768)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32768)})})},
       // Check 32 bits
       {"OpTypeInt 32 0", "42",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 42})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 42})})},
       {"OpTypeInt 32 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32)})})},
       {"OpTypeInt 32 1", "0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 32 1", "-0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 32 1", "-0x0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 32 1", "-0x001",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-1)})})},
       {"OpTypeInt 32 1", "2147483647",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7fffffffu})})},
       {"OpTypeInt 32 1", "-2147483648",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x80000000u})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x80000000u})})},
       {"OpTypeFloat 32", "1.0",
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x3f800000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x3f800000})})},
       {"OpTypeFloat 32", "10.0",
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x41200000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x41200000})})},
       {"OpTypeFloat 32", "-0x1p+128", // -infinity
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xFF800000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFF800000})})},
       {"OpTypeFloat 32", "0x1p+128", // +infinity
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x7F800000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7F800000})})},
       {"OpTypeFloat 32", "-0x1.8p+128", // A -NaN
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xFFC00000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFFC00000})})},
       {"OpTypeFloat 32", "-0x1.0002p+128", // A +NaN
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xFF800100})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFF800100})})},
       // Check 48 bits
       {"OpTypeInt 48 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 48 0", "0x800000000001",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 1, 0x00008000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 1, 0x00008000})})},
       {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0, 0xffff8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0, 0xffff8000})})},
       {"OpTypeInt 48 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
       // Check 64 bits
       {"OpTypeInt 64 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 64 0", "18446744073709551615",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
       {"OpTypeInt 64 0", "0xffffffffffffffff",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
       {"OpTypeInt 64 1", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 64 1", "-42",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
       {"OpTypeInt 64 1", "-0x01",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
       {"OpTypeInt 64 1", "9223372036854775807",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})},
       {"OpTypeInt 64 1", "0x7fffffff",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7fffffffu, 0})})},
     }));
 // clang-format on
 
@@ -388,53 +388,53 @@
     ::testing::ValuesIn(std::vector<ConstantTestCase>{
       // Check 16 bits
       {"OpTypeInt 16 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234})})},
       {"OpTypeInt 16 0", "0x8000",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x8000})})},
       {"OpTypeInt 16 1", "0x8000", // Test sign extension.
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0xffff8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0xffff8000})})},
       {"OpTypeInt 16 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32)})})},
       // Check 32 bits
       {"OpTypeInt 32 0", "42",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 42})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 42})})},
       {"OpTypeInt 32 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32)})})},
       {"OpTypeFloat 32", "1.0",
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x3f800000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x3f800000})})},
       {"OpTypeFloat 32", "10.0",
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x41200000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x41200000})})},
       // Check 48 bits
       {"OpTypeInt 48 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 48 0", "0x800000000001",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 1, 0x00008000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 1, 0x00008000})})},
       {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0, 0xffff8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0, 0xffff8000})})},
       {"OpTypeInt 48 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
       // Check 64 bits
       {"OpTypeInt 64 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 64 1", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 64 1", "-42",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
     }));
 // clang-format on
 
@@ -648,7 +648,7 @@
 // Test OpSpecConstantOp
 
 using OpSpecConstantOpTestWithIds =
-    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
+    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
 
 // The operands to the OpSpecConstantOp opcode are all Ids.
 TEST_P(OpSpecConstantOpTestWithIds, Assembly) {
@@ -658,7 +658,7 @@
   input << "\n";
 
   EXPECT_THAT(CompiledInstructions(input.str()),
-              Eq(MakeInstruction(SpvOpSpecConstantOp,
+              Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
                                  {1, 2, uint32_t(GetParam().value())},
                                  GetParam().operands())));
 
@@ -667,15 +667,15 @@
 }
 
 // clang-format off
-#define CASE1(NAME) { SpvOp##NAME, #NAME, {3} }
-#define CASE2(NAME) { SpvOp##NAME, #NAME, {3, 4} }
-#define CASE3(NAME) { SpvOp##NAME, #NAME, {3, 4, 5} }
-#define CASE4(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6} }
-#define CASE5(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6, 7} }
-#define CASE6(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6, 7, 8} }
+#define CASE1(NAME) { spv::Op::Op##NAME, #NAME, {3} }
+#define CASE2(NAME) { spv::Op::Op##NAME, #NAME, {3, 4} }
+#define CASE3(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5} }
+#define CASE4(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6} }
+#define CASE5(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6, 7} }
+#define CASE6(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6, 7, 8} }
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryOpSpecConstantOp, OpSpecConstantOpTestWithIds,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvOp>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
         // Conversion
         CASE1(SConvert),
         CASE1(FConvert),
@@ -759,7 +759,7 @@
 // clang-format on
 
 using OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers =
-    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
+    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
 
 // The operands to the OpSpecConstantOp opcode are two Ids followed by a
 // sequence of literal numbers.
@@ -770,7 +770,7 @@
   input << "\n";
 
   EXPECT_THAT(CompiledInstructions(input.str()),
-              Eq(MakeInstruction(SpvOpSpecConstantOp,
+              Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
                                  {1, 2, uint32_t(GetParam().value()), 3, 4},
                                  GetParam().operands())));
 
@@ -778,11 +778,11 @@
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
 }
 
-#define CASE(NAME) SpvOp##NAME, #NAME
+#define CASE(NAME) spv::Op::Op##NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryOpSpecConstantOp,
     OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvOp>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
         // For VectorShuffle, there are two vector operands, and at least
         // two selector Ids.  OpenCL can have up to 16-element vectors.
         {CASE(VectorShuffle), {0, 0}},
@@ -797,7 +797,7 @@
     }));
 
 using OpSpecConstantOpTestWithOneIdThenLiteralNumbers =
-    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
+    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
 
 // The operands to the OpSpecConstantOp opcode are one Id followed by a
 // sequence of literal numbers.
@@ -808,7 +808,7 @@
   input << "\n";
 
   EXPECT_THAT(CompiledInstructions(input.str()),
-              Eq(MakeInstruction(SpvOpSpecConstantOp,
+              Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
                                  {1, 2, uint32_t(GetParam().value()), 3},
                                  GetParam().operands())));
 
@@ -816,11 +816,11 @@
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
 }
 
-#define CASE(NAME) SpvOp##NAME, #NAME
+#define CASE(NAME) spv::Op::Op##NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryOpSpecConstantOp,
     OpSpecConstantOpTestWithOneIdThenLiteralNumbers,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvOp>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
         // For CompositeExtract, the universal limit permits up to 255 literal
         // indices.  Let's only test a few.
         {CASE(CompositeExtract), {0}},
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.control_flow_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.control_flow_test.cpp
index 472cb6d..bc64aa3 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.control_flow_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.control_flow_test.cpp
@@ -40,22 +40,22 @@
 // Test OpSelectionMerge
 
 using OpSelectionMergeTest = spvtest::TextToBinaryTestBase<
-    TestWithParam<EnumCase<SpvSelectionControlMask>>>;
+    TestWithParam<EnumCase<spv::SelectionControlMask>>>;
 
 TEST_P(OpSelectionMergeTest, AnySingleSelectionControlMask) {
   const std::string input = "OpSelectionMerge %1 " + GetParam().name();
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpSelectionMerge, {1, GetParam().value()})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpSelectionMerge,
+                                 {1, uint32_t(GetParam().value())})));
 }
 
 // clang-format off
-#define CASE(VALUE,NAME) { SpvSelectionControl##VALUE, NAME}
+#define CASE(VALUE,NAME) { spv::SelectionControlMask::VALUE, NAME}
 INSTANTIATE_TEST_SUITE_P(TextToBinarySelectionMerge, OpSelectionMergeTest,
-                        ValuesIn(std::vector<EnumCase<SpvSelectionControlMask>>{
+                        ValuesIn(std::vector<EnumCase<spv::SelectionControlMask>>{
                             CASE(MaskNone, "None"),
-                            CASE(FlattenMask, "Flatten"),
-                            CASE(DontFlattenMask, "DontFlatten"),
+                            CASE(Flatten, "Flatten"),
+                            CASE(DontFlatten, "DontFlatten"),
                         }));
 #undef CASE
 // clang-format on
@@ -63,9 +63,11 @@
 TEST_F(OpSelectionMergeTest, CombinedSelectionControlMask) {
   const std::string input = "OpSelectionMerge %1 Flatten|DontFlatten";
   const uint32_t expected_mask =
-      SpvSelectionControlFlattenMask | SpvSelectionControlDontFlattenMask;
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpSelectionMerge, {1, expected_mask})));
+      uint32_t(spv::SelectionControlMask::Flatten |
+               spv::SelectionControlMask::DontFlatten);
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpSelectionMerge, {1, expected_mask})));
 }
 
 TEST_F(OpSelectionMergeTest, WrongSelectionControl) {
@@ -85,15 +87,15 @@
   input << "OpLoopMerge %merge %continue " << ctrl.name();
   for (auto num : ctrl.operands()) input << " " << num;
   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
-              Eq(MakeInstruction(SpvOpLoopMerge, {1, 2, ctrl.value()},
+              Eq(MakeInstruction(spv::Op::OpLoopMerge, {1, 2, ctrl.value()},
                                  ctrl.operands())));
 }
 
 #define CASE(VALUE, NAME) \
-  { SpvLoopControl##VALUE, NAME }
-#define CASE1(VALUE, NAME, PARM)          \
-  {                                       \
-    SpvLoopControl##VALUE, NAME, { PARM } \
+  { int32_t(spv::LoopControlMask::VALUE), NAME }
+#define CASE1(VALUE, NAME, PARM)                         \
+  {                                                      \
+    int32_t(spv::LoopControlMask::VALUE), NAME, { PARM } \
   }
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryLoopMerge, OpLoopMergeTest,
@@ -101,8 +103,8 @@
             ValuesIn(std::vector<EnumCase<int>>{
                 // clang-format off
                 CASE(MaskNone, "None"),
-                CASE(UnrollMask, "Unroll"),
-                CASE(DontUnrollMask, "DontUnroll"),
+                CASE(Unroll, "Unroll"),
+                CASE(DontUnroll, "DontUnroll"),
                 // clang-format on
             })));
 
@@ -111,9 +113,9 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCase<int>>{
                 // clang-format off
-                CASE(DependencyInfiniteMask, "DependencyInfinite"),
-                CASE1(DependencyLengthMask, "DependencyLength", 234),
-                {SpvLoopControlUnrollMask|SpvLoopControlDependencyLengthMask,
+                CASE(DependencyInfinite, "DependencyInfinite"),
+                CASE1(DependencyLength, "DependencyLength", 234),
+                {int32_t(spv::LoopControlMask::Unroll|spv::LoopControlMask::DependencyLength),
                       "DependencyLength|Unroll", {33}},
                 // clang-format on
             })));
@@ -123,9 +125,9 @@
 TEST_F(OpLoopMergeTest, CombinedLoopControlMask) {
   const std::string input = "OpLoopMerge %merge %continue Unroll|DontUnroll";
   const uint32_t expected_mask =
-      SpvLoopControlUnrollMask | SpvLoopControlDontUnrollMask;
+      uint32_t(spv::LoopControlMask::Unroll | spv::LoopControlMask::DontUnroll);
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpLoopMerge, {1, 2, expected_mask})));
+              Eq(MakeInstruction(spv::Op::OpLoopMerge, {1, 2, expected_mask})));
 }
 
 TEST_F(OpLoopMergeTest, WrongLoopControl) {
@@ -137,16 +139,17 @@
 
 TEST_F(TextToBinaryTest, SwitchGoodZeroTargets) {
   EXPECT_THAT(CompiledInstructions("OpSwitch %selector %default"),
-              Eq(MakeInstruction(SpvOpSwitch, {1, 2})));
+              Eq(MakeInstruction(spv::Op::OpSwitch, {1, 2})));
 }
 
 TEST_F(TextToBinaryTest, SwitchGoodOneTarget) {
-  EXPECT_THAT(CompiledInstructions("%1 = OpTypeInt 32 0\n"
-                                   "%2 = OpConstant %1 52\n"
-                                   "OpSwitch %2 %default 12 %target0"),
-              Eq(Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-                              MakeInstruction(SpvOpConstant, {1, 2, 52}),
-                              MakeInstruction(SpvOpSwitch, {2, 3, 12, 4})})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpTypeInt 32 0\n"
+                           "%2 = OpConstant %1 52\n"
+                           "OpSwitch %2 %default 12 %target0"),
+      Eq(Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+                      MakeInstruction(spv::Op::OpConstant, {1, 2, 52}),
+                      MakeInstruction(spv::Op::OpSwitch, {2, 3, 12, 4})})));
 }
 
 TEST_F(TextToBinaryTest, SwitchGoodTwoTargets) {
@@ -155,9 +158,9 @@
                            "%2 = OpConstant %1 52\n"
                            "OpSwitch %2 %default 12 %target0 42 %target1"),
       Eq(Concatenate({
-          MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-          MakeInstruction(SpvOpConstant, {1, 2, 52}),
-          MakeInstruction(SpvOpSwitch, {2, 3, 12, 4, 42, 5}),
+          MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+          MakeInstruction(spv::Op::OpConstant, {1, 2, 52}),
+          MakeInstruction(spv::Op::OpSwitch, {2, 3, 12, 4, 42, 5}),
       })));
 }
 
@@ -246,11 +249,11 @@
       constant_str,
       case_value_str,
       {Concatenate(
-          {MakeInstruction(SpvOpTypeInt,
+          {MakeInstruction(spv::Op::OpTypeInt,
                            {1, integer_width, integer_signedness}),
-           MakeInstruction(SpvOpConstant,
+           MakeInstruction(spv::Op::OpConstant,
                            Concatenate({{1, 2}, encoded_constant})),
-           MakeInstruction(SpvOpSwitch,
+           MakeInstruction(spv::Op::OpSwitch,
                            Concatenate({{2, 3}, encoded_case_value, {4}}))})}};
 }
 
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.debug_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.debug_test.cpp
index 39ba5c5..013107b 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.debug_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.debug_test.cpp
@@ -39,7 +39,7 @@
     return static_cast<uint32_t>(language_value);
   }
   const char* language_name;
-  SpvSourceLanguage language_value;
+  spv::SourceLanguage language_value;
   uint32_t version;
 };
 
@@ -47,7 +47,7 @@
 // The list of OpSource cases to use.
 const LanguageCase kLanguageCases[] = {
 #define CASE(NAME, VERSION) \
-  { #NAME, SpvSourceLanguage##NAME, VERSION }
+  { #NAME, spv::SourceLanguage::NAME, VERSION }
   CASE(Unknown, 0),
   CASE(Unknown, 999),
   CASE(ESSL, 310),
@@ -69,9 +69,10 @@
   const std::string input = std::string("OpSource ") +
                             GetParam().language_name + " " +
                             std::to_string(GetParam().version);
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpSource, {GetParam().get_language_value(),
-                                               GetParam().version})));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpSource, {GetParam().get_language_value(),
+                                             GetParam().version})));
 }
 
 INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpSourceTest,
@@ -87,7 +88,8 @@
   const std::string input = "OpSource GLSL 450 %file_id";
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpSource, {SpvSourceLanguageGLSL, 450, 1})));
+      Eq(MakeInstruction(spv::Op::OpSource,
+                         {uint32_t(spv::SourceLanguage::GLSL), 450, 1})));
 }
 
 TEST_F(TextToBinaryTest, OpSourceAcceptsOptionalSourceText) {
@@ -95,7 +97,8 @@
   const std::string input =
       "OpSource GLSL 450 %file_id \"" + fake_source + "\"";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpSource, {SpvSourceLanguageGLSL, 450, 1},
+              Eq(MakeInstruction(spv::Op::OpSource,
+                                 {uint32_t(spv::SourceLanguage::GLSL), 450, 1},
                                  MakeVector(fake_source))));
 }
 
@@ -110,7 +113,7 @@
       std::string("OpSourceContinued \"") + GetParam() + "\"";
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpSourceContinued, MakeVector(GetParam()))));
+      Eq(MakeInstruction(spv::Op::OpSourceContinued, MakeVector(GetParam()))));
 }
 
 // TODO(dneto): utf-8, quoting, escaping
@@ -129,7 +132,7 @@
       std::string("OpSourceExtension \"") + GetParam() + "\"";
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpSourceExtension, MakeVector(GetParam()))));
+      Eq(MakeInstruction(spv::Op::OpSourceExtension, MakeVector(GetParam()))));
 }
 
 // TODO(dneto): utf-8, quoting, escaping
@@ -139,12 +142,12 @@
 
 TEST_F(TextToBinaryTest, OpLine) {
   EXPECT_THAT(CompiledInstructions("OpLine %srcfile 42 99"),
-              Eq(MakeInstruction(SpvOpLine, {1, 42, 99})));
+              Eq(MakeInstruction(spv::Op::OpLine, {1, 42, 99})));
 }
 
 TEST_F(TextToBinaryTest, OpNoLine) {
   EXPECT_THAT(CompiledInstructions("OpNoLine"),
-              Eq(MakeInstruction(SpvOpNoLine, {})));
+              Eq(MakeInstruction(spv::Op::OpNoLine, {})));
 }
 
 using OpStringTest =
@@ -154,8 +157,9 @@
   // TODO(dneto): utf-8, quoting, escaping
   const std::string input =
       std::string("%result = OpString \"") + GetParam() + "\"";
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpString, {1}, MakeVector(GetParam()))));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpString, {1}, MakeVector(GetParam()))));
 }
 
 // TODO(dneto): utf-8, quoting, escaping
@@ -169,8 +173,9 @@
 TEST_P(OpNameTest, AnyString) {
   const std::string input =
       std::string("OpName %target \"") + GetParam() + "\"";
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpName, {1}, MakeVector(GetParam()))));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpName, {1}, MakeVector(GetParam()))));
 }
 
 // UTF-8, quoting, escaping, etc. are covered in the StringLiterals tests in
@@ -185,9 +190,9 @@
   // TODO(dneto): utf-8, quoting, escaping
   const std::string input =
       std::string("OpMemberName %type 42 \"") + GetParam() + "\"";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpMemberName, {1, 42}, MakeVector(GetParam()))));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpMemberName, {1, 42},
+                                 MakeVector(GetParam()))));
 }
 
 // TODO(dneto): utf-8, quoting, escaping
@@ -205,7 +210,7 @@
       std::string("OpModuleProcessed \"") + GetParam() + "\"";
   EXPECT_THAT(
       CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpModuleProcessed, MakeVector(GetParam()))));
+      Eq(MakeInstruction(spv::Op::OpModuleProcessed, MakeVector(GetParam()))));
 }
 
 INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpModuleProcessedTest,
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.device_side_enqueue_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.device_side_enqueue_test.cpp
index 2f4dd70..7f424f3 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.device_side_enqueue_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.device_side_enqueue_test.cpp
@@ -44,7 +44,7 @@
       " %wait_events %ret_event %invoke %param %param_size %param_align " +
       GetParam().local_size_source;
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpEnqueueKernel,
+              Eq(MakeInstruction(spv::Op::OpEnqueueKernel,
                                  {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
                                  GetParam().local_size_operands)));
 }
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.extension_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.extension_test.cpp
index cf4919a..6780c7e 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.extension_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.extension_test.cpp
@@ -87,12 +87,14 @@
   EXPECT_THAT(
       CompiledInstructions(input),
       Eq(Concatenate({
-          MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("OpenCL.std")),
-          MakeInstruction(SpvOpExtInstImport, {2}, MakeVector("GLSL.std.450")),
+          MakeInstruction(spv::Op::OpExtInstImport, {1},
+                          MakeVector("OpenCL.std")),
+          MakeInstruction(spv::Op::OpExtInstImport, {2},
+                          MakeVector("GLSL.std.450")),
           MakeInstruction(
-              SpvOpExtInst,
+              spv::Op::OpExtInst,
               {3, 4, 1, uint32_t(OpenCLLIB::Entrypoints::Native_sqrt), 5}),
-          MakeInstruction(SpvOpExtInst,
+          MakeInstruction(spv::Op::OpExtInst,
                           {6, 7, 2, uint32_t(GLSLstd450MatrixInverse), 8}),
       })));
 
@@ -140,62 +142,74 @@
     SPV_KHR_shader_ballot, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
-                   SPV_ENV_VULKAN_1_0),
-            ValuesIn(std::vector<AssemblyCase>{
-                {"OpCapability SubgroupBallotKHR\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilitySubgroupBallotKHR})},
-                {"%2 = OpSubgroupBallotKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupBallotKHR, {1, 2, 3})},
-                {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupFirstInvocationKHR, {1, 2, 3})},
-                {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupEqMaskKHR})},
-                {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGeMaskKHR})},
-                {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGtMaskKHR})},
-                {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLeMaskKHR})},
-                {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLtMaskKHR})},
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
+               SPV_ENV_VULKAN_1_0),
+        ValuesIn(std::vector<AssemblyCase>{
+            {"OpCapability SubgroupBallotKHR\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {uint32_t(spv::Capability::SubgroupBallotKHR)})},
+            {"%2 = OpSubgroupBallotKHR %1 %3\n",
+             MakeInstruction(spv::Op::OpSubgroupBallotKHR, {1, 2, 3})},
+            {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
+             MakeInstruction(spv::Op::OpSubgroupFirstInvocationKHR, {1, 2, 3})},
+            {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupEqMaskKHR)})},
+            {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupGeMaskKHR)})},
+            {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupGtMaskKHR)})},
+            {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupLeMaskKHR)})},
+            {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupLtMaskKHR)})},
+        })));
 
 INSTANTIATE_TEST_SUITE_P(
     SPV_KHR_shader_ballot_vulkan_1_1, ExtensionRoundTripTest,
     // In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the
     // builtin enums.
-    Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
-            ValuesIn(std::vector<AssemblyCase>{
-                {"OpCapability SubgroupBallotKHR\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilitySubgroupBallotKHR})},
-                {"%2 = OpSubgroupBallotKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupBallotKHR, {1, 2, 3})},
-                {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupFirstInvocationKHR, {1, 2, 3})},
-                {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupEqMask})},
-                {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGeMask})},
-                {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGtMask})},
-                {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLeMask})},
-                {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLtMask})},
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
+        ValuesIn(std::vector<AssemblyCase>{
+            {"OpCapability SubgroupBallotKHR\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::SubgroupBallotKHR})},
+            {"%2 = OpSubgroupBallotKHR %1 %3\n",
+             MakeInstruction(spv::Op::OpSubgroupBallotKHR, {1, 2, 3})},
+            {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
+             MakeInstruction(spv::Op::OpSubgroupFirstInvocationKHR, {1, 2, 3})},
+            {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupEqMask)})},
+            {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupGeMask)})},
+            {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupGtMask)})},
+            {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupLeMask)})},
+            {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupLtMask)})},
+        })));
 
 // The old builtin names (with KHR suffix) still work in the assembler, and
 // map to the enums without the KHR.
@@ -206,20 +220,25 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpDecorate %1 BuiltIn SubgroupEqMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupEqMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupEqMask})},
                 {"OpDecorate %1 BuiltIn SubgroupGeMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGeMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupGeMask})},
                 {"OpDecorate %1 BuiltIn SubgroupGtMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGtMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupGtMask})},
                 {"OpDecorate %1 BuiltIn SubgroupLeMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLeMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupLeMask})},
                 {"OpDecorate %1 BuiltIn SubgroupLtMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLtMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupLtMask})},
             })));
 
 // SPV_KHR_shader_draw_parameters
@@ -228,21 +247,24 @@
     SPV_KHR_shader_draw_parameters, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(
-        ValuesIn(CommonVulkanEnvs()),
-        ValuesIn(std::vector<AssemblyCase>{
-            {"OpCapability DrawParameters\n",
-             MakeInstruction(SpvOpCapability, {SpvCapabilityDrawParameters})},
-            {"OpDecorate %1 BuiltIn BaseVertex\n",
-             MakeInstruction(SpvOpDecorate,
-                             {1, SpvDecorationBuiltIn, SpvBuiltInBaseVertex})},
-            {"OpDecorate %1 BuiltIn BaseInstance\n",
-             MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                             SpvBuiltInBaseInstance})},
-            {"OpDecorate %1 BuiltIn DrawIndex\n",
-             MakeInstruction(SpvOpDecorate,
-                             {1, SpvDecorationBuiltIn, SpvBuiltInDrawIndex})},
-        })));
+    Combine(ValuesIn(CommonVulkanEnvs()),
+            ValuesIn(std::vector<AssemblyCase>{
+                {"OpCapability DrawParameters\n",
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::DrawParameters})},
+                {"OpDecorate %1 BuiltIn BaseVertex\n",
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::BaseVertex})},
+                {"OpDecorate %1 BuiltIn BaseInstance\n",
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::BaseInstance})},
+                {"OpDecorate %1 BuiltIn DrawIndex\n",
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::DrawIndex})},
+            })));
 
 // SPV_KHR_subgroup_vote
 
@@ -253,14 +275,14 @@
     Combine(ValuesIn(CommonVulkanEnvs()),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpCapability SubgroupVoteKHR\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilitySubgroupVoteKHR})},
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::SubgroupVoteKHR})},
                 {"%2 = OpSubgroupAnyKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupAnyKHR, {1, 2, 3})},
+                 MakeInstruction(spv::Op::OpSubgroupAnyKHR, {1, 2, 3})},
                 {"%2 = OpSubgroupAllKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupAllKHR, {1, 2, 3})},
+                 MakeInstruction(spv::Op::OpSubgroupAllKHR, {1, 2, 3})},
                 {"%2 = OpSubgroupAllEqualKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupAllEqualKHR, {1, 2, 3})},
+                 MakeInstruction(spv::Op::OpSubgroupAllEqualKHR, {1, 2, 3})},
             })));
 
 // SPV_KHR_16bit_storage
@@ -269,42 +291,50 @@
     SPV_KHR_16bit_storage, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(ValuesIn(CommonVulkanEnvs()),
-            ValuesIn(std::vector<AssemblyCase>{
-                {"OpCapability StorageBuffer16BitAccess\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageUniformBufferBlock16})},
-                {"OpCapability StorageBuffer16BitAccess\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageBuffer16BitAccess})},
-                {"OpCapability UniformAndStorageBuffer16BitAccess\n",
-                 MakeInstruction(
-                     SpvOpCapability,
-                     {SpvCapabilityUniformAndStorageBuffer16BitAccess})},
-                {"OpCapability UniformAndStorageBuffer16BitAccess\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageUniform16})},
-                {"OpCapability StoragePushConstant16\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStoragePushConstant16})},
-                {"OpCapability StorageInputOutput16\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageInputOutput16})},
-            })));
+    Combine(
+        ValuesIn(CommonVulkanEnvs()),
+        ValuesIn(std::vector<AssemblyCase>{
+            {"OpCapability StorageBuffer16BitAccess\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StorageUniformBufferBlock16})},
+            {"OpCapability StorageBuffer16BitAccess\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StorageBuffer16BitAccess})},
+            {"OpCapability UniformAndStorageBuffer16BitAccess\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)
+                      spv::Capability::UniformAndStorageBuffer16BitAccess})},
+            {"OpCapability UniformAndStorageBuffer16BitAccess\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::StorageUniform16})},
+            {"OpCapability StoragePushConstant16\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StoragePushConstant16})},
+            {"OpCapability StorageInputOutput16\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StorageInputOutput16})},
+        })));
 
 INSTANTIATE_TEST_SUITE_P(
     SPV_KHR_16bit_storage_alias_check, ExtensionAssemblyTest,
-    Combine(ValuesIn(CommonVulkanEnvs()),
-            ValuesIn(std::vector<AssemblyCase>{
-                // The old name maps to the new enum.
-                {"OpCapability StorageUniformBufferBlock16\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageBuffer16BitAccess})},
-                // The new name maps to the old enum.
-                {"OpCapability UniformAndStorageBuffer16BitAccess\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageUniform16})},
-            })));
+    Combine(
+        ValuesIn(CommonVulkanEnvs()),
+        ValuesIn(std::vector<AssemblyCase>{
+            // The old name maps to the new enum.
+            {"OpCapability StorageUniformBufferBlock16\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StorageBuffer16BitAccess})},
+            // The new name maps to the old enum.
+            {"OpCapability UniformAndStorageBuffer16BitAccess\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::StorageUniform16})},
+        })));
 
 // SPV_KHR_device_group
 
@@ -315,10 +345,12 @@
     Combine(ValuesIn(CommonVulkanEnvs()),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpCapability DeviceGroup\n",
-                 MakeInstruction(SpvOpCapability, {SpvCapabilityDeviceGroup})},
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::DeviceGroup})},
                 {"OpDecorate %1 BuiltIn DeviceIndex\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInDeviceIndex})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::DeviceIndex})},
             })));
 
 // SPV_KHR_8bit_storage
@@ -327,19 +359,22 @@
     SPV_KHR_8bit_storage, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(
-        ValuesIn(CommonVulkanEnvs()),
-        ValuesIn(std::vector<AssemblyCase>{
-            {"OpCapability StorageBuffer8BitAccess\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityStorageBuffer8BitAccess})},
-            {"OpCapability UniformAndStorageBuffer8BitAccess\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityUniformAndStorageBuffer8BitAccess})},
-            {"OpCapability StoragePushConstant8\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityStoragePushConstant8})},
-        })));
+    Combine(ValuesIn(CommonVulkanEnvs()),
+            ValuesIn(std::vector<AssemblyCase>{
+                {"OpCapability StorageBuffer8BitAccess\n",
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)spv::Capability::StorageBuffer8BitAccess})},
+                {"OpCapability UniformAndStorageBuffer8BitAccess\n",
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)
+                          spv::Capability::UniformAndStorageBuffer8BitAccess})},
+                {"OpCapability StoragePushConstant8\n",
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)spv::Capability::StoragePushConstant8})},
+            })));
 
 // SPV_KHR_multiview
 
@@ -351,10 +386,12 @@
                    SPV_ENV_VULKAN_1_0),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpCapability MultiView\n",
-                 MakeInstruction(SpvOpCapability, {SpvCapabilityMultiView})},
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::MultiView})},
                 {"OpDecorate %1 BuiltIn ViewIndex\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInViewIndex})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::ViewIndex})},
             })));
 
 // SPV_AMD_shader_explicit_vertex_parameter
@@ -372,9 +409,9 @@
             {PREAMBLE "%3 = OpExtInst %2 %1 InterpolateAtVertexAMD %4 %5\n",
              Concatenate(
                  {MakeInstruction(
-                      SpvOpExtInstImport, {1},
+                      spv::Op::OpExtInstImport, {1},
                       MakeVector("SPV_AMD_shader_explicit_vertex_parameter")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 1, 4, 5})})},
         })));
 #undef PREAMBLE
 
@@ -391,49 +428,49 @@
         ValuesIn(std::vector<AssemblyCase>{
             {PREAMBLE "%3 = OpExtInst %2 %1 FMin3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 1, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 UMin3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 2, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 SMin3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 3, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 3, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 FMax3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 4, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 4, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 UMax3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 5, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 5, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 SMax3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 6, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 6, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 FMid3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 7, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 7, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 UMid3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 8, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 8, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 SMid3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 9, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 9, 4, 5, 6})})},
         })));
 #undef PREAMBLE
 
@@ -444,22 +481,25 @@
     SPV_AMD_gcn_shader, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
-                   SPV_ENV_VULKAN_1_0),
-            ValuesIn(std::vector<AssemblyCase>{
-                {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceIndexAMD %4\n",
-                 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
-                                              MakeVector("SPV_AMD_gcn_shader")),
-                              MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4})})},
-                {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceCoordAMD %4\n",
-                 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
-                                              MakeVector("SPV_AMD_gcn_shader")),
-                              MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4})})},
-                {PREAMBLE "%3 = OpExtInst %2 %1 TimeAMD\n",
-                 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
-                                              MakeVector("SPV_AMD_gcn_shader")),
-                              MakeInstruction(SpvOpExtInst, {2, 3, 1, 3})})},
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
+               SPV_ENV_VULKAN_1_0),
+        ValuesIn(std::vector<AssemblyCase>{
+            {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceIndexAMD %4\n",
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                          MakeVector("SPV_AMD_gcn_shader")),
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 1, 4})})},
+            {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceCoordAMD %4\n",
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                          MakeVector("SPV_AMD_gcn_shader")),
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 2, 4})})},
+            {PREAMBLE "%3 = OpExtInst %2 %1 TimeAMD\n",
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                          MakeVector("SPV_AMD_gcn_shader")),
+                          MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 3})})},
+        })));
 #undef PREAMBLE
 
 // SPV_AMD_shader_ballot
@@ -474,23 +514,26 @@
                SPV_ENV_VULKAN_1_0),
         ValuesIn(std::vector<AssemblyCase>{
             {PREAMBLE "%3 = OpExtInst %2 %1 SwizzleInvocationsAMD %4 %5\n",
-             Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
                                           MakeVector("SPV_AMD_shader_ballot")),
-                          MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5})})},
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 1, 4, 5})})},
             {PREAMBLE
              "%3 = OpExtInst %2 %1 SwizzleInvocationsMaskedAMD %4 %5\n",
-             Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
                                           MakeVector("SPV_AMD_shader_ballot")),
-                          MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4, 5})})},
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 2, 4, 5})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 WriteInvocationAMD %4 %5 %6\n",
-             Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
                                           MakeVector("SPV_AMD_shader_ballot")),
-                          MakeInstruction(SpvOpExtInst,
+                          MakeInstruction(spv::Op::OpExtInst,
                                           {2, 3, 1, 3, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 MbcntAMD %4\n",
-             Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
                                           MakeVector("SPV_AMD_shader_ballot")),
-                          MakeInstruction(SpvOpExtInst, {2, 3, 1, 4, 4})})},
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 4, 4})})},
         })));
 #undef PREAMBLE
 
@@ -500,16 +543,18 @@
     SPV_KHR_variable_pointers, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
-                   SPV_ENV_VULKAN_1_0),
-            ValuesIn(std::vector<AssemblyCase>{
-                {"OpCapability VariablePointers\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityVariablePointers})},
-                {"OpCapability VariablePointersStorageBuffer\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityVariablePointersStorageBuffer})},
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
+               SPV_ENV_VULKAN_1_0),
+        ValuesIn(std::vector<AssemblyCase>{
+            {"OpCapability VariablePointers\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::VariablePointers})},
+            {"OpCapability VariablePointersStorageBuffer\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::VariablePointersStorageBuffer})},
+        })));
 
 // SPV_KHR_vulkan_memory_model
 
@@ -528,126 +573,145 @@
                SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpCapability VulkanMemoryModel\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityVulkanMemoryModelKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::VulkanMemoryModelKHR})},
             {"OpCapability VulkanMemoryModelDeviceScope\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityVulkanMemoryModelDeviceScopeKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::VulkanMemoryModelDeviceScopeKHR})},
             {"OpMemoryModel Logical Vulkan\n",
-             MakeInstruction(SpvOpMemoryModel, {SpvAddressingModelLogical,
-                                                SpvMemoryModelVulkanKHR})},
+             MakeInstruction(spv::Op::OpMemoryModel,
+                             {(uint32_t)spv::AddressingModel::Logical,
+                              (uint32_t)spv::MemoryModel::VulkanKHR})},
             {"OpStore %1 %2 MakePointerAvailable %3\n",
-             MakeInstruction(SpvOpStore,
-                             {1, 2, SpvMemoryAccessMakePointerAvailableKHRMask,
-                              3})},
+             MakeInstruction(
+                 spv::Op::OpStore,
+                 {1, 2,
+                  (uint32_t)spv::MemoryAccessMask::MakePointerAvailableKHR,
+                  3})},
             {"OpStore %1 %2 Volatile|MakePointerAvailable %3\n",
-             MakeInstruction(SpvOpStore,
-                             {1, 2,
-                              int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                                  int(SpvMemoryAccessVolatileMask),
-                              3})},
+             MakeInstruction(
+                 spv::Op::OpStore,
+                 {1, 2,
+                  int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                      int(spv::MemoryAccessMask::Volatile),
+                  3})},
             {"OpStore %1 %2 Aligned|MakePointerAvailable 4 %3\n",
-             MakeInstruction(SpvOpStore,
-                             {1, 2,
-                              int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                                  int(SpvMemoryAccessAlignedMask),
-                              4, 3})},
+             MakeInstruction(
+                 spv::Op::OpStore,
+                 {1, 2,
+                  int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                      int(spv::MemoryAccessMask::Aligned),
+                  4, 3})},
             {"OpStore %1 %2 MakePointerAvailable|NonPrivatePointer %3\n",
-             MakeInstruction(SpvOpStore,
-                             {1, 2,
-                              int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                                  int(SpvMemoryAccessNonPrivatePointerKHRMask),
-                              3})},
+             MakeInstruction(
+                 spv::Op::OpStore,
+                 {1, 2,
+                  int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                      int(spv::MemoryAccessMask::NonPrivatePointerKHR),
+                  3})},
             {"%2 = OpLoad %1 %3 MakePointerVisible %4\n",
-             MakeInstruction(SpvOpLoad,
-                             {1, 2, 3, SpvMemoryAccessMakePointerVisibleKHRMask,
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpLoad,
+                 {1, 2, 3,
+                  (uint32_t)spv::MemoryAccessMask::MakePointerVisibleKHR, 4})},
             {"%2 = OpLoad %1 %3 Volatile|MakePointerVisible %4\n",
-             MakeInstruction(SpvOpLoad,
-                             {1, 2, 3,
-                              int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                                  int(SpvMemoryAccessVolatileMask),
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpLoad,
+                 {1, 2, 3,
+                  int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                      int(spv::MemoryAccessMask::Volatile),
+                  4})},
             {"%2 = OpLoad %1 %3 Aligned|MakePointerVisible 8 %4\n",
-             MakeInstruction(SpvOpLoad,
-                             {1, 2, 3,
-                              int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                                  int(SpvMemoryAccessAlignedMask),
-                              8, 4})},
+             MakeInstruction(
+                 spv::Op::OpLoad,
+                 {1, 2, 3,
+                  int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                      int(spv::MemoryAccessMask::Aligned),
+                  8, 4})},
             {"%2 = OpLoad %1 %3 MakePointerVisible|NonPrivatePointer "
              "%4\n",
-             MakeInstruction(SpvOpLoad,
-                             {1, 2, 3,
-                              int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                                  int(SpvMemoryAccessNonPrivatePointerKHRMask),
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpLoad,
+                 {1, 2, 3,
+                  int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                      int(spv::MemoryAccessMask::NonPrivatePointerKHR),
+                  4})},
             {"OpCopyMemory %1 %2 "
              "MakePointerAvailable|"
              "MakePointerVisible|"
              "NonPrivatePointer "
              "%3 %4\n",
-             MakeInstruction(SpvOpCopyMemory,
-                             {1, 2,
-                              (int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                               int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                               int(SpvMemoryAccessNonPrivatePointerKHRMask)),
-                              3, 4})},
+             MakeInstruction(
+                 spv::Op::OpCopyMemory,
+                 {1, 2,
+                  (int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                   int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                   int(spv::MemoryAccessMask::NonPrivatePointerKHR)),
+                  3, 4})},
             {"OpCopyMemorySized %1 %2 %3 "
              "MakePointerAvailable|"
              "MakePointerVisible|"
              "NonPrivatePointer "
              "%4 %5\n",
-             MakeInstruction(SpvOpCopyMemorySized,
-                             {1, 2, 3,
-                              (int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                               int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                               int(SpvMemoryAccessNonPrivatePointerKHRMask)),
-                              4, 5})},
+             MakeInstruction(
+                 spv::Op::OpCopyMemorySized,
+                 {1, 2, 3,
+                  (int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                   int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                   int(spv::MemoryAccessMask::NonPrivatePointerKHR)),
+                  4, 5})},
             // Image operands
             {"OpImageWrite %1 %2 %3 MakeTexelAvailable "
              "%4\n",
              MakeInstruction(
-                 SpvOpImageWrite,
-                 {1, 2, 3, int(SpvImageOperandsMakeTexelAvailableKHRMask), 4})},
+                 spv::Op::OpImageWrite,
+                 {1, 2, 3, int(spv::ImageOperandsMask::MakeTexelAvailableKHR),
+                  4})},
             {"OpImageWrite %1 %2 %3 MakeTexelAvailable|NonPrivateTexel "
              "%4\n",
-             MakeInstruction(SpvOpImageWrite,
-                             {1, 2, 3,
-                              int(SpvImageOperandsMakeTexelAvailableKHRMask) |
-                                  int(SpvImageOperandsNonPrivateTexelKHRMask),
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpImageWrite,
+                 {1, 2, 3,
+                  int(spv::ImageOperandsMask::MakeTexelAvailableKHR) |
+                      int(spv::ImageOperandsMask::NonPrivateTexelKHR),
+                  4})},
             {"OpImageWrite %1 %2 %3 "
              "MakeTexelAvailable|NonPrivateTexel|VolatileTexel "
              "%4\n",
-             MakeInstruction(SpvOpImageWrite,
-                             {1, 2, 3,
-                              int(SpvImageOperandsMakeTexelAvailableKHRMask) |
-                                  int(SpvImageOperandsNonPrivateTexelKHRMask) |
-                                  int(SpvImageOperandsVolatileTexelKHRMask),
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpImageWrite,
+                 {1, 2, 3,
+                  int(spv::ImageOperandsMask::MakeTexelAvailableKHR) |
+                      int(spv::ImageOperandsMask::NonPrivateTexelKHR) |
+                      int(spv::ImageOperandsMask::VolatileTexelKHR),
+                  4})},
             {"%2 = OpImageRead %1 %3 %4 MakeTexelVisible "
              "%5\n",
-             MakeInstruction(SpvOpImageRead,
+             MakeInstruction(spv::Op::OpImageRead,
                              {1, 2, 3, 4,
-                              int(SpvImageOperandsMakeTexelVisibleKHRMask),
+                              int(spv::ImageOperandsMask::MakeTexelVisibleKHR),
                               5})},
             {"%2 = OpImageRead %1 %3 %4 "
              "MakeTexelVisible|NonPrivateTexel "
              "%5\n",
-             MakeInstruction(SpvOpImageRead,
-                             {1, 2, 3, 4,
-                              int(SpvImageOperandsMakeTexelVisibleKHRMask) |
-                                  int(SpvImageOperandsNonPrivateTexelKHRMask),
-                              5})},
+             MakeInstruction(
+                 spv::Op::OpImageRead,
+                 {1, 2, 3, 4,
+                  int(spv::ImageOperandsMask::MakeTexelVisibleKHR) |
+                      int(spv::ImageOperandsMask::NonPrivateTexelKHR),
+                  5})},
             {"%2 = OpImageRead %1 %3 %4 "
              "MakeTexelVisible|NonPrivateTexel|VolatileTexel "
              "%5\n",
-             MakeInstruction(SpvOpImageRead,
-                             {1, 2, 3, 4,
-                              int(SpvImageOperandsMakeTexelVisibleKHRMask) |
-                                  int(SpvImageOperandsNonPrivateTexelKHRMask) |
-                                  int(SpvImageOperandsVolatileTexelKHRMask),
-                              5})},
+             MakeInstruction(
+                 spv::Op::OpImageRead,
+                 {1, 2, 3, 4,
+                  int(spv::ImageOperandsMask::MakeTexelVisibleKHR) |
+                      int(spv::ImageOperandsMask::NonPrivateTexelKHR) |
+                      int(spv::ImageOperandsMask::VolatileTexelKHR),
+                  5})},
 
             // Memory semantics ID values are numbers put into a SPIR-V
             // constant integer referenced by Id. There is no token for
@@ -670,20 +734,20 @@
                SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpDecorateString %1 UserSemantic \"ABC\"\n",
-             MakeInstruction(SpvOpDecorateStringGOOGLE,
-                             {1, SpvDecorationHlslSemanticGOOGLE},
+             MakeInstruction(spv::Op::OpDecorateStringGOOGLE,
+                             {1, (uint32_t)spv::Decoration::HlslSemanticGOOGLE},
                              MakeVector("ABC"))},
             {"OpDecorateString %1 UserSemantic \"ABC\"\n",
-             MakeInstruction(SpvOpDecorateString,
-                             {1, SpvDecorationUserSemantic},
+             MakeInstruction(spv::Op::OpDecorateString,
+                             {1, (uint32_t)spv::Decoration::UserSemantic},
                              MakeVector("ABC"))},
             {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n",
-             MakeInstruction(SpvOpMemberDecorateStringGOOGLE,
-                             {1, 3, SpvDecorationUserSemantic},
+             MakeInstruction(spv::Op::OpMemberDecorateStringGOOGLE,
+                             {1, 3, (uint32_t)spv::Decoration::UserSemantic},
                              MakeVector("DEF"))},
             {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n",
-             MakeInstruction(SpvOpMemberDecorateString,
-                             {1, 3, SpvDecorationUserSemantic},
+             MakeInstruction(spv::Op::OpMemberDecorateString,
+                             {1, 3, (uint32_t)spv::Decoration::UserSemantic},
                              MakeVector("DEF"))},
         })));
 
@@ -696,12 +760,13 @@
                SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE \"ABC\"\n",
-             MakeInstruction(SpvOpDecorateStringGOOGLE,
-                             {1, SpvDecorationHlslSemanticGOOGLE},
+             MakeInstruction(spv::Op::OpDecorateStringGOOGLE,
+                             {1, (uint32_t)spv::Decoration::HlslSemanticGOOGLE},
                              MakeVector("ABC"))},
             {"OpMemberDecorateStringGOOGLE %1 3 HlslSemanticGOOGLE \"DEF\"\n",
-             MakeInstruction(SpvOpMemberDecorateStringGOOGLE,
-                             {1, 3, SpvDecorationHlslSemanticGOOGLE},
+             MakeInstruction(spv::Op::OpMemberDecorateStringGOOGLE,
+                             {1, 3,
+                              (uint32_t)spv::Decoration::HlslSemanticGOOGLE},
                              MakeVector("DEF"))},
         })));
 
@@ -721,11 +786,12 @@
         // they are coupled together.
         ValuesIn(std::vector<AssemblyCase>{
             {"OpDecorateId %1 CounterBuffer %2\n",
-             MakeInstruction(SpvOpDecorateId,
-                             {1, SpvDecorationHlslCounterBufferGOOGLE, 2})},
+             MakeInstruction(
+                 spv::Op::OpDecorateId,
+                 {1, (uint32_t)spv::Decoration::HlslCounterBufferGOOGLE, 2})},
             {"OpDecorateId %1 CounterBuffer %2\n",
-             MakeInstruction(SpvOpDecorateId,
-                             {1, SpvDecorationCounterBuffer, 2})},
+             MakeInstruction(spv::Op::OpDecorateId,
+                             {1, (uint32_t)spv::Decoration::CounterBuffer, 2})},
         })));
 
 INSTANTIATE_TEST_SUITE_P(
@@ -739,8 +805,9 @@
         // they are coupled together.
         ValuesIn(std::vector<AssemblyCase>{
             {"OpDecorateId %1 HlslCounterBufferGOOGLE %2\n",
-             MakeInstruction(SpvOpDecorateId,
-                             {1, SpvDecorationHlslCounterBufferGOOGLE, 2})},
+             MakeInstruction(
+                 spv::Op::OpDecorateId,
+                 {1, (uint32_t)spv::Decoration::HlslCounterBufferGOOGLE, 2})},
         })));
 
 // SPV_NV_viewport_array2
@@ -752,23 +819,26 @@
                    SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_NV_viewport_array2\"\n",
-                 MakeInstruction(SpvOpExtension,
+                 MakeInstruction(spv::Op::OpExtension,
                                  MakeVector("SPV_NV_viewport_array2"))},
                 // The EXT and NV extensions have the same token number for this
                 // capability.
                 {"OpCapability ShaderViewportIndexLayerEXT\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityShaderViewportIndexLayerNV})},
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)spv::Capability::ShaderViewportIndexLayerNV})},
                 // Check the new capability's token number
                 {"OpCapability ShaderViewportIndexLayerEXT\n",
-                 MakeInstruction(SpvOpCapability, {5254})},
+                 MakeInstruction(spv::Op::OpCapability, {5254})},
                 // Decorations
                 {"OpDecorate %1 ViewportRelativeNV\n",
-                 MakeInstruction(SpvOpDecorate,
-                                 {1, SpvDecorationViewportRelativeNV})},
+                 MakeInstruction(
+                     spv::Op::OpDecorate,
+                     {1, (uint32_t)spv::Decoration::ViewportRelativeNV})},
                 {"OpDecorate %1 BuiltIn ViewportMaskNV\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInViewportMaskNV})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::ViewportMaskNV})},
             })));
 
 // SPV_NV_shader_subgroup_partitioned
@@ -779,38 +849,44 @@
         Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_NV_shader_subgroup_partitioned\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_NV_shader_subgroup_partitioned"))},
             {"OpCapability GroupNonUniformPartitionedNV\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityGroupNonUniformPartitionedNV})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::GroupNonUniformPartitionedNV})},
             // Check the new capability's token number
             {"OpCapability GroupNonUniformPartitionedNV\n",
-             MakeInstruction(SpvOpCapability, {5297})},
+             MakeInstruction(spv::Op::OpCapability, {5297})},
             {"%2 = OpGroupNonUniformPartitionNV %1 %3\n",
-             MakeInstruction(SpvOpGroupNonUniformPartitionNV, {1, 2, 3})},
+             MakeInstruction(spv::Op::OpGroupNonUniformPartitionNV, {1, 2, 3})},
             // Check the new instruction's token number
             {"%2 = OpGroupNonUniformPartitionNV %1 %3\n",
-             MakeInstruction(static_cast<SpvOp>(5296), {1, 2, 3})},
+             MakeInstruction(static_cast<spv::Op>(5296), {1, 2, 3})},
             // Check the new group operations
             {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd,
-                             {1, 2, 3, SpvGroupOperationPartitionedReduceNV,
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpGroupIAdd,
+                 {1, 2, 3, (uint32_t)spv::GroupOperation::PartitionedReduceNV,
+                  4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 6, 4})},
+             MakeInstruction(spv::Op::OpGroupIAdd, {1, 2, 3, 6, 4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd,
-                             {1, 2, 3,
-                              SpvGroupOperationPartitionedInclusiveScanNV, 4})},
+             MakeInstruction(
+                 spv::Op::OpGroupIAdd,
+                 {1, 2, 3,
+                  (uint32_t)spv::GroupOperation::PartitionedInclusiveScanNV,
+                  4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 7, 4})},
+             MakeInstruction(spv::Op::OpGroupIAdd, {1, 2, 3, 7, 4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd,
-                             {1, 2, 3,
-                              SpvGroupOperationPartitionedExclusiveScanNV, 4})},
+             MakeInstruction(
+                 spv::Op::OpGroupIAdd,
+                 {1, 2, 3,
+                  (uint32_t)spv::GroupOperation::PartitionedExclusiveScanNV,
+                  4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 8, 4})},
+             MakeInstruction(spv::Op::OpGroupIAdd, {1, 2, 3, 8, 4})},
         })));
 
 // SPV_EXT_descriptor_indexing
@@ -823,86 +899,90 @@
                SPV_ENV_VULKAN_1_1),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_EXT_descriptor_indexing\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_EXT_descriptor_indexing"))},
             // Check capabilities, by name
             {"OpCapability ShaderNonUniform\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityShaderNonUniformEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::ShaderNonUniformEXT})},
             {"OpCapability RuntimeDescriptorArray\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityRuntimeDescriptorArrayEXT})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::RuntimeDescriptorArrayEXT})},
             {"OpCapability InputAttachmentArrayDynamicIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityInputAttachmentArrayDynamicIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  InputAttachmentArrayDynamicIndexingEXT})},
             {"OpCapability UniformTexelBufferArrayDynamicIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  UniformTexelBufferArrayDynamicIndexingEXT})},
             {"OpCapability StorageTexelBufferArrayDynamicIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  StorageTexelBufferArrayDynamicIndexingEXT})},
             {"OpCapability UniformBufferArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityUniformBufferArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  UniformBufferArrayNonUniformIndexingEXT})},
             {"OpCapability SampledImageArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilitySampledImageArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  SampledImageArrayNonUniformIndexingEXT})},
             {"OpCapability StorageBufferArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityStorageBufferArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  StorageBufferArrayNonUniformIndexingEXT})},
             {"OpCapability StorageImageArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityStorageImageArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  StorageImageArrayNonUniformIndexingEXT})},
             {"OpCapability InputAttachmentArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  InputAttachmentArrayNonUniformIndexingEXT})},
             {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n",
              MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT})},
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::
+                      UniformTexelBufferArrayNonUniformIndexingEXT})},
             {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n",
              MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT})},
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::
+                      StorageTexelBufferArrayNonUniformIndexingEXT})},
             // Check capabilities, by number
             {"OpCapability ShaderNonUniform\n",
-             MakeInstruction(SpvOpCapability, {5301})},
+             MakeInstruction(spv::Op::OpCapability, {5301})},
             {"OpCapability RuntimeDescriptorArray\n",
-             MakeInstruction(SpvOpCapability, {5302})},
+             MakeInstruction(spv::Op::OpCapability, {5302})},
             {"OpCapability InputAttachmentArrayDynamicIndexing\n",
-             MakeInstruction(SpvOpCapability, {5303})},
+             MakeInstruction(spv::Op::OpCapability, {5303})},
             {"OpCapability UniformTexelBufferArrayDynamicIndexing\n",
-             MakeInstruction(SpvOpCapability, {5304})},
+             MakeInstruction(spv::Op::OpCapability, {5304})},
             {"OpCapability StorageTexelBufferArrayDynamicIndexing\n",
-             MakeInstruction(SpvOpCapability, {5305})},
+             MakeInstruction(spv::Op::OpCapability, {5305})},
             {"OpCapability UniformBufferArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5306})},
+             MakeInstruction(spv::Op::OpCapability, {5306})},
             {"OpCapability SampledImageArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5307})},
+             MakeInstruction(spv::Op::OpCapability, {5307})},
             {"OpCapability StorageBufferArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5308})},
+             MakeInstruction(spv::Op::OpCapability, {5308})},
             {"OpCapability StorageImageArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5309})},
+             MakeInstruction(spv::Op::OpCapability, {5309})},
             {"OpCapability InputAttachmentArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5310})},
+             MakeInstruction(spv::Op::OpCapability, {5310})},
             {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5311})},
+             MakeInstruction(spv::Op::OpCapability, {5311})},
             {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5312})},
+             MakeInstruction(spv::Op::OpCapability, {5312})},
 
             // Check the decoration token
             {"OpDecorate %1 NonUniform\n",
-             MakeInstruction(SpvOpDecorate, {1, SpvDecorationNonUniformEXT})},
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, (uint32_t)spv::Decoration::NonUniformEXT})},
             {"OpDecorate %1 NonUniform\n",
-             MakeInstruction(SpvOpDecorate, {1, 5300})},
+             MakeInstruction(spv::Op::OpDecorate, {1, 5300})},
         })));
 
 // SPV_KHR_linkonce_odr
@@ -914,13 +994,14 @@
                SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_KHR_linkonce_odr\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_KHR_linkonce_odr"))},
             {"OpDecorate %1 LinkageAttributes \"foobar\" LinkOnceODR\n",
-             MakeInstruction(SpvOpDecorate,
-                             Concatenate({{1, SpvDecorationLinkageAttributes},
-                                          MakeVector("foobar"),
-                                          {SpvLinkageTypeLinkOnceODR}}))},
+             MakeInstruction(
+                 spv::Op::OpDecorate,
+                 Concatenate({{1, (uint32_t)spv::Decoration::LinkageAttributes},
+                              MakeVector("foobar"),
+                              {(uint32_t)spv::LinkageType::LinkOnceODR}}))},
         })));
 
 // SPV_KHR_expect_assume
@@ -931,10 +1012,10 @@
                    SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_KHR_expect_assume\"\n",
-                 MakeInstruction(SpvOpExtension,
+                 MakeInstruction(spv::Op::OpExtension,
                                  MakeVector("SPV_KHR_expect_assume"))},
                 {"OpAssumeTrueKHR %1\n",
-                 MakeInstruction(SpvOpAssumeTrueKHR, {1})}})));
+                 MakeInstruction(spv::Op::OpAssumeTrueKHR, {1})}})));
 // SPV_KHR_subgroup_uniform_control_flow
 
 INSTANTIATE_TEST_SUITE_P(
@@ -944,12 +1025,12 @@
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_KHR_subgroup_uniform_control_flow\"\n",
                  MakeInstruction(
-                     SpvOpExtension,
+                     spv::Op::OpExtension,
                      MakeVector("SPV_KHR_subgroup_uniform_control_flow"))},
                 {"OpExecutionMode %1 SubgroupUniformControlFlowKHR\n",
-                 MakeInstruction(
-                     SpvOpExecutionMode,
-                     {1, SpvExecutionModeSubgroupUniformControlFlowKHR})},
+                 MakeInstruction(spv::Op::OpExecutionMode,
+                                 {1, (uint32_t)spv::ExecutionMode::
+                                         SubgroupUniformControlFlowKHR})},
             })));
 
 // SPV_KHR_integer_dot_product
@@ -962,61 +1043,71 @@
                SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_KHR_integer_dot_product\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_KHR_integer_dot_product"))},
             {"OpCapability DotProductInputAll\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityDotProductInputAllKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::DotProductInputAllKHR})},
             {"OpCapability DotProductInput4x8Bit\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityDotProductInput4x8BitKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::DotProductInput4x8BitKHR})},
             {"OpCapability DotProductInput4x8BitPacked\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityDotProductInput4x8BitPackedKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::DotProductInput4x8BitPackedKHR})},
             {"OpCapability DotProduct\n",
-             MakeInstruction(SpvOpCapability, {SpvCapabilityDotProductKHR})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::DotProductKHR})},
             {"%2 = OpSDot %1 %3 %4\n",
-             MakeInstruction(SpvOpSDotKHR, {1, 2, 3, 4})},
+             MakeInstruction(spv::Op::OpSDotKHR, {1, 2, 3, 4})},
             {"%2 = OpSDot %1 %3 %4 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpSDotKHR,
+                 spv::Op::OpSDotKHR,
                  {1, 2, 3, 4,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpUDot %1 %3 %4\n",
-             MakeInstruction(SpvOpUDotKHR, {1, 2, 3, 4})},
+             MakeInstruction(spv::Op::OpUDotKHR, {1, 2, 3, 4})},
             {"%2 = OpUDot %1 %3 %4 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpUDotKHR,
+                 spv::Op::OpUDotKHR,
                  {1, 2, 3, 4,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpSUDot %1 %3 %4\n",
-             MakeInstruction(SpvOpSUDotKHR, {1, 2, 3, 4})},
+             MakeInstruction(spv::Op::OpSUDotKHR, {1, 2, 3, 4})},
             {"%2 = OpSUDot %1 %3 %4 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpSUDotKHR,
+                 spv::Op::OpSUDotKHR,
                  {1, 2, 3, 4,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpSDotAccSat %1 %3 %4 %5\n",
-             MakeInstruction(SpvOpSDotAccSatKHR, {1, 2, 3, 4, 5})},
+             MakeInstruction(spv::Op::OpSDotAccSatKHR, {1, 2, 3, 4, 5})},
             {"%2 = OpSDotAccSat %1 %3 %4 %5 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpSDotAccSatKHR,
+                 spv::Op::OpSDotAccSatKHR,
                  {1, 2, 3, 4, 5,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpUDotAccSat %1 %3 %4 %5\n",
-             MakeInstruction(SpvOpUDotAccSatKHR, {1, 2, 3, 4, 5})},
+             MakeInstruction(spv::Op::OpUDotAccSatKHR, {1, 2, 3, 4, 5})},
             {"%2 = OpUDotAccSat %1 %3 %4 %5 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpUDotAccSatKHR,
+                 spv::Op::OpUDotAccSatKHR,
                  {1, 2, 3, 4, 5,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpSUDotAccSat %1 %3 %4 %5\n",
-             MakeInstruction(SpvOpSUDotAccSatKHR, {1, 2, 3, 4, 5})},
+             MakeInstruction(spv::Op::OpSUDotAccSatKHR, {1, 2, 3, 4, 5})},
             {"%2 = OpSUDotAccSat %1 %3 %4 %5 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpSUDotAccSatKHR,
+                 spv::Op::OpSUDotAccSatKHR,
                  {1, 2, 3, 4, 5,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
         })));
 
 // SPV_KHR_bit_instructions
@@ -1027,11 +1118,11 @@
                    SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_KHR_bit_instructions\"\n",
-                 MakeInstruction(SpvOpExtension,
+                 MakeInstruction(spv::Op::OpExtension,
                                  MakeVector("SPV_KHR_bit_instructions"))},
                 {"OpCapability BitInstructions\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityBitInstructions})},
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::BitInstructions})},
             })));
 
 // SPV_KHR_uniform_group_instructions
@@ -1044,35 +1135,44 @@
                SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_KHR_uniform_group_instructions\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_KHR_uniform_group_instructions"))},
             {"OpCapability GroupUniformArithmeticKHR\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityGroupUniformArithmeticKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::GroupUniformArithmeticKHR})},
             {"%2 = OpGroupIMulKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupIMulKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupIMulKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupFMulKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupFMulKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupFMulKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupBitwiseAndKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupBitwiseAndKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupBitwiseAndKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupBitwiseOrKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupBitwiseOrKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupBitwiseOrKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupBitwiseXorKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupBitwiseXorKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupBitwiseXorKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupLogicalAndKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupLogicalAndKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupLogicalAndKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupLogicalOrKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupLogicalOrKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupLogicalOrKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupLogicalXorKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupLogicalXorKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupLogicalXorKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
         })));
 
 // SPV_KHR_subgroup_rotate
@@ -1084,16 +1184,17 @@
                    SPV_ENV_VULKAN_1_3, SPV_ENV_OPENCL_2_1),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_KHR_subgroup_rotate\"\n",
-                 MakeInstruction(SpvOpExtension,
+                 MakeInstruction(spv::Op::OpExtension,
                                  MakeVector("SPV_KHR_subgroup_rotate"))},
                 {"OpCapability GroupNonUniformRotateKHR\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityGroupNonUniformRotateKHR})},
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)spv::Capability::GroupNonUniformRotateKHR})},
                 {"%2 = OpGroupNonUniformRotateKHR %1 %3 %4 %5\n",
-                 MakeInstruction(SpvOpGroupNonUniformRotateKHR,
+                 MakeInstruction(spv::Op::OpGroupNonUniformRotateKHR,
                                  {1, 2, 3, 4, 5})},
                 {"%2 = OpGroupNonUniformRotateKHR %1 %3 %4 %5 %6\n",
-                 MakeInstruction(SpvOpGroupNonUniformRotateKHR,
+                 MakeInstruction(spv::Op::OpGroupNonUniformRotateKHR,
                                  {1, 2, 3, 4, 5, 6})},
             })));
 
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.function_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.function_test.cpp
index 55a8e6c..9361d6c 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.function_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.function_test.cpp
@@ -33,25 +33,25 @@
 // Test OpFunction
 
 using OpFunctionControlTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvFunctionControlMask>>>;
+    ::testing::TestWithParam<EnumCase<spv::FunctionControlMask>>>;
 
 TEST_P(OpFunctionControlTest, AnySingleFunctionControlMask) {
   const std::string input = "%result_id = OpFunction %result_type " +
                             GetParam().name() + " %function_type ";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpFunction, {1, 2, GetParam().value(), 3})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpFunction,
+                                 {1, 2, (uint32_t)GetParam().value(), 3})));
 }
 
 // clang-format off
-#define CASE(VALUE,NAME) { SpvFunctionControl##VALUE, NAME }
+#define CASE(VALUE,NAME) { spv::FunctionControlMask::VALUE, NAME }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryFunctionTest, OpFunctionControlTest,
-                        ::testing::ValuesIn(std::vector<EnumCase<SpvFunctionControlMask>>{
+                        ::testing::ValuesIn(std::vector<EnumCase<spv::FunctionControlMask>>{
                             CASE(MaskNone, "None"),
-                            CASE(InlineMask, "Inline"),
-                            CASE(DontInlineMask, "DontInline"),
-                            CASE(PureMask, "Pure"),
-                            CASE(ConstMask, "Const"),
+                            CASE(Inline, "Inline"),
+                            CASE(DontInline, "DontInline"),
+                            CASE(Pure, "Pure"),
+                            CASE(Const, "Const"),
                         }));
 #undef CASE
 // clang-format on
@@ -61,11 +61,12 @@
   // the instruction parsing logic with spvTextParseMask.
   const std::string input =
       "%result_id = OpFunction %result_type Inline|Pure|Const %function_type";
-  const uint32_t expected_mask = SpvFunctionControlInlineMask |
-                                 SpvFunctionControlPureMask |
-                                 SpvFunctionControlConstMask;
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpFunction, {1, 2, expected_mask, 3})));
+  const uint32_t expected_mask = uint32_t(spv::FunctionControlMask::Inline |
+                                          spv::FunctionControlMask::Pure |
+                                          spv::FunctionControlMask::Const);
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpFunction, {1, 2, expected_mask, 3})));
 }
 
 TEST_F(OpFunctionControlTest, WrongFunctionControl) {
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.group_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.group_test.cpp
index becc3aa..606e00e 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.group_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.group_test.cpp
@@ -32,20 +32,20 @@
 // Test GroupOperation enum
 
 using GroupOperationTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvGroupOperation>>>;
+    ::testing::TestWithParam<EnumCase<spv::GroupOperation>>>;
 
 TEST_P(GroupOperationTest, AnyGroupOperation) {
   const std::string input =
       "%result = OpGroupIAdd %type %scope " + GetParam().name() + " %x";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, GetParam().value(), 4})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpGroupIAdd,
+                                 {1, 2, 3, (uint32_t)GetParam().value(), 4})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvGroupOperation##NAME, #NAME}
+#define CASE(NAME) { spv::GroupOperation::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(TextToBinaryGroupOperation, GroupOperationTest,
-                        ::testing::ValuesIn(std::vector<EnumCase<SpvGroupOperation>>{
+                        ::testing::ValuesIn(std::vector<EnumCase<spv::GroupOperation>>{
                             CASE(Reduce),
                             CASE(InclusiveScan),
                             CASE(ExclusiveScan),
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.image_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.image_test.cpp
index 8d8ff43..3e7a560 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.image_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.image_test.cpp
@@ -45,11 +45,11 @@
   const std::string input =
       "%2 = OpImageFetch %1 %3 %4" + GetParam().image_operands + "\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpImageFetch, {1, 2, 3, 4},
+              Eq(MakeInstruction(spv::Op::OpImageFetch, {1, 2, 3, 4},
                                  GetParam().expected_mask_and_operands)));
 }
 
-#define MASK(NAME) SpvImageOperands##NAME##Mask
+#define MASK(NAME) uint32_t(spv::ImageOperandsMask::NAME)
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryImageOperandsAny, ImageOperandsTest,
     ::testing::ValuesIn(std::vector<ImageOperandsCase>{
@@ -68,7 +68,7 @@
         {" MinLod %5", {MASK(MinLod), 5}},
     }));
 #undef MASK
-#define MASK(NAME) static_cast<uint32_t>(SpvImageOperands##NAME##Mask)
+#define MASK(NAME) static_cast<uint32_t>(spv::ImageOperandsMask::NAME)
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryImageOperandsCombination, ImageOperandsTest,
     ::testing::ValuesIn(std::vector<ImageOperandsCase>{
@@ -110,7 +110,7 @@
 TEST_F(OpImageTest, Valid) {
   const std::string input = "%2 = OpImage %1 %3\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpImage, {1, 2, 3})));
+              Eq(MakeInstruction(spv::Op::OpImage, {1, 2, 3})));
 
   // Test the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input);
@@ -153,7 +153,7 @@
 TEST_F(OpImageSparseReadTest, OnlyRequiredOperands) {
   const std::string input = "%2 = OpImageSparseRead %1 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpImageSparseRead, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpImageSparseRead, {1, 2, 3, 4})));
   // Test the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input);
 }
@@ -167,13 +167,13 @@
   const std::string input =
       "%2 = OpImageSparseRead %1 %3 %4" + GetParam().image_operands + "\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpImageSparseRead, {1, 2, 3, 4},
+              Eq(MakeInstruction(spv::Op::OpImageSparseRead, {1, 2, 3, 4},
                                  GetParam().expected_mask_and_operands)));
   // Test the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input);
 }
 
-#define MASK(NAME) SpvImageOperands##NAME##Mask
+#define MASK(NAME) uint32_t(spv::ImageOperandsMask::NAME)
 INSTANTIATE_TEST_SUITE_P(ImageSparseReadImageOperandsAny,
                          ImageSparseReadImageOperandsTest,
                          ::testing::ValuesIn(std::vector<ImageOperandsCase>{
@@ -190,7 +190,7 @@
                              {" MinLod %5", {MASK(MinLod), 5}},
                          }));
 #undef MASK
-#define MASK(NAME) static_cast<uint32_t>(SpvImageOperands##NAME##Mask)
+#define MASK(NAME) static_cast<uint32_t>(spv::ImageOperandsMask::NAME)
 INSTANTIATE_TEST_SUITE_P(
     ImageSparseReadImageOperandsCombination, ImageSparseReadImageOperandsTest,
     ::testing::ValuesIn(std::vector<ImageOperandsCase>{
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.memory_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.memory_test.cpp
index f94c134..629ab66 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.memory_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.memory_test.cpp
@@ -35,51 +35,53 @@
 // Test assembly of Memory Access masks
 
 using MemoryAccessTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvMemoryAccessMask>>>;
+    ::testing::TestWithParam<EnumCase<spv::MemoryAccessMask>>>;
 
 TEST_P(MemoryAccessTest, AnySingleMemoryAccessMask) {
   std::stringstream input;
   input << "OpStore %ptr %value " << GetParam().name();
   for (auto operand : GetParam().operands()) input << " " << operand;
-  EXPECT_THAT(CompiledInstructions(input.str()),
-              Eq(MakeInstruction(SpvOpStore, {1, 2, GetParam().value()},
-                                 GetParam().operands())));
+  EXPECT_THAT(
+      CompiledInstructions(input.str()),
+      Eq(MakeInstruction(spv::Op::OpStore, {1, 2, (uint32_t)GetParam().value()},
+                         GetParam().operands())));
 }
 
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryMemoryAccessTest, MemoryAccessTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvMemoryAccessMask>>{
-        {SpvMemoryAccessMaskNone, "None", {}},
-        {SpvMemoryAccessVolatileMask, "Volatile", {}},
-        {SpvMemoryAccessAlignedMask, "Aligned", {16}},
-        {SpvMemoryAccessNontemporalMask, "Nontemporal", {}},
+    ::testing::ValuesIn(std::vector<EnumCase<spv::MemoryAccessMask>>{
+        {spv::MemoryAccessMask::MaskNone, "None", {}},
+        {spv::MemoryAccessMask::Volatile, "Volatile", {}},
+        {spv::MemoryAccessMask::Aligned, "Aligned", {16}},
+        {spv::MemoryAccessMask::Nontemporal, "Nontemporal", {}},
     }));
 
 TEST_F(TextToBinaryTest, CombinedMemoryAccessMask) {
   const std::string input = "OpStore %ptr %value Volatile|Aligned 16";
-  const uint32_t expected_mask =
-      SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask;
+  const uint32_t expected_mask = uint32_t(spv::MemoryAccessMask::Volatile |
+                                          spv::MemoryAccessMask::Aligned);
   EXPECT_THAT(expected_mask, Eq(3u));
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpStore, {1, 2, expected_mask, 16})));
+              Eq(MakeInstruction(spv::Op::OpStore, {1, 2, expected_mask, 16})));
 }
 
 // Test Storage Class enum values
 
 using StorageClassTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvStorageClass>>>;
+    ::testing::TestWithParam<EnumCase<spv::StorageClass>>>;
 
 TEST_P(StorageClassTest, AnyStorageClass) {
   const std::string input = "%1 = OpVariable %2 " + GetParam().name();
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpVariable, {1, 2, GetParam().value()})));
+              Eq(MakeInstruction(spv::Op::OpVariable,
+                                 {1, 2, (uint32_t)GetParam().value()})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvStorageClass##NAME, #NAME, {} }
+#define CASE(NAME) { spv::StorageClass::NAME, #NAME, {} }
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryStorageClassTest, StorageClassTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvStorageClass>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::StorageClass>>{
         CASE(UniformConstant),
         CASE(Input),
         CASE(Uniform),
@@ -103,7 +105,7 @@
 TEST_F(MemoryRoundTripTest, OpPtrEqualGood) {
   std::string spirv = "%2 = OpPtrEqual %1 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpPtrEqual, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpPtrEqual, {1, 2, 3, 4})));
   std::string disassembly = EncodeAndDecodeSuccessfully(
       spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -120,7 +122,7 @@
 TEST_F(MemoryRoundTripTest, OpPtrNotEqualGood) {
   std::string spirv = "%2 = OpPtrNotEqual %1 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpPtrNotEqual, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpPtrNotEqual, {1, 2, 3, 4})));
   std::string disassembly = EncodeAndDecodeSuccessfully(
       spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -137,7 +139,7 @@
 TEST_F(MemoryRoundTripTest, OpPtrDiffGood) {
   std::string spirv = "%2 = OpPtrDiff %1 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpPtrDiff, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpPtrDiff, {1, 2, 3, 4})));
   std::string disassembly = EncodeAndDecodeSuccessfully(
       spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -157,7 +159,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryNoMemAccessGood) {
   std::string spirv = "OpCopyMemory %1 %2\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -179,7 +181,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNoneGood) {
   std::string spirv = "OpCopyMemory %1 %2 None\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 0})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 0})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -188,7 +190,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessVolatileGood) {
   std::string spirv = "OpCopyMemory %1 %2 Volatile\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -197,7 +199,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessAligned8Good) {
   std::string spirv = "OpCopyMemory %1 %2 Aligned 8\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 2, 8})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 2, 8})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -206,7 +208,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNontemporalGood) {
   std::string spirv = "OpCopyMemory %1 %2 Nontemporal\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 4})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -215,7 +217,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessAvGood) {
   std::string spirv = "OpCopyMemory %1 %2 MakePointerAvailable %3\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 8, 3})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 8, 3})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -224,7 +226,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessVisGood) {
   std::string spirv = "OpCopyMemory %1 %2 MakePointerVisible %3\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 16, 3})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 16, 3})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -233,7 +235,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNonPrivateGood) {
   std::string spirv = "OpCopyMemory %1 %2 NonPrivatePointer\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 32})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 32})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -245,7 +247,7 @@
       "Volatile|Aligned|Nontemporal|MakePointerAvailable|"
       "MakePointerVisible|NonPrivatePointer 16 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 63, 16, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 63, 16, 3, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -255,7 +257,7 @@
   std::string spirv = "OpCopyMemory %1 %2 Volatile Volatile\n";
   // Note: This will assemble but should not validate for SPIR-V 1.3
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_3),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 1, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 1, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -264,7 +266,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryTwoAccessV14Good) {
   std::string spirv = "OpCopyMemory %1 %2 Volatile Volatile\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 1, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 1, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -275,8 +277,9 @@
       "OpCopyMemory %1 %2 Volatile|Nontemporal|"
       "MakePointerVisible %3 "
       "Aligned|MakePointerAvailable|NonPrivatePointer 16 %4\n";
-  EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 21, 3, 42, 16, 4})));
+  EXPECT_THAT(
+      CompiledInstructions(spirv),
+      Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 21, 3, 42, 16, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -287,7 +290,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedNoMemAccessGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -309,7 +312,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNoneGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 None\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 0})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 0})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -318,7 +321,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessVolatileGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -327,7 +330,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessAligned8Good) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Aligned 8\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 2, 8})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 2, 8})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -336,7 +339,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNontemporalGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Nontemporal\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -345,7 +348,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessAvGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 MakePointerAvailable %4\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 8, 4})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 8, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -353,8 +356,9 @@
 
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessVisGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 MakePointerVisible %4\n";
-  EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 16, 4})));
+  EXPECT_THAT(
+      CompiledInstructions(spirv),
+      Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 16, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -363,7 +367,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNonPrivateGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 NonPrivatePointer\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 32})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 32})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -376,7 +380,7 @@
       "MakePointerVisible|NonPrivatePointer 16 %4 %5\n";
   EXPECT_THAT(
       CompiledInstructions(spirv),
-      Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 63, 16, 4, 5})));
+      Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 63, 16, 4, 5})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -386,7 +390,7 @@
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile Volatile\n";
   // Note: This will assemble but should not validate for SPIR-V 1.3
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_3),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 1, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 1, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -395,7 +399,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedTwoAccessV14Good) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile Volatile\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 1, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 1, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -406,9 +410,9 @@
       "OpCopyMemorySized %1 %2 %3 Volatile|Nontemporal|"
       "MakePointerVisible %4 "
       "Aligned|MakePointerAvailable|NonPrivatePointer 16 %5\n";
-  EXPECT_THAT(
-      CompiledInstructions(spirv),
-      Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 21, 4, 42, 16, 5})));
+  EXPECT_THAT(CompiledInstructions(spirv),
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized,
+                                 {1, 2, 3, 21, 4, 42, 16, 5})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.misc_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.misc_test.cpp
index 03b1e09..9ee425a 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.misc_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.misc_test.cpp
@@ -29,7 +29,8 @@
 using TextToBinaryMisc = spvtest::TextToBinaryTest;
 
 TEST_F(TextToBinaryMisc, OpNop) {
-  EXPECT_THAT(CompiledInstructions("OpNop"), Eq(MakeInstruction(SpvOpNop, {})));
+  EXPECT_THAT(CompiledInstructions("OpNop"),
+              Eq(MakeInstruction(spv::Op::OpNop, {})));
 }
 
 TEST_F(TextToBinaryMisc, OpUndef) {
@@ -37,7 +38,8 @@
                                                    %u = OpUndef %f32)");
   const uint32_t typeID = 1;
   EXPECT_THAT(code[1], Eq(typeID));
-  EXPECT_THAT(Subvector(code, 3), Eq(MakeInstruction(SpvOpUndef, {typeID, 2})));
+  EXPECT_THAT(Subvector(code, 3),
+              Eq(MakeInstruction(spv::Op::OpUndef, {typeID, 2})));
 }
 
 TEST_F(TextToBinaryMisc, OpWrong) {
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.mode_setting_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.mode_setting_test.cpp
index 7f15c8b..c62ba3e 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.mode_setting_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.mode_setting_test.cpp
@@ -46,9 +46,9 @@
   uint32_t get_memory_value() const {
     return static_cast<uint32_t>(memory_value);
   }
-  SpvAddressingModel addressing_value;
+  spv::AddressingModel addressing_value;
   std::string addressing_name;
-  SpvMemoryModel memory_value;
+  spv::MemoryModel memory_value;
   std::string memory_name;
 };
 
@@ -58,16 +58,16 @@
 TEST_P(OpMemoryModelTest, AnyMemoryModelCase) {
   const std::string input = "OpMemoryModel " + GetParam().addressing_name +
                             " " + GetParam().memory_name;
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpMemoryModel, {GetParam().get_addressing_value(),
-                                            GetParam().get_memory_value()})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpMemoryModel,
+                                 {GetParam().get_addressing_value(),
+                                  GetParam().get_memory_value()})));
 }
 
-#define CASE(ADDRESSING, MEMORY)                                         \
-  {                                                                      \
-    SpvAddressingModel##ADDRESSING, #ADDRESSING, SpvMemoryModel##MEMORY, \
-        #MEMORY                                                          \
+#define CASE(ADDRESSING, MEMORY)                                             \
+  {                                                                          \
+    spv::AddressingModel::ADDRESSING, #ADDRESSING, spv::MemoryModel::MEMORY, \
+        #MEMORY                                                              \
   }
 // clang-format off
 INSTANTIATE_TEST_SUITE_P(TextToBinaryMemoryModel, OpMemoryModelTest,
@@ -97,7 +97,7 @@
   uint32_t get_execution_value() const {
     return static_cast<uint32_t>(execution_value);
   }
-  SpvExecutionModel execution_value;
+  spv::ExecutionModel execution_value;
   std::string execution_name;
   std::string entry_point_name;
 };
@@ -109,14 +109,14 @@
   // TODO(dneto): utf-8, escaping, quoting cases for entry point name.
   const std::string input = "OpEntryPoint " + GetParam().execution_name +
                             " %1 \"" + GetParam().entry_point_name + "\"";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpEntryPoint, {GetParam().get_execution_value(), 1},
-                         MakeVector(GetParam().entry_point_name))));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpEntryPoint,
+                                 {GetParam().get_execution_value(), 1},
+                                 MakeVector(GetParam().entry_point_name))));
 }
 
 // clang-format off
-#define CASE(NAME) SpvExecutionModel##NAME, #NAME
+#define CASE(NAME) spv::ExecutionModel::NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(TextToBinaryEntryPoint, OpEntryPointTest,
                         ValuesIn(std::vector<EntryPointCase>{
                           { CASE(Vertex), "" },
@@ -137,7 +137,7 @@
 
 // Test OpExecutionMode
 using OpExecutionModeTest = spvtest::TextToBinaryTestBase<
-    TestWithParam<std::tuple<spv_target_env, EnumCase<SpvExecutionMode>>>>;
+    TestWithParam<std::tuple<spv_target_env, EnumCase<spv::ExecutionMode>>>>;
 
 TEST_P(OpExecutionModeTest, AnyExecutionMode) {
   // This string should assemble, but should not validate.
@@ -146,16 +146,16 @@
   for (auto operand : std::get<1>(GetParam()).operands())
     input << " " << operand;
   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
-              Eq(MakeInstruction(SpvOpExecutionMode,
+              Eq(MakeInstruction(spv::Op::OpExecutionMode,
                                  {1, std::get<1>(GetParam()).value()},
                                  std::get<1>(GetParam()).operands())));
 }
 
-#define CASE(NAME) SpvExecutionMode##NAME, #NAME
+#define CASE(NAME) spv::ExecutionMode::NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryExecutionMode, OpExecutionModeTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCase<SpvExecutionMode>>{
+            ValuesIn(std::vector<EnumCase<spv::ExecutionMode>>{
                 // The operand literal values are arbitrarily chosen,
                 // but there are the right number of them.
                 {CASE(Invocations), {101}},
@@ -195,7 +195,7 @@
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryExecutionModeV11, OpExecutionModeTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCase<SpvExecutionMode>>{
+            ValuesIn(std::vector<EnumCase<spv::ExecutionMode>>{
                 {CASE(Initializer)},
                 {CASE(Finalizer)},
                 {CASE(SubgroupSize), {12}},
@@ -216,18 +216,18 @@
 // Test OpCapability
 
 using OpCapabilityTest =
-    spvtest::TextToBinaryTestBase<TestWithParam<EnumCase<SpvCapability>>>;
+    spvtest::TextToBinaryTestBase<TestWithParam<EnumCase<spv::Capability>>>;
 
 TEST_P(OpCapabilityTest, AnyCapability) {
   const std::string input = "OpCapability " + GetParam().name();
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpCapability, {GetParam().value()})));
+              Eq(MakeInstruction(spv::Op::OpCapability, {GetParam().value()})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvCapability##NAME, #NAME }
+#define CASE(NAME) { spv::Capability::NAME, #NAME }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryCapability, OpCapabilityTest,
-                        ValuesIn(std::vector<EnumCase<SpvCapability>>{
+                        ValuesIn(std::vector<EnumCase<spv::Capability>>{
                             CASE(Matrix),
                             CASE(Shader),
                             CASE(Geometry),
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.pipe_storage_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.pipe_storage_test.cpp
index 955f5ef..2a41d42 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.pipe_storage_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.pipe_storage_test.cpp
@@ -28,7 +28,7 @@
 TEST_F(OpTypePipeStorageTest, OpcodeAssemblesInV10) {
   EXPECT_THAT(
       CompiledInstructions("%res = OpTypePipeStorage", SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpTypePipeStorage, {1})));
+      Eq(MakeInstruction(spv::Op::OpTypePipeStorage, {1})));
 }
 
 TEST_F(OpTypePipeStorageTest, ArgumentCount) {
@@ -38,7 +38,7 @@
          "'OpTypePipeStorage'."));
   EXPECT_THAT(
       CompiledInstructions("%res = OpTypePipeStorage", SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpTypePipeStorage, {1})));
+      Eq(MakeInstruction(spv::Op::OpTypePipeStorage, {1})));
   EXPECT_THAT(CompileFailure("%res = OpTypePipeStorage %1 %2 %3 %4 %5",
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("'=' expected after result id."));
@@ -47,9 +47,10 @@
 using OpConstantPipeStorageTest = spvtest::TextToBinaryTest;
 
 TEST_F(OpConstantPipeStorageTest, OpcodeAssemblesInV10) {
-  EXPECT_THAT(CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5",
-                                   SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpConstantPipeStorage, {1, 2, 3, 4, 5})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5",
+                           SPV_ENV_UNIVERSAL_1_0),
+      Eq(MakeInstruction(spv::Op::OpConstantPipeStorage, {1, 2, 3, 4, 5})));
 }
 
 TEST_F(OpConstantPipeStorageTest, ArgumentCount) {
@@ -65,9 +66,10 @@
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("Expected operand for OpConstantPipeStorage instruction, but "
                  "found the end of the stream."));
-  EXPECT_THAT(CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5",
-                                   SPV_ENV_UNIVERSAL_1_1),
-              Eq(MakeInstruction(SpvOpConstantPipeStorage, {1, 2, 3, 4, 5})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5",
+                           SPV_ENV_UNIVERSAL_1_1),
+      Eq(MakeInstruction(spv::Op::OpConstantPipeStorage, {1, 2, 3, 4, 5})));
   EXPECT_THAT(CompileFailure("%1 = OpConstantPipeStorage %2 3 4 5 %6 %7",
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("'=' expected after result id."));
@@ -91,9 +93,10 @@
 using OpCreatePipeFromPipeStorageTest = spvtest::TextToBinaryTest;
 
 TEST_F(OpCreatePipeFromPipeStorageTest, OpcodeAssemblesInV10) {
-  EXPECT_THAT(CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3",
-                                   SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpCreatePipeFromPipeStorage, {1, 2, 3})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3",
+                           SPV_ENV_UNIVERSAL_1_0),
+      Eq(MakeInstruction(spv::Op::OpCreatePipeFromPipeStorage, {1, 2, 3})));
 }
 
 TEST_F(OpCreatePipeFromPipeStorageTest, ArgumentCount) {
@@ -109,9 +112,10 @@
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("Expected operand for OpCreatePipeFromPipeStorage "
                  "instruction, but found the next instruction instead."));
-  EXPECT_THAT(CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3",
-                                   SPV_ENV_UNIVERSAL_1_1),
-              Eq(MakeInstruction(SpvOpCreatePipeFromPipeStorage, {1, 2, 3})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3",
+                           SPV_ENV_UNIVERSAL_1_1),
+      Eq(MakeInstruction(spv::Op::OpCreatePipeFromPipeStorage, {1, 2, 3})));
   EXPECT_THAT(CompileFailure("%1 = OpCreatePipeFromPipeStorage %2 %3 %4 %5",
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("'=' expected after result id."));
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.reserved_sampling_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.reserved_sampling_test.cpp
index 42e4e2a..abc1667 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.reserved_sampling_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.reserved_sampling_test.cpp
@@ -30,33 +30,36 @@
 
 TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjImplicitLod) {
   std::string input = "%2 = OpImageSparseSampleProjImplicitLod %1 %3 %4\n";
-  EXPECT_THAT(
-      CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpImageSparseSampleProjImplicitLod, {1, 2, 3, 4})));
+  EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
+              Eq(MakeInstruction(spv::Op::OpImageSparseSampleProjImplicitLod,
+                                 {1, 2, 3, 4})));
 }
 
 TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjExplicitLod) {
   std::string input =
       "%2 = OpImageSparseSampleProjExplicitLod %1 %3 %4 Lod %5\n";
   EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpImageSparseSampleProjExplicitLod,
-                                 {1, 2, 3, 4, SpvImageOperandsLodMask, 5})));
+              Eq(MakeInstruction(
+                  spv::Op::OpImageSparseSampleProjExplicitLod,
+                  {1, 2, 3, 4, (uint32_t)spv::ImageOperandsMask::Lod, 5})));
 }
 
 TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjDrefImplicitLod) {
   std::string input =
       "%2 = OpImageSparseSampleProjDrefImplicitLod %1 %3 %4 %5\n";
-  EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpImageSparseSampleProjDrefImplicitLod,
-                                 {1, 2, 3, 4, 5})));
+  EXPECT_THAT(
+      CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
+      Eq(MakeInstruction(spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+                         {1, 2, 3, 4, 5})));
 }
 
 TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjDrefExplicitLod) {
   std::string input =
       "%2 = OpImageSparseSampleProjDrefExplicitLod %1 %3 %4 %5 Lod %6\n";
   EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpImageSparseSampleProjDrefExplicitLod,
-                                 {1, 2, 3, 4, 5, SpvImageOperandsLodMask, 6})));
+              Eq(MakeInstruction(
+                  spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+                  {1, 2, 3, 4, 5, (uint32_t)spv::ImageOperandsMask::Lod, 6})));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.subgroup_dispatch_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.subgroup_dispatch_test.cpp
index 8c40445..45d7780 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.subgroup_dispatch_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.subgroup_dispatch_test.cpp
@@ -35,7 +35,7 @@
       CompiledInstructions("%res = OpGetKernelLocalSizeForSubgroupCount %type "
                            "%sgcount %invoke %param %param_size %param_align",
                            SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpGetKernelLocalSizeForSubgroupCount,
+      Eq(MakeInstruction(spv::Op::OpGetKernelLocalSizeForSubgroupCount,
                          {1, 2, 3, 4, 5, 6, 7})));
 }
 
@@ -57,7 +57,7 @@
       CompiledInstructions("%res = OpGetKernelLocalSizeForSubgroupCount %type "
                            "%sgcount %invoke %param %param_size %param_align",
                            SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpGetKernelLocalSizeForSubgroupCount,
+      Eq(MakeInstruction(spv::Op::OpGetKernelLocalSizeForSubgroupCount,
                          {1, 2, 3, 4, 5, 6, 7})));
   EXPECT_THAT(
       CompileFailure("%res = OpGetKernelLocalSizeForSubgroupCount %type "
@@ -81,11 +81,11 @@
 using OpGetKernelMaxNumSubgroupsTest = spvtest::TextToBinaryTest;
 
 TEST_F(OpGetKernelMaxNumSubgroupsTest, OpcodeAssemblesInV10) {
-  EXPECT_THAT(
-      CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type "
-                           "%invoke %param %param_size %param_align",
-                           SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpGetKernelMaxNumSubgroups, {1, 2, 3, 4, 5, 6})));
+  EXPECT_THAT(CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type "
+                                   "%invoke %param %param_size %param_align",
+                                   SPV_ENV_UNIVERSAL_1_0),
+              Eq(MakeInstruction(spv::Op::OpGetKernelMaxNumSubgroups,
+                                 {1, 2, 3, 4, 5, 6})));
 }
 
 TEST_F(OpGetKernelMaxNumSubgroupsTest, ArgumentCount) {
@@ -101,11 +101,11 @@
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("Expected operand for OpGetKernelMaxNumSubgroups instruction, "
                  "but found the end of the stream."));
-  EXPECT_THAT(
-      CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type "
-                           "%invoke %param %param_size %param_align",
-                           SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpGetKernelMaxNumSubgroups, {1, 2, 3, 4, 5, 6})));
+  EXPECT_THAT(CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type "
+                                   "%invoke %param %param_size %param_align",
+                                   SPV_ENV_UNIVERSAL_1_1),
+              Eq(MakeInstruction(spv::Op::OpGetKernelMaxNumSubgroups,
+                                 {1, 2, 3, 4, 5, 6})));
   EXPECT_THAT(CompileFailure("%res = OpGetKernelMaxNumSubgroups %type %invoke "
                              "%param %param_size %param_align %extra",
                              SPV_ENV_UNIVERSAL_1_1),
diff --git a/third_party/SPIRV-Tools/test/text_to_binary.type_declaration_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary.type_declaration_test.cpp
index 65a2355..241600e 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary.type_declaration_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary.type_declaration_test.cpp
@@ -32,28 +32,29 @@
 // Test Dim enums via OpTypeImage
 
 using DimTest =
-    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvDim>>>;
+    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Dim>>>;
 
 TEST_P(DimTest, AnyDim) {
   const std::string input =
       "%1 = OpTypeImage %2 " + GetParam().name() + " 2 3 0 4 Rgba8\n";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpTypeImage, {1, 2, GetParam().value(), 2, 3, 0, 4,
-                                          SpvImageFormatRgba8})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpTypeImage,
+                                 {1, 2, (uint32_t)GetParam().value(), 2, 3, 0,
+                                  4, (uint32_t)spv::ImageFormat::Rgba8})));
 
   // Check the disassembler as well.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
 // clang-format off
-#define CASE(NAME) {SpvDim##NAME, #NAME}
+#define CASE(NAME) {spv::Dim::NAME, #NAME}
+#define CASE1(DIM, NAME) {spv::Dim::DIM, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryDim, DimTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvDim>>{
-        CASE(1D),
-        CASE(2D),
-        CASE(3D),
+    ::testing::ValuesIn(std::vector<EnumCase<spv::Dim>>{
+        CASE1(Dim1D, 1D),
+        CASE1(Dim2D, 2D),
+        CASE1(Dim3D, 3D),
         CASE(Cube),
         CASE(Rect),
         CASE(Buffer),
@@ -70,23 +71,24 @@
 // Test ImageFormat enums via OpTypeImage
 
 using ImageFormatTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvImageFormat>>>;
+    ::testing::TestWithParam<EnumCase<spv::ImageFormat>>>;
 
 TEST_P(ImageFormatTest, AnyImageFormatAndNoAccessQualifier) {
   const std::string input =
       "%1 = OpTypeImage %2 1D 2 3 0 4 " + GetParam().name() + "\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpTypeImage, {1, 2, SpvDim1D, 2, 3, 0, 4,
-                                                  GetParam().value()})));
+              Eq(MakeInstruction(spv::Op::OpTypeImage,
+                                 {1, 2, (uint32_t)spv::Dim::Dim1D, 2, 3, 0, 4,
+                                  GetParam().value()})));
   // Check the disassembler as well.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
 // clang-format off
-#define CASE(NAME) {SpvImageFormat##NAME, #NAME}
+#define CASE(NAME) {spv::ImageFormat::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryImageFormat, ImageFormatTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvImageFormat>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::ImageFormat>>{
         CASE(Unknown),
         CASE(Rgba32f),
         CASE(Rgba16f),
@@ -138,24 +140,25 @@
 
 // Test AccessQualifier enums via OpTypeImage.
 using ImageAccessQualifierTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvAccessQualifier>>>;
+    ::testing::TestWithParam<EnumCase<spv::AccessQualifier>>>;
 
 TEST_P(ImageAccessQualifierTest, AnyAccessQualifier) {
   const std::string input =
       "%1 = OpTypeImage %2 1D 2 3 0 4 Rgba8 " + GetParam().name() + "\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpTypeImage,
-                                 {1, 2, SpvDim1D, 2, 3, 0, 4,
-                                  SpvImageFormatRgba8, GetParam().value()})));
+              Eq(MakeInstruction(
+                  spv::Op::OpTypeImage,
+                  {1, 2, (uint32_t)spv::Dim::Dim1D, 2, 3, 0, 4,
+                   (uint32_t)spv::ImageFormat::Rgba8, GetParam().value()})));
   // Check the disassembler as well.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
 // clang-format off
-#define CASE(NAME) {SpvAccessQualifier##NAME, #NAME}
+#define CASE(NAME) {spv::AccessQualifier::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     AccessQualifier, ImageAccessQualifierTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvAccessQualifier>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::AccessQualifier>>{
       CASE(ReadOnly),
       CASE(WriteOnly),
       CASE(ReadWrite),
@@ -166,21 +169,22 @@
 // Test AccessQualifier enums via OpTypePipe.
 
 using OpTypePipeTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvAccessQualifier>>>;
+    ::testing::TestWithParam<EnumCase<spv::AccessQualifier>>>;
 
 TEST_P(OpTypePipeTest, AnyAccessQualifier) {
   const std::string input = "%1 = OpTypePipe " + GetParam().name() + "\n";
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpTypePipe, {1, GetParam().value()})));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpTypePipe, {1, GetParam().value()})));
   // Check the disassembler as well.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
 // clang-format off
-#define CASE(NAME) {SpvAccessQualifier##NAME, #NAME}
+#define CASE(NAME) {spv::AccessQualifier::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryTypePipe, OpTypePipeTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvAccessQualifier>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::AccessQualifier>>{
                             CASE(ReadOnly),
                             CASE(WriteOnly),
                             CASE(ReadWrite),
@@ -195,12 +199,12 @@
 
 using OpTypeForwardPointerTest = spvtest::TextToBinaryTest;
 
-#define CASE(storage_class)                                               \
-  do {                                                                    \
-    EXPECT_THAT(                                                          \
-        CompiledInstructions("OpTypeForwardPointer %pt " #storage_class), \
-        Eq(MakeInstruction(SpvOpTypeForwardPointer,                       \
-                           {1, SpvStorageClass##storage_class})));        \
+#define CASE(storage_class)                                                    \
+  do {                                                                         \
+    EXPECT_THAT(                                                               \
+        CompiledInstructions("OpTypeForwardPointer %pt " #storage_class),      \
+        Eq(MakeInstruction(spv::Op::OpTypeForwardPointer,                      \
+                           {1, (uint32_t)spv::StorageClass::storage_class}))); \
   } while (0)
 
 TEST_F(OpTypeForwardPointerTest, ValidStorageClass) {
@@ -245,7 +249,7 @@
 TEST_F(OpSizeOfTest, OpcodeAssemblesInV10) {
   EXPECT_THAT(
       CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3})));
+      Eq(MakeInstruction(spv::Op::OpSizeOf, {1, 2, 3})));
 }
 
 TEST_F(OpSizeOfTest, ArgumentCount) {
@@ -258,7 +262,7 @@
                  "next instruction instead."));
   EXPECT_THAT(
       CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3})));
+      Eq(MakeInstruction(spv::Op::OpSizeOf, {1, 2, 3})));
   EXPECT_THAT(
       CompileFailure("%1 = OpSizeOf %2 %3 44 55 ", SPV_ENV_UNIVERSAL_1_1),
       Eq("Expected <opcode> or <result-id> at the beginning of an instruction, "
diff --git a/third_party/SPIRV-Tools/test/text_to_binary_test.cpp b/third_party/SPIRV-Tools/test/text_to_binary_test.cpp
index 0b348e8..a958097 100644
--- a/third_party/SPIRV-Tools/test/text_to_binary_test.cpp
+++ b/third_party/SPIRV-Tools/test/text_to_binary_test.cpp
@@ -180,9 +180,10 @@
 TEST_F(TextToBinaryTest, CRLF) {
   const std::string input =
       "%i32 = OpTypeInt 32 1\r\n%c = OpConstant %i32 123\r\n";
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-                              MakeInstruction(SpvOpConstant, {1, 2, 123})})));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+                      MakeInstruction(spv::Op::OpConstant, {1, 2, 123})})));
 }
 
 using TextToBinaryFloatValueTest = spvtest::TextToBinaryTestBase<
@@ -192,8 +193,8 @@
   const std::string input =
       "%1 = OpTypeFloat 32\n%2 = OpConstant %1 " + GetParam().first;
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-                              MakeInstruction(SpvOpConstant,
+              Eq(Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+                              MakeInstruction(spv::Op::OpConstant,
                                               {1, 2, GetParam().second})})));
 }
 
@@ -222,8 +223,8 @@
   const std::string input =
       "%1 = OpTypeFloat 16\n%2 = OpConstant %1 " + GetParam().first;
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 16}),
-                              MakeInstruction(SpvOpConstant,
+              Eq(Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 16}),
+                              MakeInstruction(spv::Op::OpConstant,
                                               {1, 2, GetParam().second})})));
 }
 
diff --git a/third_party/SPIRV-Tools/test/unit_spirv.h b/third_party/SPIRV-Tools/test/unit_spirv.h
index f0a2958..bc9857e 100644
--- a/third_party/SPIRV-Tools/test/unit_spirv.h
+++ b/third_party/SPIRV-Tools/test/unit_spirv.h
@@ -105,7 +105,7 @@
 // Returns a vector of words representing a single instruction with the
 // given opcode and operand words as a vector.
 inline std::vector<uint32_t> MakeInstruction(
-    SpvOp opcode, const std::vector<uint32_t>& args) {
+    spv::Op opcode, const std::vector<uint32_t>& args) {
   std::vector<uint32_t> result{
       spvOpcodeMake(uint16_t(args.size() + 1), opcode)};
   result.insert(result.end(), args.begin(), args.end());
@@ -116,7 +116,7 @@
 // given opcode and whose operands are the concatenation of the two given
 // argument lists.
 inline std::vector<uint32_t> MakeInstruction(
-    SpvOp opcode, std::vector<uint32_t> args,
+    spv::Op opcode, std::vector<uint32_t> args,
     const std::vector<uint32_t>& extra_args) {
   args.insert(args.end(), extra_args.begin(), extra_args.end());
   return MakeInstruction(opcode, args);
@@ -200,10 +200,10 @@
 }
 
 // Returns the capabilities in a CapabilitySet as an ordered vector.
-inline std::vector<SpvCapability> ElementsIn(
+inline std::vector<spv::Capability> ElementsIn(
     const spvtools::CapabilitySet& capabilities) {
-  std::vector<SpvCapability> result;
-  capabilities.ForEach([&result](SpvCapability c) { result.push_back(c); });
+  std::vector<spv::Capability> result;
+  capabilities.ForEach([&result](spv::Capability c) { result.push_back(c); });
   return result;
 }
 
diff --git a/third_party/SPIRV-Tools/test/val/CMakeLists.txt b/third_party/SPIRV-Tools/test/val/CMakeLists.txt
index d02807a..de89b93 100644
--- a/third_party/SPIRV-Tools/test/val/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/test/val/CMakeLists.txt
@@ -36,16 +36,16 @@
        val_data_test.cpp
        val_decoration_test.cpp
        val_derivatives_test.cpp
-       val_entry_point.cpp
+       val_entry_point_test.cpp
        val_explicit_reserved_test.cpp
        val_extensions_test.cpp
-       val_extension_spv_khr_expect_assume.cpp
-       val_extension_spv_khr_linkonce_odr.cpp
-       val_extension_spv_khr_subgroup_uniform_control_flow.cpp
-       val_extension_spv_khr_integer_dot_product.cpp
-       val_extension_spv_khr_bit_instructions.cpp
-       val_extension_spv_khr_terminate_invocation.cpp
-       val_extension_spv_khr_subgroup_rotate.cpp
+       val_extension_spv_khr_expect_assume_test.cpp
+       val_extension_spv_khr_linkonce_odr_test.cpp
+       val_extension_spv_khr_subgroup_uniform_control_flow_test.cpp
+       val_extension_spv_khr_integer_dot_product_test.cpp
+       val_extension_spv_khr_bit_instructions_test.cpp
+       val_extension_spv_khr_terminate_invocation_test.cpp
+       val_extension_spv_khr_subgroup_rotate_test.cpp
        val_ext_inst_test.cpp
        val_ext_inst_debug_test.cpp
        ${VAL_TEST_COMMON_SRCS}
@@ -77,6 +77,7 @@
        val_literals_test.cpp
        val_logicals_test.cpp
        val_memory_test.cpp
+       val_mesh_shading_test.cpp
        val_misc_test.cpp
        val_modes_test.cpp
        val_non_semantic_test.cpp
@@ -90,7 +91,8 @@
 
 add_spvtools_unittest(TARGET val_rstuvw
   SRCS
-       val_ray_query.cpp
+       val_ray_query_test.cpp
+       val_ray_tracing_test.cpp
        val_small_type_uses_test.cpp
        val_ssa_test.cpp
        val_state_test.cpp
diff --git a/third_party/SPIRV-Tools/test/val/val_adjacency_test.cpp b/third_party/SPIRV-Tools/test/val/val_adjacency_test.cpp
index 2959853..4649948 100644
--- a/third_party/SPIRV-Tools/test/val/val_adjacency_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_adjacency_test.cpp
@@ -54,7 +54,7 @@
   CompileSuccessfully(module);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ID 1[%bool] has not been defined"));
+              HasSubstr("ID '1[%bool]' has not been defined"));
 }
 
 TEST_F(ValidateAdjacency, OpLoopMergeEndsModuleFail) {
diff --git a/third_party/SPIRV-Tools/test/val/val_arithmetics_test.cpp b/third_party/SPIRV-Tools/test/val/val_arithmetics_test.cpp
index 4c093e9..631375e 100644
--- a/third_party/SPIRV-Tools/test/val/val_arithmetics_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_arithmetics_test.cpp
@@ -606,8 +606,9 @@
 
   CompileSuccessfully(GenerateCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 6[%float] cannot be a "
-                                               "type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Operand '6[%float]' cannot be a "
+                        "type"));
 }
 
 TEST_F(ValidateArithmetics, DotNotVectorTypeOperand2) {
diff --git a/third_party/SPIRV-Tools/test/val/val_atomics_test.cpp b/third_party/SPIRV-Tools/test/val/val_atomics_test.cpp
index a0308d5..b266ad6 100644
--- a/third_party/SPIRV-Tools/test/val/val_atomics_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_atomics_test.cpp
@@ -778,8 +778,8 @@
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("AtomicStore: Vulkan spec only allows storage classes for "
-                "atomic to be: Uniform, Workgroup, Image, StorageBuffer, or "
-                "PhysicalStorageBuffer."));
+                "atomic to be: Uniform, Workgroup, Image, StorageBuffer, "
+                "PhysicalStorageBuffer or TaskPayloadWorkgroupEXT."));
 }
 
 TEST_F(ValidateAtomics, AtomicStoreFunctionPointerStorageType) {
@@ -1000,8 +1000,9 @@
 
   CompileSuccessfully(GenerateKernelCode(body));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 27[%_ptr_Workgroup_float] cannot be a type"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Operand '27[%_ptr_Workgroup_float]' cannot be a type"));
 }
 
 TEST_F(ValidateAtomics, AtomicLoadWrongPointerDataType) {
@@ -1273,7 +1274,7 @@
   CompileSuccessfully(GenerateKernelCode(body));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 33[%_ptr_Workgroup_v4float] cannot be a "
+              HasSubstr("Operand '33[%_ptr_Workgroup_v4float]' cannot be a "
                         "type"));
 }
 
@@ -1400,7 +1401,7 @@
   CompileSuccessfully(GenerateKernelCode(body));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 33[%_ptr_Workgroup_v4float] cannot be a "
+              HasSubstr("Operand '33[%_ptr_Workgroup_v4float]' cannot be a "
                         "type"));
 }
 
diff --git a/third_party/SPIRV-Tools/test/val/val_barriers_test.cpp b/third_party/SPIRV-Tools/test/val/val_barriers_test.cpp
index f27e467..c86cdc1 100644
--- a/third_party/SPIRV-Tools/test/val/val_barriers_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_barriers_test.cpp
@@ -254,8 +254,9 @@
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("OpControlBarrier requires one of the following Execution "
-                "Models: TessellationControl, GLCompute or Kernel"));
+      HasSubstr("OpControlBarrier requires one of the following "
+                "Execution Models: TessellationControl, GLCompute, Kernel, "
+                "MeshNV or TaskNV"));
 }
 
 TEST_F(ValidateBarriers, OpControlBarrierExecutionModelFragmentSpirv13) {
@@ -359,6 +360,8 @@
 
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-SubgroupVoteKHR-06997"));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -413,10 +416,12 @@
   CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
   EXPECT_THAT(getDiagnosticString(),
-              AnyVUID("VUID-StandaloneSpirv-None-04639"));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Workgroup Memory Scope is limited to MeshNV, TaskNV, "
-                        "and GLCompute execution model"));
+              AnyVUID("VUID-StandaloneSpirv-None-07321"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Workgroup Memory Scope is limited to MeshNV, "
+                "TaskNV, MeshEXT, TaskEXT, TessellationControl, and GLCompute "
+                "execution model"));
 }
 
 TEST_F(ValidateBarriers,
@@ -431,8 +436,8 @@
               AnyVUID("VUID-StandaloneSpirv-None-04637"));
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("in Vulkan environment, Workgroup execution scope is "
-                        "only for TaskNV, MeshNV, TessellationControl, and "
-                        "GLCompute execution models"));
+                        "only for TaskNV, MeshNV, TaskEXT, MeshEXT, "
+                        "TessellationControl, and GLCompute execution models"));
 }
 
 TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupComputeSuccess) {
@@ -542,10 +547,11 @@
   CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
                       SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpControlBarrier requires one of the following Execution "
-                "Models: TessellationControl, GLCompute or Kernel"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpControlBarrier requires one of the following "
+                        "Execution "
+                        "Models: TessellationControl, GLCompute, Kernel, "
+                        "MeshNV or TaskNV"));
 }
 
 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p1) {
@@ -586,8 +592,9 @@
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("OpControlBarrier requires one of the following Execution "
-                "Models: TessellationControl, GLCompute or Kernel"));
+      HasSubstr("OpControlBarrier requires one of the following "
+                "Execution Models: TessellationControl, GLCompute, Kernel, "
+                "MeshNV or TaskNV"));
 }
 
 TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p1) {
@@ -629,10 +636,11 @@
       GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
       SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpControlBarrier requires one of the following Execution "
-                "Models: TessellationControl, GLCompute or Kernel"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpControlBarrier requires one of the following "
+                        "Execution "
+                        "Models: TessellationControl, GLCompute, Kernel, "
+                        "MeshNV or TaskNV"));
 }
 
 TEST_F(ValidateBarriers,
@@ -677,10 +685,11 @@
                                          "TessellationEvaluation"),
                       SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpControlBarrier requires one of the following Execution "
-                "Models: TessellationControl, GLCompute or Kernel"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpControlBarrier requires one of the following "
+                        "Execution "
+                        "Models: TessellationControl, GLCompute, Kernel, "
+                        "MeshNV or TaskNV"));
 }
 
 TEST_F(ValidateBarriers, OpMemoryBarrierSuccess) {
@@ -765,6 +774,8 @@
 
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-SubgroupVoteKHR-06997"));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -960,7 +971,7 @@
 
   CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 5[%uint] cannot be a "
+  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '5[%uint]' cannot be a "
                                                "type"));
 }
 
diff --git a/third_party/SPIRV-Tools/test/val/val_builtins_test.cpp b/third_party/SPIRV-Tools/test/val/val_builtins_test.cpp
index 2cbe9a8..4f9fc97 100644
--- a/third_party/SPIRV-Tools/test/val/val_builtins_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_builtins_test.cpp
@@ -60,8 +60,9 @@
 using ValidateVulkanCombineBuiltInExecutionModelDataTypeResult =
     spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
                                      const char*, const char*, TestResult>>;
-using ValidateVulkanCombineBuiltInArrayedVariable = spvtest::ValidateBase<
-    std::tuple<const char*, const char*, const char*, const char*, TestResult>>;
+using ValidateVulkanCombineBuiltInArrayedVariable =
+    spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
+                                     const char*, const char*, TestResult>>;
 using ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult =
     spvtest::ValidateBase<
         std::tuple<const char*, const char*, const char*, const char*,
@@ -784,8 +785,8 @@
                    "VUID-NumWorkgroups-NumWorkgroups-04296 "
                    "VUID-WorkgroupId-WorkgroupId-04422"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "to be used only with GLCompute, MeshNV, or "
-                              "TaskNV execution model"))));
+                              "to be used only with GLCompute, MeshNV, "
+                              "TaskNV, MeshEXT or TaskEXT execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
     ComputeShaderInputInt32Vec3NotInput,
@@ -1006,7 +1007,7 @@
         Values("VUID-Layer-Layer-04274 VUID-ViewportIndex-ViewportIndex-04406"),
         Values(TestResult(SPV_ERROR_INVALID_DATA,
                           "Input storage class if execution model is Vertex, "
-                          "TessellationEvaluation, Geometry, or MeshNV",
+                          "TessellationEvaluation, Geometry, MeshNV or MeshEXT",
                           "which is called with execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
@@ -1311,14 +1312,14 @@
 INSTANTIATE_TEST_SUITE_P(
     PrimitiveIdInvalidExecutionModel,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
-    Combine(Values("PrimitiveId"), Values("Vertex", "GLCompute"),
-            Values("Input"), Values("%u32"),
-            Values("VUID-PrimitiveId-PrimitiveId-04330"),
-            Values(TestResult(
-                SPV_ERROR_INVALID_DATA,
-                "to be used only with Fragment, TessellationControl, "
-                "TessellationEvaluation, Geometry, MeshNV, IntersectionKHR, "
-                "AnyHitKHR, and ClosestHitKHR execution models"))));
+    Combine(
+        Values("PrimitiveId"), Values("Vertex", "GLCompute"), Values("Input"),
+        Values("%u32"), Values("VUID-PrimitiveId-PrimitiveId-04330"),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "to be used only with Fragment, TessellationControl, "
+                          "TessellationEvaluation, Geometry, MeshNV, MeshEXT, "
+                          "IntersectionKHR, "
+                          "AnyHitKHR, and ClosestHitKHR execution models"))));
 
 INSTANTIATE_TEST_SUITE_P(
     PrimitiveIdFragmentNotInput,
@@ -1867,16 +1868,18 @@
 INSTANTIATE_TEST_SUITE_P(
     DrawIndexInvalidExecutionModel,
     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
-    Combine(Values("DrawIndex"),
-            Values("Fragment", "GLCompute", "Geometry", "TessellationControl",
-                   "TessellationEvaluation"),
-            Values("Input"), Values("%u32"),
-            Values("OpCapability DrawParameters\n"),
-            Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
-            Values("VUID-DrawIndex-DrawIndex-04207"),
-            Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "to be used only with Vertex, MeshNV, or TaskNV "
-                              "execution model"))));
+    Combine(
+        Values("DrawIndex"),
+        Values("Fragment", "GLCompute", "Geometry", "TessellationControl",
+               "TessellationEvaluation"),
+        Values("Input"), Values("%u32"),
+        Values("OpCapability DrawParameters\n"),
+        Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
+        Values("VUID-DrawIndex-DrawIndex-04207"),
+        Values(TestResult(
+            SPV_ERROR_INVALID_DATA,
+            "to be used only with Vertex, MeshNV, TaskNV , MeshEXT or TaskEXT "
+            "execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
     DrawIndexNotInput,
@@ -2164,17 +2167,17 @@
 INSTANTIATE_TEST_SUITE_P(
     PrimitiveIdRTNotExecutionMode,
     ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
-    Combine(Values(SPV_ENV_VULKAN_1_2), Values("PrimitiveId"),
-            Values("RayGenerationKHR", "MissKHR", "CallableKHR"),
-            Values("Input"), Values("%u32"),
-            Values("OpCapability RayTracingKHR\n"),
-            Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
-            Values("VUID-PrimitiveId-PrimitiveId-04330"),
-            Values(TestResult(
-                SPV_ERROR_INVALID_DATA,
-                "to be used only with Fragment, TessellationControl, "
-                "TessellationEvaluation, Geometry, MeshNV, IntersectionKHR, "
-                "AnyHitKHR, and ClosestHitKHR execution models"))));
+    Combine(
+        Values(SPV_ENV_VULKAN_1_2), Values("PrimitiveId"),
+        Values("RayGenerationKHR", "MissKHR", "CallableKHR"), Values("Input"),
+        Values("%u32"), Values("OpCapability RayTracingKHR\n"),
+        Values("OpExtension \"SPV_KHR_ray_tracing\"\n"),
+        Values("VUID-PrimitiveId-PrimitiveId-04330"),
+        Values(TestResult(SPV_ERROR_INVALID_DATA,
+                          "to be used only with Fragment, TessellationControl, "
+                          "TessellationEvaluation, Geometry, MeshNV, MeshEXT, "
+                          "IntersectionKHR, "
+                          "AnyHitKHR, and ClosestHitKHR execution models"))));
 
 INSTANTIATE_TEST_SUITE_P(
     PrimitiveIdRTNotInput,
@@ -2676,7 +2679,8 @@
   const char* const execution_model = std::get<1>(GetParam());
   const char* const storage_class = std::get<2>(GetParam());
   const char* const data_type = std::get<3>(GetParam());
-  const TestResult& test_result = std::get<4>(GetParam());
+  const char* const vuid = std::get<4>(GetParam());
+  const TestResult& test_result = std::get<5>(GetParam());
 
   CodeGenerator generator = GetArrayedVariableCodeGenerator(
       built_in, execution_model, storage_class, data_type);
@@ -2690,18 +2694,20 @@
   if (test_result.error_str2) {
     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
   }
+  if (vuid) {
+    EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
+  }
 }
 
-INSTANTIATE_TEST_SUITE_P(PointSizeArrayedF32TessControl,
-                         ValidateVulkanCombineBuiltInArrayedVariable,
-                         Combine(Values("PointSize"),
-                                 Values("TessellationControl"), Values("Input"),
-                                 Values("%f32"), Values(TestResult())));
+INSTANTIATE_TEST_SUITE_P(
+    PointSizeArrayedF32TessControl, ValidateVulkanCombineBuiltInArrayedVariable,
+    Combine(Values("PointSize"), Values("TessellationControl"), Values("Input"),
+            Values("%f32"), Values(nullptr), Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PointSizeArrayedF64TessControl, ValidateVulkanCombineBuiltInArrayedVariable,
     Combine(Values("PointSize"), Values("TessellationControl"), Values("Input"),
-            Values("%f64"),
+            Values("%f64"), Values("VUID-PointSize-PointSize-04317"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float scalar",
                               "has bit width 64"))));
@@ -2709,7 +2715,7 @@
 INSTANTIATE_TEST_SUITE_P(
     PointSizeArrayedF32Vertex, ValidateVulkanCombineBuiltInArrayedVariable,
     Combine(Values("PointSize"), Values("Vertex"), Values("Output"),
-            Values("%f32"),
+            Values("%f32"), Values("VUID-PointSize-PointSize-04317"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float scalar",
                               "is not a float scalar"))));
@@ -2718,13 +2724,14 @@
                          ValidateVulkanCombineBuiltInArrayedVariable,
                          Combine(Values("Position"),
                                  Values("TessellationControl"), Values("Input"),
-                                 Values("%f32vec4"), Values(TestResult())));
+                                 Values("%f32vec4"), Values(nullptr),
+                                 Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     PositionArrayedF32Vec3TessControl,
     ValidateVulkanCombineBuiltInArrayedVariable,
     Combine(Values("Position"), Values("TessellationControl"), Values("Input"),
-            Values("%f32vec3"),
+            Values("%f32vec3"), Values("VUID-Position-Position-04321"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float vector",
                               "has 3 components"))));
@@ -2732,7 +2739,7 @@
 INSTANTIATE_TEST_SUITE_P(
     PositionArrayedF32Vec4Vertex, ValidateVulkanCombineBuiltInArrayedVariable,
     Combine(Values("Position"), Values("Vertex"), Values("Output"),
-            Values("%f32vec4"),
+            Values("%f32vec4"), Values("VUID-Position-Position-04321"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 4-component 32-bit float vector",
                               "is not a float vector"))));
@@ -2742,13 +2749,15 @@
     ValidateVulkanCombineBuiltInArrayedVariable,
     Combine(Values("ClipDistance", "CullDistance"),
             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
-            Values("Output"), Values("%f32arr2", "%f32arr4"),
+            Values("Output"), Values("%f32arr2", "%f32arr4"), Values(nullptr),
             Values(TestResult())));
 
 INSTANTIATE_TEST_SUITE_P(
     ClipAndCullDistanceVertexInput, ValidateVulkanCombineBuiltInArrayedVariable,
     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
             Values("Input"), Values("%f32arr4"),
+            Values("VUID-ClipDistance-ClipDistance-04191 "
+                   "VUID-CullDistance-CullDistance-04200"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float array",
                               "components are not float scalar"))));
@@ -2758,6 +2767,8 @@
     Combine(Values("ClipDistance", "CullDistance"),
             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
             Values("Input"), Values("%f32vec2", "%f32vec4"),
+            Values("VUID-ClipDistance-ClipDistance-04191 "
+                   "VUID-CullDistance-CullDistance-04200"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
                               "needs to be a 32-bit float array",
                               "components are not float scalar"))));
@@ -2840,6 +2851,61 @@
                               "needs to be a 32-bit int scalar",
                               "has bit width 64"))));
 
+INSTANTIATE_TEST_SUITE_P(
+    ArmCoreBuiltinsInputSuccess,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("CoreIDARM", "CoreCountARM", "CoreMaxIDARM", "WarpIDARM",
+                   "WarpMaxIDARM"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "GLCompute"),
+            Values("Input"), Values("%u32"),
+            Values("OpCapability CoreBuiltinsARM\n"),
+            Values("OpExtension \"SPV_ARM_core_builtins\"\n"), Values(nullptr),
+            Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+    ArmCoreBuiltinsNotInput,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("CoreIDARM", "CoreCountARM", "CoreMaxIDARM", "WarpIDARM",
+                   "WarpMaxIDARM"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "GLCompute"),
+            Values("Output"), Values("%u32"),
+            Values("OpCapability CoreBuiltinsARM\n"),
+            Values("OpExtension \"SPV_ARM_core_builtins\"\n"), Values(nullptr),
+            Values(TestResult(
+                SPV_ERROR_INVALID_DATA,
+                "to be only used for variables with Input storage class",
+                "uses storage class Output"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    ArmCoreBuiltinsNotIntScalar,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("CoreIDARM", "CoreCountARM", "CoreMaxIDARM", "WarpIDARM",
+                   "WarpMaxIDARM"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "GLCompute"),
+            Values("Input"), Values("%f32", "%u32vec3"),
+            Values("OpCapability CoreBuiltinsARM\n"),
+            Values("OpExtension \"SPV_ARM_core_builtins\"\n"), Values(nullptr),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "needs to be a 32-bit int scalar",
+                              "is not an int scalar"))));
+
+INSTANTIATE_TEST_SUITE_P(
+    ArmCoreBuiltinsNotInt32,
+    ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+    Combine(Values("CoreIDARM", "CoreCountARM", "CoreMaxIDARM", "WarpIDARM",
+                   "WarpMaxIDARM"),
+            Values("Vertex", "Fragment", "TessellationControl",
+                   "TessellationEvaluation", "Geometry", "GLCompute"),
+            Values("Input"), Values("%u64"),
+            Values("OpCapability CoreBuiltinsARM\n"),
+            Values("OpExtension \"SPV_ARM_core_builtins\"\n"), Values(nullptr),
+            Values(TestResult(SPV_ERROR_INVALID_DATA,
+                              "needs to be a 32-bit int scalar",
+                              "has bit width 64"))));
+
 CodeGenerator GetWorkgroupSizeSuccessGenerator() {
   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
 
@@ -2896,10 +2962,10 @@
 
   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Vulkan spec allows BuiltIn WorkgroupSize to be used "
-                "only with GLCompute, MeshNV, or TaskNV execution model"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Vulkan spec allows BuiltIn WorkgroupSize to be used "
+                        "only with GLCompute, MeshNV, TaskNV, MeshEXT or "
+                        "TaskEXT execution model"));
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("is referencing ID <2> (OpConstantComposite) which is "
                         "decorated with BuiltIn WorkgroupSize in function <1> "
@@ -3356,7 +3422,7 @@
 OpFunctionEnd
 )";
 
-    generator.add_at_the_end_ = function_body;
+  generator.add_at_the_end_ = function_body;
 
   return generator;
 }
@@ -3419,7 +3485,7 @@
 OpFunctionEnd
 )";
 
-    generator.add_at_the_end_ = function_body;
+  generator.add_at_the_end_ = function_body;
 
   return generator;
 }
@@ -3437,7 +3503,6 @@
               HasSubstr("VUID-FragDepth-FragDepth-04216"));
 }
 
-
 TEST_F(ValidateBuiltIns, AllowInstanceIdWithIntersectionShader) {
   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
   generator.capabilities_ += R"(
@@ -3766,8 +3831,8 @@
             Values("VUID-SubgroupId-SubgroupId-04367 "
                    "VUID-NumSubgroups-NumSubgroups-04293"),
             Values(TestResult(SPV_ERROR_INVALID_DATA,
-                              "to be used only with GLCompute, MeshNV, or "
-                              "TaskNV execution model"))));
+                              "to be used only with GLCompute, MeshNV, "
+                              "TaskNV, MeshEXT or TaskEXT execution model"))));
 
 INSTANTIATE_TEST_SUITE_P(
     SubgroupNumAndIdNotU32, ValidateVulkanSubgroupBuiltIns,
diff --git a/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp b/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp
index ede51a9..d2edec1 100644
--- a/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp
@@ -37,7 +37,7 @@
 using ::testing::HasSubstr;
 using ::testing::MatchesRegex;
 
-using ValidateCFG = spvtest::ValidateBase<SpvCapability>;
+using ValidateCFG = spvtest::ValidateBase<spv::Capability>;
 using spvtest::ScopedContext;
 
 std::string nameOps() { return ""; }
@@ -58,7 +58,7 @@
 class Block {
   std::string label_;
   std::string body_;
-  SpvOp type_;
+  spv::Op type_;
   std::vector<Block> successors_;
 
  public:
@@ -66,7 +66,7 @@
   ///
   /// @param[in]: label the label id of the block
   /// @param[in]: type the branch instruction that ends the block
-  explicit Block(std::string label, SpvOp type = SpvOpBranch)
+  explicit Block(std::string label, spv::Op type = spv::Op::OpBranch)
       : label_(label), body_(), type_(type), successors_() {}
 
   /// Sets the instructions which will appear in the body of the block
@@ -89,13 +89,13 @@
     }
 
     switch (type_) {
-      case SpvOpBranchConditional:
+      case spv::Op::OpBranchConditional:
         out << "OpBranchConditional %cond ";
         for (Block& b : successors_) {
           out << "%" + b.label_ + " ";
         }
         break;
-      case SpvOpSwitch: {
+      case spv::Op::OpSwitch: {
         out << "OpSwitch %one %" + successors_.front().label_;
         std::stringstream ss;
         for (size_t i = 1; i < successors_.size(); i++) {
@@ -103,25 +103,25 @@
         }
         out << ss.str();
       } break;
-      case SpvOpLoopMerge: {
+      case spv::Op::OpLoopMerge: {
         assert(successors_.size() == 2);
         out << "OpLoopMerge %" + successors_[0].label_ + " %" +
                    successors_[0].label_ + "None";
       } break;
 
-      case SpvOpReturn:
+      case spv::Op::OpReturn:
         assert(successors_.size() == 0);
         out << "OpReturn\n";
         break;
-      case SpvOpUnreachable:
+      case spv::Op::OpUnreachable:
         assert(successors_.size() == 0);
         out << "OpUnreachable\n";
         break;
-      case SpvOpBranch:
+      case spv::Op::OpBranch:
         assert(successors_.size() == 1);
         out << "OpBranch %" + successors_.front().label_;
         break;
-      case SpvOpKill:
+      case spv::Op::OpKill:
         assert(successors_.size() == 0);
         out << "OpKill\n";
         break;
@@ -138,9 +138,9 @@
 
 /// Assigns the successors for the Block on the lhs
 Block& operator>>(Block& lhs, std::vector<Block> successors) {
-  if (lhs.type_ == SpvOpBranchConditional) {
+  if (lhs.type_ == spv::Op::OpBranchConditional) {
     assert(successors.size() == 2);
-  } else if (lhs.type_ == SpvOpSwitch) {
+  } else if (lhs.type_ == spv::Op::OpSwitch) {
     assert(successors.size() > 1);
   }
   lhs.successors_ = successors;
@@ -149,12 +149,12 @@
 
 /// Assigns the successor for the Block on the lhs
 Block& operator>>(Block& lhs, Block& successor) {
-  assert(lhs.type_ == SpvOpBranch);
+  assert(lhs.type_ == spv::Op::OpBranch);
   lhs.successors_.push_back(successor);
   return lhs;
 }
 
-const std::string& GetDefaultHeader(SpvCapability cap) {
+const std::string& GetDefaultHeader(spv::Capability cap) {
   static const std::string shader_header =
       "OpCapability Shader\n"
       "OpCapability Linkage\n"
@@ -165,7 +165,7 @@
       "OpCapability Linkage\n"
       "OpMemoryModel Logical OpenCL\n";
 
-  return (cap == SpvCapabilityShader) ? shader_header : kernel_header;
+  return (cap == spv::Capability::Shader) ? shader_header : kernel_header;
 }
 
 const std::string& types_consts() {
@@ -181,8 +181,8 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(StructuredControlFlow, ValidateCFG,
-                         ::testing::Values(SpvCapabilityShader,
-                                           SpvCapabilityKernel));
+                         ::testing::Values(spv::Capability::Shader,
+                                           spv::Capability::Kernel));
 
 TEST_P(ValidateCFG, LoopReachableFromEntryButNeverLeadingToReturn) {
   // In this case, the loop is reachable from a node without a predecessor,
@@ -268,11 +268,11 @@
 }
 
 TEST_P(ValidateCFG, Simple) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
+  Block loop("loop", spv::Op::OpBranchConditional);
   Block cont("cont");
-  Block merge("merge", SpvOpReturn);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -298,7 +298,7 @@
 TEST_P(ValidateCFG, Variable) {
   Block entry("entry");
   Block cont("cont");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%var = OpVariable %ptrt Function\n");
 
@@ -317,7 +317,7 @@
 TEST_P(ValidateCFG, VariableNotInFirstBlockBad) {
   Block entry("entry");
   Block cont("cont");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   // This operation should only be performed in the entry block
   cont.SetBody("%var = OpVariable %ptrt Function\n");
@@ -339,10 +339,10 @@
 }
 
 TEST_P(ValidateCFG, BlockSelfLoopIsOk) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %loop None\n");
@@ -363,11 +363,11 @@
 }
 
 TEST_P(ValidateCFG, BlockAppearsBeforeDominatorBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   Block cont("cont");
-  Block branch("branch", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) branch.SetBody("OpSelectionMerge %merge None\n");
@@ -386,17 +386,17 @@
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              MatchesRegex("Block .\\[%cont\\] appears in the binary "
-                           "before its dominator .\\[%branch\\]\n"
+              MatchesRegex("Block '.\\[%cont\\]' appears in the binary "
+                           "before its dominator '.\\[%branch\\]'\n"
                            "  %branch = OpLabel\n"));
 }
 
 TEST_P(ValidateCFG, MergeBlockTargetedByMultipleHeaderBlocksBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   Block loop("loop");
-  Block selection("selection", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block selection("selection", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody(" OpLoopMerge %merge %loop None\n");
@@ -419,7 +419,7 @@
   if (is_shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
-                MatchesRegex("Block .\\[%merge\\] is already a merge block "
+                MatchesRegex("Block '.\\[%merge\\]' is already a merge block "
                              "for another header\n"
                              "  %Main = OpFunction %void None %9\n"));
   } else {
@@ -428,11 +428,11 @@
 }
 
 TEST_P(ValidateCFG, MergeBlockTargetedByMultipleHeaderBlocksSelectionBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block selection("selection", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block selection("selection", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) selection.SetBody(" OpSelectionMerge %merge None\n");
@@ -455,7 +455,7 @@
   if (is_shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
-                MatchesRegex("Block .\\[%merge\\] is already a merge block "
+                MatchesRegex("Block '.\\[%merge\\]' is already a merge block "
                              "for another header\n"
                              "  %Main = OpFunction %void None %9\n"));
   } else {
@@ -466,7 +466,7 @@
 TEST_P(ValidateCFG, BranchTargetFirstBlockBadSinceEntryBlock) {
   Block entry("entry");
   Block bad("bad");
-  Block end("end", SpvOpReturn);
+  Block end("end", spv::Op::OpReturn);
   std::string str = GetDefaultHeader(GetParam()) +
                     nameOps("entry", "bad", std::make_pair("func", "Main")) +
                     types_consts() +
@@ -480,8 +480,8 @@
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              MatchesRegex("First block .\\[%entry\\] of function "
-                           ".\\[%Main\\] is targeted by block .\\[%bad\\]\n"
+              MatchesRegex("First block '.\\[%entry\\]' of function "
+                           "'.\\[%Main\\]' is targeted by block '.\\[%bad\\]'\n"
                            "  %Main = OpFunction %void None %10\n"));
 }
 
@@ -489,7 +489,7 @@
   Block entry("entry");
   entry.SetBody("%undef = OpUndef %boolt\n");
   Block bad("bad");
-  Block end("end", SpvOpReturn);
+  Block end("end", spv::Op::OpReturn);
   Block badvalue("undef");  // This references the OpUndef.
   std::string str = GetDefaultHeader(GetParam()) +
                     nameOps("entry", "bad", std::make_pair("func", "Main")) +
@@ -511,8 +511,8 @@
 
 TEST_P(ValidateCFG, BranchConditionalTrueTargetFirstBlockBad) {
   Block entry("entry");
-  Block bad("bad", SpvOpBranchConditional);
-  Block exit("exit", SpvOpReturn);
+  Block bad("bad", spv::Op::OpBranchConditional);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   bad.SetBody(" OpLoopMerge %entry %exit None\n");
@@ -529,18 +529,19 @@
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              MatchesRegex("First block .\\[%entry\\] of function .\\[%Main\\] "
-                           "is targeted by block .\\[%bad\\]\n"
-                           "  %Main = OpFunction %void None %10\n"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      MatchesRegex("First block '.\\[%entry\\]' of function '.\\[%Main\\]' "
+                   "is targeted by block '.\\[%bad\\]'\n"
+                   "  %Main = OpFunction %void None %10\n"));
 }
 
 TEST_P(ValidateCFG, BranchConditionalFalseTargetFirstBlockBad) {
   Block entry("entry");
-  Block bad("bad", SpvOpBranchConditional);
+  Block bad("bad", spv::Op::OpBranchConditional);
   Block t("t");
   Block merge("merge");
-  Block end("end", SpvOpReturn);
+  Block end("end", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   bad.SetBody("OpLoopMerge %merge %cont None\n");
@@ -558,21 +559,22 @@
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              MatchesRegex("First block .\\[%entry\\] of function .\\[%Main\\] "
-                           "is targeted by block .\\[%bad\\]\n"
-                           "  %Main = OpFunction %void None %10\n"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      MatchesRegex("First block '.\\[%entry\\]' of function '.\\[%Main\\]' "
+                   "is targeted by block '.\\[%bad\\]'\n"
+                   "  %Main = OpFunction %void None %10\n"));
 }
 
 TEST_P(ValidateCFG, SwitchTargetFirstBlockBad) {
   Block entry("entry");
-  Block bad("bad", SpvOpSwitch);
+  Block bad("bad", spv::Op::OpSwitch);
   Block block1("block1");
   Block block2("block2");
   Block block3("block3");
   Block def("def");  // default block
   Block merge("merge");
-  Block end("end", SpvOpReturn);
+  Block end("end", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   bad.SetBody("OpSelectionMerge %merge None\n");
@@ -594,23 +596,24 @@
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              MatchesRegex("First block .\\[%entry\\] of function .\\[%Main\\] "
-                           "is targeted by block .\\[%bad\\]\n"
-                           "  %Main = OpFunction %void None %10\n"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      MatchesRegex("First block '.\\[%entry\\]' of function '.\\[%Main\\]' "
+                   "is targeted by block '.\\[%bad\\]'\n"
+                   "  %Main = OpFunction %void None %10\n"));
 }
 
 TEST_P(ValidateCFG, BranchToBlockInOtherFunctionBad) {
   Block entry("entry");
-  Block middle("middle", SpvOpBranchConditional);
-  Block end("end", SpvOpReturn);
+  Block middle("middle", spv::Op::OpBranchConditional);
+  Block end("end", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   middle.SetBody("OpSelectionMerge %end None\n");
 
   Block entry2("entry2");
   Block middle2("middle2");
-  Block end2("end2", SpvOpReturn);
+  Block end2("end2", spv::Op::OpReturn);
 
   std::string str = GetDefaultHeader(GetParam()) +
                     nameOps("middle2", std::make_pair("func", "Main")) +
@@ -630,19 +633,19 @@
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      MatchesRegex("Block\\(s\\) \\{.\\[%middle2\\]\\} are referenced but not "
-                   "defined in function .\\[%Main\\]\n"
-                   "  %Main = OpFunction %void None %9\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              MatchesRegex(
+                  "Block\\(s\\) \\{'.\\[%middle2\\]'\\} are referenced but not "
+                  "defined in function '.\\[%Main\\]'\n"
+                  "  %Main = OpFunction %void None %9\n"));
 }
 
 TEST_P(ValidateCFG, HeaderDoesntStrictlyDominateMergeBad) {
   // If a merge block is reachable, then it must be strictly dominated by
   // its header block.
-  bool is_shader = GetParam() == SpvCapabilityShader;
-  Block head("head", SpvOpBranchConditional);
-  Block exit("exit", SpvOpReturn);
+  bool is_shader = GetParam() == spv::Capability::Shader;
+  Block head("head", spv::Op::OpBranchConditional);
+  Block exit("exit", spv::Op::OpReturn);
 
   head.SetBody("%cond = OpSLessThan %boolt %one %two\n");
 
@@ -662,25 +665,26 @@
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(
         getDiagnosticString(),
-        MatchesRegex("The selection construct with the selection header "
-                     ".\\[%head\\] does not strictly structurally dominate the "
-                     "merge block "
-                     ".\\[%head\\]\n  %head = OpLabel\n"));
+        MatchesRegex(
+            "The selection construct with the selection header "
+            "'.\\[%head\\]' does not strictly structurally dominate the "
+            "merge block "
+            "'.\\[%head\\]'\n  %head = OpLabel\n"));
   } else {
     ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << str;
   }
 }
 
-std::string GetUnreachableMergeNoMergeInst(SpvCapability cap) {
+std::string GetUnreachableMergeNoMergeInst(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpReturn);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   std::string str = header;
@@ -701,18 +705,18 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeTerminatedBy(SpvCapability cap, SpvOp op) {
+std::string GetUnreachableMergeTerminatedBy(spv::Capability cap, spv::Op op) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
   Block merge("merge", op);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   str += nameOps("branch", "merge", std::make_pair("func", "Main"));
@@ -730,33 +734,35 @@
 
 TEST_P(ValidateCFG, UnreachableMergeTerminatedByOpUnreachable) {
   CompileSuccessfully(
-      GetUnreachableMergeTerminatedBy(GetParam(), SpvOpUnreachable));
+      GetUnreachableMergeTerminatedBy(GetParam(), spv::Op::OpUnreachable));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
 TEST_F(ValidateCFG, UnreachableMergeTerminatedByOpKill) {
-  CompileSuccessfully(
-      GetUnreachableMergeTerminatedBy(SpvCapabilityShader, SpvOpKill));
+  CompileSuccessfully(GetUnreachableMergeTerminatedBy(spv::Capability::Shader,
+                                                      spv::Op::OpKill));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
 TEST_P(ValidateCFG, UnreachableMergeTerminatedByOpReturn) {
-  CompileSuccessfully(GetUnreachableMergeTerminatedBy(GetParam(), SpvOpReturn));
+  CompileSuccessfully(
+      GetUnreachableMergeTerminatedBy(GetParam(), spv::Op::OpReturn));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableContinueTerminatedBy(SpvCapability cap, SpvOp op) {
+std::string GetUnreachableContinueTerminatedBy(spv::Capability cap,
+                                               spv::Op op) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
   Block target("target", op);
 
-  if (op == SpvOpBranch) target >> branch;
+  if (op == spv::Op::OpBranch) target >> branch;
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
 
   str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
@@ -771,10 +777,10 @@
   return str;
 }
 
-TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpUnreachable) {
+TEST_P(ValidateCFG, UnreachableContinueTerminatedByOpUnreachable) {
   CompileSuccessfully(
-      GetUnreachableContinueTerminatedBy(GetParam(), SpvOpUnreachable));
-  if (GetParam() == SpvCapabilityShader) {
+      GetUnreachableContinueTerminatedBy(GetParam(), spv::Op::OpUnreachable));
+  if (GetParam() == spv::Capability::Shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
                 HasSubstr("targeted by 0 back-edge blocks"));
@@ -783,18 +789,18 @@
   }
 }
 
-TEST_F(ValidateCFG, UnreachableContinueTerminatedBySpvOpKill) {
-  CompileSuccessfully(
-      GetUnreachableContinueTerminatedBy(SpvCapabilityShader, SpvOpKill));
+TEST_F(ValidateCFG, UnreachableContinueTerminatedByOpKill) {
+  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
+      spv::Capability::Shader, spv::Op::OpKill));
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("targeted by 0 back-edge blocks"));
 }
 
-TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpReturn) {
+TEST_P(ValidateCFG, UnreachableContinueTerminatedByOpReturn) {
   CompileSuccessfully(
-      GetUnreachableContinueTerminatedBy(GetParam(), SpvOpReturn));
-  if (GetParam() == SpvCapabilityShader) {
+      GetUnreachableContinueTerminatedBy(GetParam(), spv::Op::OpReturn));
+  if (GetParam() == spv::Capability::Shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
                 HasSubstr("targeted by 0 back-edge blocks"));
@@ -803,25 +809,25 @@
   }
 }
 
-TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpBranch) {
+TEST_P(ValidateCFG, UnreachableContinueTerminatedByOpBranch) {
   CompileSuccessfully(
-      GetUnreachableContinueTerminatedBy(GetParam(), SpvOpBranch));
+      GetUnreachableContinueTerminatedBy(GetParam(), spv::Op::OpBranch));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeUnreachableMergeInst(SpvCapability cap) {
+std::string GetUnreachableMergeUnreachableMergeInst(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
-  Block body("body", SpvOpReturn);
+  Block body("body", spv::Op::OpReturn);
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpUnreachable);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpUnreachable);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   str += nameOps("branch", "merge", std::make_pair("func", "Main"));
@@ -843,19 +849,19 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableContinueUnreachableLoopInst(SpvCapability cap) {
+std::string GetUnreachableContinueUnreachableLoopInst(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
-  Block body("body", SpvOpReturn);
+  Block body("body", spv::Op::OpReturn);
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
 
   target >> branch;
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
 
   str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
@@ -876,21 +882,21 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeWithComplexBody(SpvCapability cap) {
+std::string GetUnreachableMergeWithComplexBody(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpUnreachable);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpUnreachable);
 
   entry.AppendBody("%placeholder   = OpVariable %intptrt Function\n");
   entry.AppendBody("%cond    = OpSLessThan %boolt %one %two\n");
   merge.AppendBody("OpStore %placeholder %one\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   str += nameOps("branch", "merge", std::make_pair("func", "Main"));
@@ -912,13 +918,13 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableContinueWithComplexBody(SpvCapability cap) {
+std::string GetUnreachableContinueWithComplexBody(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
 
   target >> branch;
 
@@ -926,7 +932,7 @@
   target.AppendBody("OpStore %placeholder %one\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
 
   str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
@@ -947,19 +953,19 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeWithBranchUse(SpvCapability cap) {
+std::string GetUnreachableMergeWithBranchUse(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpBranch);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpUnreachable);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpBranch);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpUnreachable);
 
   entry.AppendBody("%cond    = OpSLessThan %boolt %one %two\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   str += nameOps("branch", "merge", std::make_pair("func", "Main"));
@@ -980,20 +986,20 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeWithMultipleUses(SpvCapability cap) {
+std::string GetUnreachableMergeWithMultipleUses(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpUnreachable);
-  Block duplicate("duplicate", SpvOpBranchConditional);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpUnreachable);
+  Block duplicate("duplicate", spv::Op::OpBranchConditional);
 
   entry.AppendBody("%cond    = OpSLessThan %boolt %one %two\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader) {
+  if (cap == spv::Capability::Shader) {
     branch.AppendBody("OpSelectionMerge %merge None\n");
     duplicate.AppendBody("OpSelectionMerge %merge None\n");
   }
@@ -1014,7 +1020,7 @@
 
 TEST_P(ValidateCFG, UnreachableMergeWithMultipleUses) {
   CompileSuccessfully(GetUnreachableMergeWithMultipleUses(GetParam()));
-  if (GetParam() == SpvCapabilityShader) {
+  if (GetParam() == spv::Capability::Shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
                 HasSubstr("is already a merge block for another header"));
@@ -1023,20 +1029,20 @@
   }
 }
 
-std::string GetUnreachableContinueWithBranchUse(SpvCapability cap) {
+std::string GetUnreachableContinueWithBranchUse(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
 
   target >> branch;
 
   entry.AppendBody("%placeholder   = OpVariable %intptrt Function\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
 
   str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
@@ -1057,16 +1063,16 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetReachableMergeAndContinue(SpvCapability cap) {
+std::string GetReachableMergeAndContinue(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
-  Block body("body", SpvOpBranchConditional);
-  Block t("t", SpvOpBranch);
-  Block f("f", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
+  Block body("body", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpBranch);
+  Block f("f", spv::Op::OpBranch);
 
   target >> branch;
   body.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
@@ -1074,7 +1080,7 @@
   f >> target;
 
   std::string str = header;
-  if (cap == SpvCapabilityShader) {
+  if (cap == spv::Capability::Shader) {
     branch.AppendBody("OpLoopMerge %merge %target None\n");
     body.AppendBody("OpSelectionMerge %f None\n");
   }
@@ -1100,23 +1106,23 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeAndContinue(SpvCapability cap) {
+std::string GetUnreachableMergeAndContinue(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
-  Block body("body", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block pre_target("pre_target", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
+  Block body("body", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block pre_target("pre_target", spv::Op::OpBranch);
 
   target >> branch;
   body.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader) {
+  if (cap == spv::Capability::Shader) {
     branch.AppendBody("OpLoopMerge %merge %target None\n");
     body.AppendBody("OpSelectionMerge %pre_target None\n");
   }
@@ -1143,12 +1149,12 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableBlock(SpvCapability cap) {
+std::string GetUnreachableBlock(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block unreachable("unreachable");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   std::string str = header;
   str += nameOps("unreachable", "exit", std::make_pair("func", "Main"));
@@ -1167,18 +1173,18 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableBranch(SpvCapability cap) {
+std::string GetUnreachableBranch(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block unreachable("unreachable", SpvOpBranchConditional);
+  Block unreachable("unreachable", spv::Op::OpBranchConditional);
   Block unreachablechildt("unreachablechildt");
   Block unreachablechildf("unreachablechildf");
   Block merge("merge");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   unreachable.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     unreachable.AppendBody("OpSelectionMerge %merge None\n");
 
   std::string str = header;
@@ -1215,10 +1221,10 @@
 }
 
 TEST_P(ValidateCFG, SingleBlockLoop) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block exit("exit", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.AppendBody("OpLoopMerge %exit %loop None\n");
@@ -1236,15 +1242,15 @@
 }
 
 TEST_P(ValidateCFG, NestedLoops) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   Block loop1("loop1");
   Block loop1_cont_break_block("loop1_cont_break_block",
-                               SpvOpBranchConditional);
-  Block loop2("loop2", SpvOpBranchConditional);
+                               spv::Op::OpBranchConditional);
+  Block loop2("loop2", spv::Op::OpBranchConditional);
   Block loop2_merge("loop2_merge");
   Block loop1_merge("loop1_merge");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -1271,7 +1277,7 @@
 }
 
 TEST_P(ValidateCFG, NestedSelection) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   const int N = 256;
   std::vector<Block> if_blocks;
@@ -1280,18 +1286,18 @@
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
 
-  if_blocks.emplace_back("if0", SpvOpBranchConditional);
+  if_blocks.emplace_back("if0", spv::Op::OpBranchConditional);
 
   if (is_shader) if_blocks[0].SetBody("OpSelectionMerge %if_merge0 None\n");
-  merge_blocks.emplace_back("if_merge0", SpvOpReturn);
+  merge_blocks.emplace_back("if_merge0", spv::Op::OpReturn);
 
   for (int i = 1; i < N; i++) {
     std::stringstream ss;
     ss << i;
-    if_blocks.emplace_back("if" + ss.str(), SpvOpBranchConditional);
+    if_blocks.emplace_back("if" + ss.str(), spv::Op::OpBranchConditional);
     if (is_shader)
       if_blocks[i].SetBody("OpSelectionMerge %if_merge" + ss.str() + " None\n");
-    merge_blocks.emplace_back("if_merge" + ss.str(), SpvOpBranch);
+    merge_blocks.emplace_back("if_merge" + ss.str(), spv::Op::OpBranch);
   }
   std::string str = GetDefaultHeader(GetParam()) + std::string(types_consts()) +
                     "%func    = OpFunction %voidt None %funct\n";
@@ -1314,14 +1320,14 @@
 }
 
 TEST_P(ValidateCFG, BackEdgeBlockDoesntPostDominateContinueTargetBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop1("loop1", SpvOpBranchConditional);
-  Block loop2("loop2", SpvOpBranchConditional);
+  Block loop1("loop1", spv::Op::OpBranchConditional);
+  Block loop2("loop2", spv::Op::OpBranchConditional);
   Block loop2_merge("loop2_merge");
-  Block loop1_cont("loop1_cont", SpvOpBranchConditional);
+  Block loop1_cont("loop1_cont", spv::Op::OpBranchConditional);
   Block be_block("be_block");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -1344,14 +1350,14 @@
   str += "OpFunctionEnd";
 
   CompileSuccessfully(str);
-  if (GetParam() == SpvCapabilityShader) {
+  if (GetParam() == spv::Capability::Shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(
         getDiagnosticString(),
         MatchesRegex(
             "The continue construct with the continue target "
-            ".\\[%loop1_cont\\] is not structurally post dominated by the "
-            "back-edge block .\\[%be_block\\]\n"
+            "'.\\[%loop1_cont\\]' is not structurally post dominated by the "
+            "back-edge block '.\\[%be_block\\]'\n"
             "  %be_block = OpLabel\n"));
   } else {
     ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
@@ -1359,12 +1365,12 @@
 }
 
 TEST_P(ValidateCFG, BranchingToNonLoopHeaderBlockBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block split("split", SpvOpBranchConditional);
+  Block split("split", spv::Op::OpBranchConditional);
   Block t("t");
   Block f("f");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) split.SetBody("OpSelectionMerge %exit None\n");
@@ -1385,7 +1391,7 @@
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(
         getDiagnosticString(),
-        MatchesRegex("Back-edges \\(.\\[%f\\] -> .\\[%split\\]\\) can only "
+        MatchesRegex("Back-edges \\('.\\[%f\\]' -> '.\\[%split\\]'\\) can only "
                      "be formed between a block and a loop header.\n"
                      "  %f = OpLabel\n"));
   } else {
@@ -1394,10 +1400,10 @@
 }
 
 TEST_P(ValidateCFG, BranchingToSameNonLoopHeaderBlockBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block split("split", SpvOpBranchConditional);
-  Block exit("exit", SpvOpReturn);
+  Block split("split", spv::Op::OpBranchConditional);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) split.SetBody("OpSelectionMerge %exit None\n");
@@ -1417,7 +1423,7 @@
     EXPECT_THAT(
         getDiagnosticString(),
         MatchesRegex(
-            "Back-edges \\(.\\[%split\\] -> .\\[%split\\]\\) can only be "
+            "Back-edges \\('.\\[%split\\]' -> '.\\[%split\\]'\\) can only be "
             "formed between a block and a loop header.\n  %split = OpLabel\n"));
   } else {
     ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
@@ -1425,12 +1431,12 @@
 }
 
 TEST_P(ValidateCFG, MultipleBackEdgeBlocksToLoopHeaderBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
+  Block loop("loop", spv::Op::OpBranchConditional);
   Block back0("back0");
   Block back1("back1");
-  Block merge("merge", SpvOpReturn);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %back0 None\n");
@@ -1452,7 +1458,7 @@
     EXPECT_THAT(
         getDiagnosticString(),
         MatchesRegex(
-            "Loop header .\\[%loop\\] is targeted by 2 back-edge blocks but "
+            "Loop header '.\\[%loop\\]' is targeted by 2 back-edge blocks but "
             "the standard requires exactly one\n  %loop = OpLabel\n"))
         << str;
   } else {
@@ -1461,13 +1467,13 @@
 }
 
 TEST_P(ValidateCFG, ContinueTargetMustBePostDominatedByBackEdge) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block cheader("cheader", SpvOpBranchConditional);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block cheader("cheader", spv::Op::OpBranchConditional);
   Block be_block("be_block");
-  Block merge("merge", SpvOpReturn);
-  Block exit("exit", SpvOpReturn);
+  Block merge("merge", spv::Op::OpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %cheader None\n");
@@ -1487,23 +1493,24 @@
   CompileSuccessfully(str);
   if (is_shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-    EXPECT_THAT(getDiagnosticString(),
-                MatchesRegex(
-                    "The continue construct with the continue target "
-                    ".\\[%cheader\\] is not structurally post dominated by the "
-                    "back-edge block .\\[%be_block\\]\n"
-                    "  %be_block = OpLabel\n"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        MatchesRegex(
+            "The continue construct with the continue target "
+            "'.\\[%cheader\\]' is not structurally post dominated by the "
+            "back-edge block '.\\[%be_block\\]'\n"
+            "  %be_block = OpLabel\n"));
   } else {
     ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
   }
 }
 
 TEST_P(ValidateCFG, BranchOutOfConstructToMergeBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block cont("cont", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block cont("cont", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %loop None\n");
@@ -1524,8 +1531,8 @@
     EXPECT_THAT(
         getDiagnosticString(),
         MatchesRegex("The continue construct with the continue target "
-                     ".\\[%loop\\] is not structurally post dominated by the "
-                     "back-edge block .\\[%cont\\]\n"
+                     "'.\\[%loop\\]' is not structurally post dominated by the "
+                     "back-edge block '.\\[%cont\\]'\n"
                      "  %cont = OpLabel\n"))
         << str;
   } else {
@@ -1534,12 +1541,12 @@
 }
 
 TEST_P(ValidateCFG, BranchOutOfConstructBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block cont("cont", SpvOpBranchConditional);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block cont("cont", spv::Op::OpBranchConditional);
   Block merge("merge");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %loop None\n");
@@ -1561,8 +1568,8 @@
     EXPECT_THAT(
         getDiagnosticString(),
         MatchesRegex("The continue construct with the continue target "
-                     ".\\[%loop\\] is not structurally post dominated by the "
-                     "back-edge block .\\[%cont\\]\n"
+                     "'.\\[%loop\\]' is not structurally post dominated by the "
+                     "back-edge block '.\\[%cont\\]'\n"
                      "  %cont = OpLabel\n"));
   } else {
     ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
@@ -1570,12 +1577,12 @@
 }
 
 TEST_F(ValidateCFG, OpSwitchToUnreachableBlock) {
-  Block entry("entry", SpvOpSwitch);
+  Block entry("entry", spv::Op::OpSwitch);
   Block case0("case0");
   Block case1("case1");
   Block case2("case2");
-  Block def("default", SpvOpUnreachable);
-  Block phi("phi", SpvOpReturn);
+  Block def("default", spv::Op::OpUnreachable);
+  Block phi("phi", spv::Op::OpReturn);
 
   std::string str = R"(
 OpCapability Shader
@@ -1636,7 +1643,7 @@
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      MatchesRegex("Loop header .\\[%loop\\] is targeted by "
+      MatchesRegex("Loop header '.\\[%loop\\]' is targeted by "
                    "0 back-edge blocks but the standard requires exactly "
                    "one\n  %loop = OpLabel\n"));
 }
@@ -1682,13 +1689,13 @@
   // The nested construct has an unreachable merge block.  In the
   // augmented CFG that merge block
   // we still determine that the
-  bool is_shader = GetParam() == SpvCapabilityShader;
-  Block entry("entry", SpvOpBranchConditional);
-  Block inner_head("inner_head", SpvOpBranchConditional);
-  Block inner_true("inner_true", SpvOpReturn);
-  Block inner_false("inner_false", SpvOpReturn);
+  bool is_shader = GetParam() == spv::Capability::Shader;
+  Block entry("entry", spv::Op::OpBranchConditional);
+  Block inner_head("inner_head", spv::Op::OpBranchConditional);
+  Block inner_true("inner_true", spv::Op::OpReturn);
+  Block inner_false("inner_false", spv::Op::OpReturn);
   Block inner_merge("inner_merge");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -1716,13 +1723,13 @@
   // The continue construct cannot be the merge target of a nested selection
   // because the loop construct must contain "if_merge" because it contains
   // "if_head".
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   Block loop("loop");
-  Block if_head("if_head", SpvOpBranchConditional);
+  Block if_head("if_head", spv::Op::OpBranchConditional);
   Block if_true("if_true");
-  Block if_merge("if_merge", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block if_merge("if_merge", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -1748,9 +1755,10 @@
     EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(
         getDiagnosticString(),
-        HasSubstr("Header block 3[%if_head] is contained in the loop construct "
-                  "headed "
-                  "by 2[%loop], but its merge block 5[%if_merge] is not"));
+        HasSubstr(
+            "Header block '3[%if_head]' is contained in the loop construct "
+            "headed "
+            "by '2[%loop]', but its merge block '5[%if_merge]' is not"));
   } else {
     EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
   }
@@ -1759,11 +1767,11 @@
 TEST_P(ValidateCFG, SingleLatchBlockMultipleBranchesToLoopHeader) {
   // This test case ensures we allow both branches of a loop latch block
   // to go back to the loop header.  It still counts as a single back edge.
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block latch("latch", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block latch("latch", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -1955,8 +1963,9 @@
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
-          "Case construct that targets 10[%10] has branches to multiple other "
-          "case construct targets 12[%12] and 11[%11]\n  %10 = OpLabel"));
+          "Case construct that targets '10[%10]' has branches to multiple "
+          "other "
+          "case construct targets '12[%12]' and '11[%11]'\n  %10 = OpLabel"));
 }
 
 TEST_F(ValidateCFG, MultipleFallThroughToDefault) {
@@ -1990,7 +1999,7 @@
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("Multiple case constructs have branches to the case construct "
-                "that targets 10[%10]\n  %10 = OpLabel"));
+                "that targets '10[%10]'\n  %10 = OpLabel"));
 }
 
 TEST_F(ValidateCFG, MultipleFallThroughToNonDefault) {
@@ -2024,7 +2033,7 @@
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("Multiple case constructs have branches to the case construct "
-                "that targets 12[%12]\n  %12 = OpLabel"));
+                "that targets '12[%12]'\n  %12 = OpLabel"));
 }
 
 TEST_F(ValidateCFG, DuplicateTargetWithFallThrough) {
@@ -2085,10 +2094,11 @@
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Case construct that targets 12[%12] has branches to the case "
-                "construct that targets 11[%11], but does not immediately "
-                "precede it in the OpSwitch's target list\n"
-                "  OpSwitch %uint_0 %10 0 %11 1 %12"));
+      HasSubstr(
+          "Case construct that targets '12[%12]' has branches to the case "
+          "construct that targets '11[%11]', but does not immediately "
+          "precede it in the OpSwitch's target list\n"
+          "  OpSwitch %uint_0 %10 0 %11 1 %12"));
 }
 
 TEST_F(ValidateCFG, WrongOperandListThroughDefault) {
@@ -2121,10 +2131,11 @@
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Case construct that targets 12[%12] has branches to the case "
-                "construct that targets 11[%11], but does not immediately "
-                "precede it in the OpSwitch's target list\n"
-                "  OpSwitch %uint_0 %10 0 %11 1 %12"));
+      HasSubstr(
+          "Case construct that targets '12[%12]' has branches to the case "
+          "construct that targets '11[%11]', but does not immediately "
+          "precede it in the OpSwitch's target list\n"
+          "  OpSwitch %uint_0 %10 0 %11 1 %12"));
 }
 
 TEST_F(ValidateCFG, WrongOperandListNotLast) {
@@ -2159,10 +2170,11 @@
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Case construct that targets 12[%12] has branches to the case "
-                "construct that targets 11[%11], but does not immediately "
-                "precede it in the OpSwitch's target list\n"
-                "  OpSwitch %uint_0 %10 0 %11 1 %12 2 %13"));
+      HasSubstr(
+          "Case construct that targets '12[%12]' has branches to the case "
+          "construct that targets '11[%11]', but does not immediately "
+          "precede it in the OpSwitch's target list\n"
+          "  OpSwitch %uint_0 %10 0 %11 1 %12 2 %13"));
 }
 
 TEST_F(ValidateCFG, GoodUnreachableSwitch) {
@@ -2226,11 +2238,12 @@
 
   CompileSuccessfully(text);
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Case construct that targets 8[%8] has invalid branch "
-                        "to block 10[%10] (not another case construct, "
-                        "corresponding merge, outer loop merge or outer loop "
-                        "continue)"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Case construct that targets '8[%8]' has invalid branch "
+                "to block '10[%10]' (not another case construct, "
+                "corresponding merge, outer loop merge or outer loop "
+                "continue)"));
 }
 
 TEST_F(ValidateCFG, GoodCaseExitsToOuterConstructs) {
@@ -2297,8 +2310,8 @@
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Case construct that targets 1[%default] has branches to the "
-                "case construct that targets 2[%other], but does not "
+      HasSubstr("Case construct that targets '1[%default]' has branches to the "
+                "case construct that targets '2[%other]', but does not "
                 "immediately precede it in the OpSwitch's target list"));
 }
 
@@ -2330,8 +2343,8 @@
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Case construct that targets 2[%other] has branches to the "
-                "case construct that targets 1[%default], but does not "
+      HasSubstr("Case construct that targets '2[%other]' has branches to the "
+                "case construct that targets '1[%default]', but does not "
                 "immediately precede it in the OpSwitch's target list"));
 }
 
@@ -2800,7 +2813,7 @@
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Back-edges (10[%10] -> 9[%9]) can only be formed "
+              HasSubstr("Back-edges ('10[%10]' -> '9[%9]') can only be formed "
                         "between a block and a loop header"));
 }
 
@@ -2826,7 +2839,7 @@
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Merge Block 1[%undef] must be an OpLabel"));
+              HasSubstr("Merge Block '1[%undef]' must be an OpLabel"));
 }
 
 TEST_F(ValidateCFG, LoopMergeContinueTargetNotLabel) {
@@ -2851,7 +2864,7 @@
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Continue Target 1[%undef] must be an OpLabel"));
+              HasSubstr("Continue Target '1[%undef]' must be an OpLabel"));
 }
 
 TEST_F(ValidateCFG, LoopMergeMergeBlockContinueTargetSameLabel) {
@@ -3095,9 +3108,10 @@
 
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("block <ID> 10[%10] exits the selection headed by <ID> "
-                        "8[%8], but not via a structured exit"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("block <ID> '10[%10]' exits the selection headed by <ID> "
+                "'8[%8]', but not via a structured exit"));
 }
 
 TEST_F(ValidateCFG, InvalidLoopExit) {
@@ -3131,8 +3145,8 @@
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("block <ID> 11[%11] exits the loop headed by <ID> "
-                        "8[%8], but not via a structured exit"));
+              HasSubstr("block <ID> '11[%11]' exits the loop headed by <ID> "
+                        "'8[%8]', but not via a structured exit"));
 }
 
 TEST_F(ValidateCFG, InvalidContinueExit) {
@@ -3165,9 +3179,10 @@
 
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("block <ID> 11[%11] exits the continue headed by <ID> "
-                        "10[%10], but not via a structured exit"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("block <ID> '11[%11]' exits the continue headed by <ID> "
+                "'10[%10]', but not via a structured exit"));
 }
 
 TEST_F(ValidateCFG, InvalidSelectionExitBackedge) {
@@ -3205,8 +3220,9 @@
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("The continue construct with the continue target 9[%9] is not "
-                "structurally post dominated by the back-edge block 13[%13]"));
+      HasSubstr(
+          "The continue construct with the continue target '9[%9]' is not "
+          "structurally post dominated by the back-edge block '13[%13]'"));
 }
 
 TEST_F(ValidateCFG, BreakFromSwitch) {
@@ -3269,9 +3285,10 @@
 
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("block <ID> 12[%12] exits the selection headed by <ID> "
-                        "10[%10], but not via a structured exit"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("block <ID> '12[%12]' exits the selection headed by <ID> "
+                "'10[%10]', but not via a structured exit"));
 }
 
 TEST_F(ValidateCFG, BreakToOuterSwitch) {
@@ -3308,9 +3325,10 @@
 
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("block <ID> 14[%14] exits the selection headed by <ID> "
-                        "10[%10], but not via a structured exit"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("block <ID> '14[%14]' exits the selection headed by <ID> "
+                "'10[%10]', but not via a structured exit"));
 }
 
 TEST_F(ValidateCFG, BreakToOuterLoop) {
@@ -3352,8 +3370,8 @@
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("block <ID> 15[%15] exits the loop headed by <ID> "
-                        "10[%10], but not via a structured exit"));
+              HasSubstr("block <ID> '15[%15]' exits the loop headed by <ID> "
+                        "'10[%10]', but not via a structured exit"));
 }
 
 TEST_F(ValidateCFG, ContinueFromNestedSelection) {
@@ -3800,9 +3818,9 @@
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
-          "Header block 3[%body] is contained in the loop construct headed by "
-          "1[%loop], but its merge block 2[%continue] is not"));
+      HasSubstr("Header block '3[%body]' is contained in the loop construct "
+                "headed by "
+                "'1[%loop]', but its merge block '2[%continue]' is not"));
 }
 
 TEST_F(ValidateCFG, ContinueCannotBeLoopMergeTarget) {
@@ -3837,9 +3855,9 @@
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
-          "Header block 3[%inner] is contained in the loop construct headed by "
-          "1[%loop], but its merge block 2[%continue] is not"));
+      HasSubstr("Header block '3[%inner]' is contained in the loop construct "
+                "headed by "
+                "'1[%loop]', but its merge block '2[%continue]' is not"));
 }
 
 TEST_F(ValidateCFG, ExitFromConstructWhoseHeaderIsAMerge) {
@@ -4214,11 +4232,10 @@
 
   CompileSuccessfully(text);
   EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "The selection construct with the selection header "
-          "8[%8] does not structurally dominate the merge block 10[%10]\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("The selection construct with the selection header "
+                        "'8[%8]' does not structurally dominate the merge "
+                        "block '10[%10]'\n"));
 }
 
 TEST_F(ValidateCFG, UnreachableIsStaticallyReachable) {
@@ -4386,9 +4403,10 @@
 
   CompileSuccessfully(text);
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("block <ID> 1[%BAD] exits the continue headed by <ID> "
-                        "1[%BAD], but not via a structured exit"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("block <ID> '1[%BAD]' exits the continue headed by <ID> "
+                "'1[%BAD]', but not via a structured exit"));
 }
 
 TEST_F(ValidateCFG, SwitchSelectorNotAnInt) {
@@ -4581,8 +4599,35 @@
   EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("The continue construct with the continue target 7[%7] "
-                "does not structurally dominate the back-edge block 8[%8]"));
+      HasSubstr("The continue construct with the continue target '7[%7]' "
+                "does not structurally dominate the back-edge block '8[%8]'"));
+}
+
+TEST_F(ValidateCFG, BadLoop) {
+  const std::string text = R"(
+OpCapability Shader
+OpMemoryModel Logical Simple
+OpEntryPoint Fragment %2 "           "
+OpExecutionMode %2 OriginUpperLeft
+OpName %49 "loop"
+%void = OpTypeVoid
+%12 = OpTypeFunction %void
+%2 = OpFunction %void None %12
+%33 = OpLabel
+OpBranch %49
+%50 = OpLabel
+OpBranch %49
+%49 = OpLabel
+OpLoopMerge %33 %50 Unroll
+OpBranch %49
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Loop header '2[%loop]' is targeted by 2 back-edge "
+                        "blocks but the standard requires exactly one"));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/val/val_composites_test.cpp b/third_party/SPIRV-Tools/test/val/val_composites_test.cpp
index 507ee88..0fd1ed6 100644
--- a/third_party/SPIRV-Tools/test/val/val_composites_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_composites_test.cpp
@@ -322,8 +322,9 @@
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 5[%float] cannot be a "
-                                               "type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Operand '5[%float]' cannot be a "
+                        "type"));
 }
 
 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent2) {
@@ -540,7 +541,7 @@
   CompileSuccessfully(GenerateShaderCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ID 19[%float_0] is not a type id"));
+              HasSubstr("ID '19[%float_0]' is not a type id"));
 }
 
 TEST_F(ValidateComposites, CopyObjectWrongOperandType) {
@@ -660,7 +661,7 @@
 
   CompileSuccessfully(GenerateShaderCode(body));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 11[%v4float] cannot "
+  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '11[%v4float]' cannot "
                                                "be a type"));
 }
 
diff --git a/third_party/SPIRV-Tools/test/val/val_conversion_test.cpp b/third_party/SPIRV-Tools/test/val/val_conversion_test.cpp
index f6f37b3..1f8c426 100644
--- a/third_party/SPIRV-Tools/test/val/val_conversion_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_conversion_test.cpp
@@ -813,8 +813,9 @@
 
   CompileSuccessfully(GenerateKernelCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 4[%float] cannot be a "
-                                               "type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Operand '4[%float]' cannot be a "
+                        "type"));
 }
 
 TEST_F(ValidateConversion, PtrCastToGenericWrongInputStorageClass) {
@@ -1258,8 +1259,9 @@
 
   CompileSuccessfully(GenerateKernelCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 4[%float] cannot be a "
-                                               "type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Operand '4[%float]' cannot be a "
+                        "type"));
 }
 
 TEST_F(ValidateConversion, BitcastWrongResultType) {
@@ -1458,7 +1460,7 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 1[%uint] cannot be a "
+  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '1[%uint]' cannot be a "
                                                "type"));
 }
 
diff --git a/third_party/SPIRV-Tools/test/val/val_data_test.cpp b/third_party/SPIRV-Tools/test/val/val_data_test.cpp
index eef08a1..6a7f243 100644
--- a/third_party/SPIRV-Tools/test/val/val_data_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_data_test.cpp
@@ -387,7 +387,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 3[%3] requires a previous definition"));
+              HasSubstr("Operand '3[%3]' requires a previous definition"));
 }
 
 TEST_F(ValidateData, matrix_bad_column_type) {
@@ -549,7 +549,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 3[%3] requires a previous definition"));
+              HasSubstr("Operand '3[%3]' requires a previous definition"));
 }
 
 TEST_F(ValidateData, missing_forward_pointer_decl_self_reference) {
@@ -561,7 +561,7 @@
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Operand 2[%_struct_2] requires a previous definition"));
+      HasSubstr("Operand '2[%_struct_2]' requires a previous definition"));
 }
 
 TEST_F(ValidateData, forward_pointer_missing_definition) {
@@ -824,7 +824,7 @@
   CompileSuccessfully(test, SPV_ENV_UNIVERSAL_1_5);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 3[%_ptr_PhysicalStorageBuffer__struct_1] "
+              HasSubstr("Operand '3[%_ptr_PhysicalStorageBuffer__struct_1]' "
                         "requires a previous definition"));
 }
 
diff --git a/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp b/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp
index 77526bf..dae6c26 100644
--- a/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp
@@ -62,9 +62,10 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
   // Must have 2 decorations.
-  EXPECT_THAT(vstate_->id_decorations(id),
-              Eq(std::set<Decoration>{Decoration(SpvDecorationLocation, {4}),
-                                      Decoration(SpvDecorationCentroid)}));
+  EXPECT_THAT(
+      vstate_->id_decorations(id),
+      Eq(std::set<Decoration>{Decoration(spv::Decoration::Location, {4}),
+                              Decoration(spv::Decoration::Centroid)}));
 }
 
 TEST_F(ValidateDecorations, ValidateOpMemberDecorateRegistration) {
@@ -89,15 +90,15 @@
   const uint32_t arr_id = 1;
   EXPECT_THAT(
       vstate_->id_decorations(arr_id),
-      Eq(std::set<Decoration>{Decoration(SpvDecorationArrayStride, {4})}));
+      Eq(std::set<Decoration>{Decoration(spv::Decoration::ArrayStride, {4})}));
 
   // The struct must have 3 decorations.
   const uint32_t struct_id = 2;
   EXPECT_THAT(
       vstate_->id_decorations(struct_id),
-      Eq(std::set<Decoration>{Decoration(SpvDecorationNonReadable, {}, 2),
-                              Decoration(SpvDecorationOffset, {2}, 2),
-                              Decoration(SpvDecorationBufferBlock)}));
+      Eq(std::set<Decoration>{Decoration(spv::Decoration::NonReadable, {}, 2),
+                              Decoration(spv::Decoration::Offset, {2}, 2),
+                              Decoration(spv::Decoration::BufferBlock)}));
 }
 
 TEST_F(ValidateDecorations, ValidateOpMemberDecorateOutOfBound) {
@@ -120,7 +121,7 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Index 1 provided in OpMemberDecorate for struct <id> "
-                        "2[%_struct_2] is out of bounds. The structure has 1 "
+                        "'2[%_struct_2]' is out of bounds. The structure has 1 "
                         "members. Largest valid index is 0."));
 }
 
@@ -152,9 +153,9 @@
 
   // Decoration group has 3 decorations.
   auto expected_decorations =
-      std::set<Decoration>{Decoration(SpvDecorationDescriptorSet, {0}),
-                           Decoration(SpvDecorationRelaxedPrecision),
-                           Decoration(SpvDecorationRestrict)};
+      std::set<Decoration>{Decoration(spv::Decoration::DescriptorSet, {0}),
+                           Decoration(spv::Decoration::RelaxedPrecision),
+                           Decoration(spv::Decoration::Restrict)};
 
   // Decoration group is applied to id 1, 2, 3, and 4. Note that id 1 (which is
   // the decoration group id) also has all the decorations.
@@ -182,7 +183,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
   // Decoration group has 1 decoration.
   auto expected_decorations =
-      std::set<Decoration>{Decoration(SpvDecorationOffset, {3}, 3)};
+      std::set<Decoration>{Decoration(spv::Decoration::Offset, {3}, 3)};
 
   // Decoration group is applied to id 2, 3, and 4.
   EXPECT_THAT(vstate_->id_decorations(2), Eq(expected_decorations));
@@ -280,12 +281,13 @@
   )";
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Structure <id> 1[%_struct_1] contains members with "
-                        "BuiltIn decoration. Therefore this structure may not "
-                        "be contained as a member of another structure type. "
-                        "Structure <id> 4[%_struct_4] contains structure <id> "
-                        "1[%_struct_1]."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Structure <id> '1[%_struct_1]' contains members with "
+                "BuiltIn decoration. Therefore this structure may not "
+                "be contained as a member of another structure type. "
+                "Structure <id> '4[%_struct_4]' contains structure <id> "
+                "'1[%_struct_1]'."));
 }
 
 TEST_F(ValidateDecorations, StructContainsNonBuiltInStructGood) {
@@ -1217,9 +1219,14 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "'GLSLShared' is not valid for the Vulkan execution environment"));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must not use GLSLShared decoration"));
+              HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
 }
 
 TEST_F(ValidateDecorations, BufferBlockGLSLSharedBad) {
@@ -1246,9 +1253,14 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "'GLSLShared' is not valid for the Vulkan execution environment"));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must not use GLSLShared decoration"));
+              HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
 }
 
 TEST_F(ValidateDecorations, BlockNestedStructGLSLSharedBad) {
@@ -1281,9 +1293,14 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "'GLSLShared' is not valid for the Vulkan execution environment"));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must not use GLSLShared decoration"));
+              HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
 }
 
 TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLSharedBad) {
@@ -1316,9 +1333,14 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "'GLSLShared' is not valid for the Vulkan execution environment"));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must not use GLSLShared decoration"));
+              HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
 }
 
 TEST_F(ValidateDecorations, BlockGLSLPackedBad) {
@@ -1345,9 +1367,14 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "'GLSLPacked' is not valid for the Vulkan execution environment"));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must not use GLSLPacked decoration"));
+              HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
 }
 
 TEST_F(ValidateDecorations, BufferBlockGLSLPackedBad) {
@@ -1374,9 +1401,14 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "'GLSLPacked' is not valid for the Vulkan execution environment"));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must not use GLSLPacked decoration"));
+              HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
 }
 
 TEST_F(ValidateDecorations, BlockNestedStructGLSLPackedBad) {
@@ -1409,9 +1441,14 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "'GLSLPacked' is not valid for the Vulkan execution environment"));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must not use GLSLPacked decoration"));
+              HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
 }
 
 TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLPackedBad) {
@@ -1444,9 +1481,14 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "'GLSLPacked' is not valid for the Vulkan execution environment"));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("must not use GLSLPacked decoration"));
+              HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
 }
 
 TEST_F(ValidateDecorations, BlockMissingArrayStrideBad) {
@@ -1847,7 +1889,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_SUCCESS,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
 }
 
 TEST_F(ValidateDecorations, BlockLayoutPermitsTightVec3ScalarPackingGood) {
@@ -1876,7 +1919,7 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
+  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
       << getDiagnosticString();
 }
 
@@ -2058,7 +2101,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("Structure id 2 decorated as Block for variable in Uniform "
@@ -2466,7 +2510,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_SUCCESS,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
 }
 
 TEST_F(ValidateDecorations, BlockArrayExtendedAlignmentGood) {
@@ -2530,7 +2575,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -2727,7 +2773,7 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
+  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
       << getDiagnosticString();
 }
 
@@ -2759,7 +2805,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -2793,7 +2840,7 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
+  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
       << getDiagnosticString();
 }
 
@@ -2822,7 +2869,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -3162,6 +3210,48 @@
           "statically used per shader entry point."));
 }
 
+TEST_F(ValidateDecorations,
+       VulkanMultiplePushConstantsSingleEntryPointInterfaceBad) {
+  std::string spirv = R"(
+            OpCapability Shader
+            OpMemoryModel Logical GLSL450
+            OpEntryPoint Vertex %func1 "func1" %pc1 %pc2
+            OpDecorate %struct Block
+            OpMemberDecorate %struct 0 Offset 0
+    %void = OpTypeVoid
+  %voidfn = OpTypeFunction %void
+   %float = OpTypeFloat 32
+     %int = OpTypeInt 32 0
+   %int_0 = OpConstant %int 0
+  %struct = OpTypeStruct %float
+     %ptr = OpTypePointer PushConstant %struct
+%ptr_float = OpTypePointer PushConstant %float
+     %pc1 = OpVariable %ptr PushConstant
+     %pc2 = OpVariable %ptr PushConstant
+   %func1 = OpFunction %void None %voidfn
+  %label1 = OpLabel
+ %access1 = OpAccessChain %ptr_float %pc1 %int_0
+   %load1 = OpLoad %float %access1
+            OpReturn
+            OpFunctionEnd
+   %func2 = OpFunction %void None %voidfn
+  %label2 = OpLabel
+ %access2 = OpAccessChain %ptr_float %pc2 %int_0
+   %load2 = OpLoad %float %access2
+            OpReturn
+            OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-OpVariable-06673"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Entry-point has more than one variable with the "
+                        "PushConstant storage class in the interface"));
+}
+
 TEST_F(ValidateDecorations, VulkanUniformMissingDescriptorSetBad) {
   std::string spirv = R"(
             OpCapability Shader
@@ -3674,7 +3764,7 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
+  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
       << getDiagnosticString();
 }
 
@@ -3709,7 +3799,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -3776,7 +3867,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_SUCCESS,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
 }
 
 TEST_F(ValidateDecorations,
@@ -3807,7 +3899,7 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
+  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
       << getDiagnosticString();
 }
 
@@ -3839,7 +3931,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -3907,7 +4000,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("Structure id 6 decorated as Block for variable in Uniform "
@@ -3974,7 +4068,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("Structure id 8 decorated as Block for variable in Uniform "
@@ -4040,7 +4135,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -4076,7 +4172,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("Structure id 3 decorated as BufferBlock for variable in "
@@ -4115,7 +4212,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -4131,6 +4229,7 @@
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %1 "main"
+               OpExecutionMode %1 LocalSize 1 1 1
                OpMemberDecorate %_struct_6 0 Offset 0
                OpMemberDecorate %_struct_2 0 Offset 0
                OpMemberDecorate %_struct_2 1 Offset 4
@@ -4149,7 +4248,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -4274,7 +4374,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -4404,7 +4505,7 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
+  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
       << getDiagnosticString();
 }
 
@@ -4448,7 +4549,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -4495,7 +4597,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_SUCCESS,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
 }
 
 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackBad) {
@@ -4529,7 +4632,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Structure id 4 decorated as BufferBlock for variable "
                         "in Uniform storage class must follow standard storage "
@@ -4569,7 +4673,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_SUCCESS,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
 }
 
 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackBad) {
@@ -4603,7 +4708,8 @@
   )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -4687,7 +4793,7 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Coherent decoration targeting 1[%1] is "
+              HasSubstr("Coherent decoration targeting '1[%1]' is "
                         "banned when using the Vulkan memory model."));
 }
 
@@ -4707,8 +4813,9 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Coherent decoration targeting 1[%_struct_1] (member index 0) "
-                "is banned when using the Vulkan memory model."));
+      HasSubstr(
+          "Coherent decoration targeting '1[%_struct_1]' (member index 0) "
+          "is banned when using the Vulkan memory model."));
 }
 
 TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatile) {
@@ -4728,7 +4835,7 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Volatile decoration targeting 1[%1] is banned when "
+              HasSubstr("Volatile decoration targeting '1[%1]' is banned when "
                         "using the Vulkan memory model."));
 }
 
@@ -4747,7 +4854,7 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Volatile decoration targeting 1[%_struct_1] (member "
+              HasSubstr("Volatile decoration targeting '1[%_struct_1]' (member "
                         "index 1) is banned when using the Vulkan memory "
                         "model."));
 }
@@ -5140,8 +5247,10 @@
 TEST_F(ValidateDecorations, RecurseThroughRuntimeArray) {
   const std::string spirv = R"(
 OpCapability Shader
-OpCapability Linkage
+OpExtension "SPV_KHR_storage_buffer_storage_class"
 OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
 OpDecorate %outer Block
 OpMemberDecorate %inner 0 Offset 0
 OpMemberDecorate %inner 1 Offset 1
@@ -5151,17 +5260,24 @@
 %inner = OpTypeStruct %int %int
 %runtime = OpTypeRuntimeArray %inner
 %outer = OpTypeStruct %runtime
-%outer_ptr = OpTypePointer Uniform %outer
-%var = OpVariable %outer_ptr Uniform
+%outer_ptr = OpTypePointer StorageBuffer %outer
+%var = OpVariable %outer_ptr StorageBuffer
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
 )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Structure id 2 decorated as Block for variable in Uniform "
-                "storage class must follow standard uniform buffer layout "
-                "rules: member 1 at offset 1 is not aligned to 4"));
+      HasSubstr(
+          "Structure id 3 decorated as Block for variable in StorageBuffer "
+          "storage class must follow standard storage buffer layout "
+          "rules: member 1 at offset 1 is not aligned to 4"));
 }
 
 TEST_F(ValidateDecorations, EmptyStructAtNonZeroOffsetGood) {
@@ -6883,6 +6999,8 @@
   CompileSuccessfully(spirv, env);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-04924"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Component decoration specified for type"));
   EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a scalar or vector"));
 }
@@ -6891,6 +7009,7 @@
                                           const std::string& decoration) {
   return R"(
 OpCapability Shader
+OpCapability Int64
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %main "main" %entryPointOutput
 OpExecutionMode %main OriginUpperLeft
@@ -6903,6 +7022,9 @@
 %v3float = OpTypeVector %float 3
 %v4float = OpTypeVector %float 4
 %uint = OpTypeInt 32 0
+%uint64 = OpTypeInt 64 0
+%v2uint64 = OpTypeVector %uint64 2
+%v3uint64 = OpTypeVector %uint64 3
 %uint_2 = OpConstant %uint 2
 %arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
 %float_0 = OpConstant %float 0
@@ -6958,8 +7080,10 @@
   CompileSuccessfully(spirv, env);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Sequence of components starting with 4 "
-                        "and ending with 4 gets larger than 3"));
+              AnyVUID("VUID-StandaloneSpirv-Component-04920"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Component decoration value must not be greater than 3"));
 }
 
 TEST_F(ValidateDecorations, ComponentDecorationVector3GoodVulkan) {
@@ -6987,6 +7111,8 @@
   CompileSuccessfully(spirv, env);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-04921"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Sequence of components starting with 1 "
                         "and ending with 4 gets larger than 3"));
 }
@@ -6998,6 +7124,8 @@
   CompileSuccessfully(spirv, env);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-04921"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Sequence of components starting with 3 "
                         "and ending with 6 gets larger than 3"));
 }
@@ -7020,10 +7148,101 @@
   CompileSuccessfully(spirv, env);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-04921"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Sequence of components starting with 2 "
                         "and ending with 4 gets larger than 3"));
 }
 
+TEST_F(ValidateDecorations, ComponentDecoration64ScalarGoodVulkan) {
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  std::string spirv = ShaderWithComponentDecoration("uint64", "Component 0");
+
+  CompileSuccessfully(spirv, env);
+  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
+}
+
+TEST_F(ValidateDecorations, ComponentDecoration64Scalar1BadVulkan) {
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  std::string spirv = ShaderWithComponentDecoration("uint64", "Component 1");
+
+  CompileSuccessfully(spirv, env);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-04923"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Component decoration value must not be 1 or 3 for "
+                        "64-bit data types"));
+}
+
+TEST_F(ValidateDecorations, ComponentDecoration64Scalar2GoodVulkan) {
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  std::string spirv = ShaderWithComponentDecoration("uint64", "Component 2");
+
+  CompileSuccessfully(spirv, env);
+  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
+}
+
+TEST_F(ValidateDecorations, ComponentDecoration64Scalar3BadVulkan) {
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  std::string spirv = ShaderWithComponentDecoration("uint64", "Component 3");
+
+  CompileSuccessfully(spirv, env);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-04923"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Component decoration value must not be 1 or 3 for "
+                        "64-bit data types"));
+}
+
+TEST_F(ValidateDecorations, ComponentDecoration64Vec0GoodVulkan) {
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  std::string spirv = ShaderWithComponentDecoration("v2uint64", "Component 0");
+
+  CompileSuccessfully(spirv, env);
+  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
+}
+
+TEST_F(ValidateDecorations, ComponentDecoration64Vec1BadVulkan) {
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  std::string spirv = ShaderWithComponentDecoration("v2uint64", "Component 1");
+
+  CompileSuccessfully(spirv, env);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-04923"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Component decoration value must not be 1 or 3 for "
+                        "64-bit data types"));
+}
+
+TEST_F(ValidateDecorations, ComponentDecoration64Vec2BadVulkan) {
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  std::string spirv = ShaderWithComponentDecoration("v2uint64", "Component 2");
+
+  CompileSuccessfully(spirv, env);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-04922"));
+  HasSubstr(
+      "Sequence of components starting with 2 "
+      "and ending with 6 gets larger than 3");
+}
+
+TEST_F(ValidateDecorations, ComponentDecoration64VecWideBadVulkan) {
+  const spv_target_env env = SPV_ENV_VULKAN_1_0;
+  std::string spirv = ShaderWithComponentDecoration("v3uint64", "Component 0");
+
+  CompileSuccessfully(spirv, env);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-07703"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Component decoration only allowed on 64-bit scalar "
+                        "and 2-component vector"));
+}
+
 TEST_F(ValidateDecorations, ComponentDecorationBlockGood) {
   std::string spirv = R"(
 OpCapability Shader
@@ -7095,6 +7314,8 @@
   CompileSuccessfully(spirv, env);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
   EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Component-04921"));
+  EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Sequence of components starting with 2 "
                         "and ending with 4 gets larger than 3"));
 }
@@ -7970,7 +8191,7 @@
 
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_ERROR_INVALID_ID,
-            ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("Block must be explicitly laid out with Offset decorations"));
@@ -8005,13 +8226,12 @@
 
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_ERROR_INVALID_ID,
-            ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
-          "Block for variable in Workgroup storage class must follow "
-          "standard storage buffer layout rules: "
-          "member 0 at offset 1 is not aligned to 4"));
+      HasSubstr("Block for variable in Workgroup storage class must follow "
+                "relaxed storage buffer layout rules: "
+                "member 0 at offset 1 is not aligned to 4"));
 }
 
 TEST_F(ValidateDecorations, BadMatrixStrideUniform) {
@@ -8041,7 +8261,7 @@
 )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -8078,7 +8298,7 @@
 )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -8097,8 +8317,6 @@
 OpMemberDecorate %block 0 Offset 0
 OpMemberDecorate %block 0 MatrixStride 3
 OpMemberDecorate %block 0 ColMajor
-OpDecorate %var DescriptorSet 0
-OpDecorate %var Binding 0
 %void = OpTypeVoid
 %float = OpTypeFloat 32
 %float4 = OpTypeVector %float 4
@@ -8114,7 +8332,7 @@
 )";
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -8152,7 +8370,7 @@
 
   options_->scalar_block_layout = true;
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
@@ -8651,9 +8869,8 @@
               AnyVUID("VUID-StandaloneSpirv-Flat-06201"));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
-          "OpEntryPoint interfaces variable must not be fragment execution "
-          "model with an output storage class for Entry Point id 2."));
+      HasSubstr("decorated variable must not be used in fragment execution "
+                "model as an Output storage class for Entry Point id 2."));
 }
 
 TEST_P(ValidateDecorationString, VulkanVertexInputInvalidInterface) {
@@ -8691,8 +8908,8 @@
               AnyVUID("VUID-StandaloneSpirv-Flat-06202"));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("OpEntryPoint interfaces variable must not be vertex execution "
-                "model with an input storage class for Entry Point id 2."));
+      HasSubstr("decorated variable must not be used in vertex execution model "
+                "as an Input storage class for Entry Point id 2."));
 }
 
 INSTANTIATE_TEST_SUITE_P(FragmentInputInterface, ValidateDecorationString,
diff --git a/third_party/SPIRV-Tools/test/val/val_derivatives_test.cpp b/third_party/SPIRV-Tools/test/val/val_derivatives_test.cpp
index 0a84661..e605f3a 100644
--- a/third_party/SPIRV-Tools/test/val/val_derivatives_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_derivatives_test.cpp
@@ -130,7 +130,7 @@
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 10[%v4float] cannot "
+  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '10[%v4float]' cannot "
                                                "be a type"));
 }
 
diff --git a/third_party/SPIRV-Tools/test/val/val_entry_point.cpp b/third_party/SPIRV-Tools/test/val/val_entry_point_test.cpp
similarity index 100%
rename from third_party/SPIRV-Tools/test/val/val_entry_point.cpp
rename to third_party/SPIRV-Tools/test/val/val_entry_point_test.cpp
diff --git a/third_party/SPIRV-Tools/test/val/val_ext_inst_test.cpp b/third_party/SPIRV-Tools/test/val/val_ext_inst_test.cpp
index a2109db..e685acd 100644
--- a/third_party/SPIRV-Tools/test/val/val_ext_inst_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_ext_inst_test.cpp
@@ -4321,7 +4321,7 @@
   CompileSuccessfully(GenerateKernelCode(ss.str()));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 89[%_ptr_Workgroup_half] cannot be a type"));
+              HasSubstr("Operand '89[%_ptr_Workgroup_half]' cannot be a type"));
 }
 
 TEST_P(ValidateOpenCLStdVStoreHalfLike, ConstPointer) {
@@ -4493,7 +4493,7 @@
   CompileSuccessfully(GenerateKernelCode(ss.str()));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 89[%_ptr_Workgroup_half] cannot be a type"));
+              HasSubstr("Operand '89[%_ptr_Workgroup_half]' cannot be a type"));
 }
 
 TEST_P(ValidateOpenCLStdVLoadHalfLike, OffsetWrongStorageType) {
@@ -4664,9 +4664,10 @@
 
   CompileSuccessfully(GenerateKernelCode(ss.str()));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 120[%_ptr_UniformConstant_float] cannot be a "
-                        "type"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Operand '120[%_ptr_UniformConstant_float]' cannot be a "
+                "type"));
 }
 
 TEST_F(ValidateExtInst, VLoadNWrongStorageClass) {
@@ -4779,7 +4780,7 @@
   CompileSuccessfully(GenerateKernelCode(ss.str()));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 114[%_ptr_UniformConstant_half] cannot be a "
+              HasSubstr("Operand '114[%_ptr_UniformConstant_half]' cannot be a "
                         "type"));
 }
 
@@ -4933,7 +4934,7 @@
   CompileSuccessfully(GenerateKernelCode(ss.str()));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 127[%_ptr_Generic_float] cannot be a type"));
+              HasSubstr("Operand '127[%_ptr_Generic_float]' cannot be a type"));
 }
 
 TEST_F(ValidateExtInst, VStoreNWrongStorageClass) {
@@ -5248,9 +5249,10 @@
 
   CompileSuccessfully(GenerateKernelCode(body));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 137[%_ptr_UniformConstant_uchar] cannot be a "
-                        "type"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Operand '137[%_ptr_UniformConstant_uchar]' cannot be a "
+                "type"));
 }
 
 TEST_F(ValidateExtInst, OpenCLStdPrintfFormatNotUniformConstStorageClass) {
@@ -5342,7 +5344,7 @@
   CompileSuccessfully(GenerateKernelCode(body));
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 99[%_ptr_CrossWorkgroup_uint] cannot be a "
+              HasSubstr("Operand '99[%_ptr_CrossWorkgroup_uint]' cannot be a "
                         "type"));
 }
 
diff --git a/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_bit_instructions.cpp b/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_bit_instructions_test.cpp
similarity index 100%
rename from third_party/SPIRV-Tools/test/val/val_extension_spv_khr_bit_instructions.cpp
rename to third_party/SPIRV-Tools/test/val/val_extension_spv_khr_bit_instructions_test.cpp
diff --git a/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_expect_assume.cpp b/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_expect_assume_test.cpp
similarity index 100%
rename from third_party/SPIRV-Tools/test/val/val_extension_spv_khr_expect_assume.cpp
rename to third_party/SPIRV-Tools/test/val/val_extension_spv_khr_expect_assume_test.cpp
diff --git a/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_integer_dot_product.cpp b/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_integer_dot_product_test.cpp
similarity index 100%
rename from third_party/SPIRV-Tools/test/val/val_extension_spv_khr_integer_dot_product.cpp
rename to third_party/SPIRV-Tools/test/val/val_extension_spv_khr_integer_dot_product_test.cpp
diff --git a/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_linkonce_odr.cpp b/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_linkonce_odr_test.cpp
similarity index 100%
rename from third_party/SPIRV-Tools/test/val/val_extension_spv_khr_linkonce_odr.cpp
rename to third_party/SPIRV-Tools/test/val/val_extension_spv_khr_linkonce_odr_test.cpp
diff --git a/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_subgroup_rotate.cpp b/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_subgroup_rotate_test.cpp
similarity index 100%
rename from third_party/SPIRV-Tools/test/val/val_extension_spv_khr_subgroup_rotate.cpp
rename to third_party/SPIRV-Tools/test/val/val_extension_spv_khr_subgroup_rotate_test.cpp
diff --git a/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_subgroup_uniform_control_flow.cpp b/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_subgroup_uniform_control_flow_test.cpp
similarity index 100%
rename from third_party/SPIRV-Tools/test/val/val_extension_spv_khr_subgroup_uniform_control_flow.cpp
rename to third_party/SPIRV-Tools/test/val/val_extension_spv_khr_subgroup_uniform_control_flow_test.cpp
diff --git a/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_terminate_invocation.cpp b/third_party/SPIRV-Tools/test/val/val_extension_spv_khr_terminate_invocation_test.cpp
similarity index 100%
rename from third_party/SPIRV-Tools/test/val/val_extension_spv_khr_terminate_invocation.cpp
rename to third_party/SPIRV-Tools/test/val/val_extension_spv_khr_terminate_invocation_test.cpp
diff --git a/third_party/SPIRV-Tools/test/val/val_function_test.cpp b/third_party/SPIRV-Tools/test/val/val_function_test.cpp
index af0199a..e7d5cd7 100644
--- a/third_party/SPIRV-Tools/test/val/val_function_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_function_test.cpp
@@ -181,13 +181,14 @@
   } else {
     EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
     if (storage_class == "StorageBuffer") {
-      EXPECT_THAT(getDiagnosticString(),
-                  HasSubstr("StorageBuffer pointer operand 1[%var] requires a "
-                            "variable pointers capability"));
+      EXPECT_THAT(
+          getDiagnosticString(),
+          HasSubstr("StorageBuffer pointer operand '1[%var]' requires a "
+                    "variable pointers capability"));
     } else {
       EXPECT_THAT(
           getDiagnosticString(),
-          HasSubstr("Invalid storage class for pointer operand 1[%var]"));
+          HasSubstr("Invalid storage class for pointer operand '1[%var]'"));
     }
   }
 }
@@ -211,8 +212,9 @@
     EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
   } else {
     EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-    EXPECT_THAT(getDiagnosticString(),
-                HasSubstr("Invalid storage class for pointer operand 1[%var]"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr("Invalid storage class for pointer operand '1[%var]'"));
   }
 }
 
@@ -235,8 +237,9 @@
     EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
   } else {
     EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-    EXPECT_THAT(getDiagnosticString(),
-                HasSubstr("Invalid storage class for pointer operand 1[%var]"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr("Invalid storage class for pointer operand '1[%var]'"));
   }
 }
 
@@ -258,11 +261,12 @@
     EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
     if (storage_class == "StorageBuffer") {
       EXPECT_THAT(getDiagnosticString(),
-                  HasSubstr("StorageBuffer pointer operand 1[%p] requires a "
+                  HasSubstr("StorageBuffer pointer operand '1[%p]' requires a "
                             "variable pointers capability"));
     } else {
-      EXPECT_THAT(getDiagnosticString(),
-                  HasSubstr("Invalid storage class for pointer operand 1[%p]"));
+      EXPECT_THAT(
+          getDiagnosticString(),
+          HasSubstr("Invalid storage class for pointer operand '1[%p]'"));
     }
   }
 }
@@ -287,7 +291,7 @@
   } else {
     EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
-                HasSubstr("Invalid storage class for pointer operand 1[%p]"));
+                HasSubstr("Invalid storage class for pointer operand '1[%p]'"));
   }
 }
 
@@ -311,7 +315,7 @@
   } else {
     EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
-                HasSubstr("Invalid storage class for pointer operand 1[%p]"));
+                HasSubstr("Invalid storage class for pointer operand '1[%p]'"));
   }
 }
 
@@ -334,16 +338,17 @@
     EXPECT_THAT(
         getDiagnosticString(),
         HasSubstr(
-            "Pointer operand 2[%gep] must be a memory object declaration"));
+            "Pointer operand '2[%gep]' must be a memory object declaration"));
   } else {
     if (storage_class == "StorageBuffer") {
-      EXPECT_THAT(getDiagnosticString(),
-                  HasSubstr("StorageBuffer pointer operand 2[%gep] requires a "
-                            "variable pointers capability"));
+      EXPECT_THAT(
+          getDiagnosticString(),
+          HasSubstr("StorageBuffer pointer operand '2[%gep]' requires a "
+                    "variable pointers capability"));
     } else if (storage_class != "UniformConstant") {
       EXPECT_THAT(
           getDiagnosticString(),
-          HasSubstr("Invalid storage class for pointer operand 2[%gep]"));
+          HasSubstr("Invalid storage class for pointer operand '2[%gep]'"));
     }
   }
 }
@@ -373,11 +378,11 @@
       EXPECT_THAT(
           getDiagnosticString(),
           HasSubstr(
-              "Pointer operand 2[%gep] must be a memory object declaration"));
+              "Pointer operand '2[%gep]' must be a memory object declaration"));
     } else {
       EXPECT_THAT(
           getDiagnosticString(),
-          HasSubstr("Invalid storage class for pointer operand 2[%gep]"));
+          HasSubstr("Invalid storage class for pointer operand '2[%gep]'"));
     }
   }
 }
@@ -407,11 +412,11 @@
       EXPECT_THAT(
           getDiagnosticString(),
           HasSubstr(
-              "Pointer operand 2[%gep] must be a memory object declaration"));
+              "Pointer operand '2[%gep]' must be a memory object declaration"));
     } else {
       EXPECT_THAT(
           getDiagnosticString(),
-          HasSubstr("Invalid storage class for pointer operand 2[%gep]"));
+          HasSubstr("Invalid storage class for pointer operand '2[%gep]'"));
     }
   }
 }
diff --git a/third_party/SPIRV-Tools/test/val/val_id_test.cpp b/third_party/SPIRV-Tools/test/val/val_id_test.cpp
index b7e5042..a457980 100644
--- a/third_party/SPIRV-Tools/test/val/val_id_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_id_test.cpp
@@ -35,7 +35,15 @@
 using ::testing::HasSubstr;
 using ::testing::ValuesIn;
 
-using ValidateIdWithMessage = spvtest::ValidateBase<bool>;
+class ValidateIdWithMessage : public spvtest::ValidateBase<bool> {
+ public:
+  ValidateIdWithMessage() {
+    const bool use_friendly_names = GetParam();
+    spvValidatorOptionsSetFriendlyNames(options_, use_friendly_names);
+  }
+
+  std::string make_message(const char* msg);
+};
 
 std::string kOpCapabilitySetupWithoutVector16 = R"(
      OpCapability Shader
@@ -177,9 +185,61 @@
                OpFunctionEnd
 )";
 
+// Transform an expected validation message to either use friendly names (as
+// provided in the message) or replace the friendly names by the corresponding
+// id.  The same flag used to configure the validator to output friendly names
+// or not is used here.
+std::string ValidateIdWithMessage::make_message(const char* msg) {
+  const bool use_friendly_names = GetParam();
+  if (use_friendly_names) {
+    return msg;
+  }
+
+  std::string message(msg);
+  std::ostringstream result;
+
+  size_t next = 0;
+  while (next < message.size()) {
+    // Parse 'num[%name]'
+    size_t open_quote = message.find('\'', next);
+
+    // Copy up to the first quote
+    result.write(msg + next, open_quote - next);
+    if (open_quote == std::string::npos) {
+      break;
+    }
+    // Handle apostrophes
+    if (!isdigit(message[open_quote + 1])) {
+      result << '\'';
+      next = open_quote + 1;
+      continue;
+    }
+
+    size_t open_bracket = message.find('[', open_quote + 1);
+    assert(open_bracket != std::string::npos);
+
+    size_t close_bracket = message.find(']', open_bracket + 1);
+    assert(close_bracket != std::string::npos);
+
+    size_t close_quote = close_bracket + 1;
+    assert(close_quote < message.size() && message[close_quote] == '\'');
+
+    // Change to 'num[%num]' because friendly names are not being used.
+    result.write(msg + open_quote, open_bracket - open_quote + 1);
+    result << '%';
+    result.write(msg + open_quote + 1, open_bracket - open_quote - 1);
+    result << "]'";
+
+    // Continue to the next id, or end of string.
+    next = close_quote + 1;
+  }
+
+  return result.str();
+}
+
 // TODO: OpUndef
 
-TEST_F(ValidateIdWithMessage, OpName) {
+TEST_P(ValidateIdWithMessage, OpName) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpName %2 "name"
 %1 = OpTypeInt 32 0
@@ -189,7 +249,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpMemberNameGood) {
+TEST_P(ValidateIdWithMessage, OpMemberNameGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberName %2 0 "foo"
 %1 = OpTypeInt 32 0
@@ -197,30 +257,30 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpMemberNameTypeBad) {
+TEST_P(ValidateIdWithMessage, OpMemberNameTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberName %1 0 "foo"
 %1 = OpTypeInt 32 0)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpMemberName Type <id> '1[%uint]' is not a struct type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpMemberName Type <id> '1[%uint]' is not a struct type.")));
 }
-TEST_F(ValidateIdWithMessage, OpMemberNameMemberBad) {
+TEST_P(ValidateIdWithMessage, OpMemberNameMemberBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberName %1 1 "foo"
 %2 = OpTypeInt 32 0
 %1 = OpTypeStruct %2)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpMemberName Member <id> '1[%_struct_1]' index is larger "
-                "than Type <id> '1[%_struct_1]'s member count."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpMemberName Member <id> '1[%_struct_1]' index is larger "
+                  "than Type <id> '1[%_struct_1]'s member count.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpLineGood) {
+TEST_P(ValidateIdWithMessage, OpLineGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpString "/path/to/source.file"
      OpLine %1 0 0
@@ -231,7 +291,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpLineFileBad) {
+TEST_P(ValidateIdWithMessage, OpLineFileBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
   %1 = OpTypeInt 32 0
      OpLine %1 0 0
@@ -239,10 +299,11 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpLine Target <id> '1[%uint]' is not an OpString."));
+              HasSubstr(make_message(
+                  "OpLine Target <id> '1[%uint]' is not an OpString.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpDecorateGood) {
+TEST_P(ValidateIdWithMessage, OpDecorateGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpDecorate %2 GLSLShared
 %1 = OpTypeInt 64 0
@@ -250,16 +311,17 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpDecorateBad) {
+TEST_P(ValidateIdWithMessage, OpDecorateBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 OpDecorate %1 GLSLShared)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("forward referenced IDs have not been defined"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("forward referenced IDs have not been defined")));
 }
 
-TEST_F(ValidateIdWithMessage, OpMemberDecorateGood) {
+TEST_P(ValidateIdWithMessage, OpMemberDecorateGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberDecorate %2 0 RelaxedPrecision
 %1 = OpTypeInt 32 0
@@ -267,17 +329,18 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpMemberDecorateBad) {
+TEST_P(ValidateIdWithMessage, OpMemberDecorateBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberDecorate %1 0 RelaxedPrecision
 %1 = OpTypeInt 32 0)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpMemberDecorate Structure type <id> '1[%uint]' is "
-                        "not a struct type."));
+              HasSubstr(make_message(
+                  "OpMemberDecorate Structure type <id> '1[%uint]' is "
+                  "not a struct type.")));
 }
-TEST_F(ValidateIdWithMessage, OpMemberDecorateMemberBad) {
+TEST_P(ValidateIdWithMessage, OpMemberDecorateMemberBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberDecorate %1 3 RelaxedPrecision
 %int = OpTypeInt 32 0
@@ -285,12 +348,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Index 3 provided in OpMemberDecorate for struct <id> "
-                        "1[%_struct_1] is out of bounds. The structure has 2 "
-                        "members. Largest valid index is 1."));
+              HasSubstr(make_message(
+                  "Index 3 provided in OpMemberDecorate for struct <id> "
+                  "'1[%_struct_1]' is out of bounds. The structure has 2 "
+                  "members. Largest valid index is 1.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpGroupDecorateGood) {
+TEST_P(ValidateIdWithMessage, OpGroupDecorateGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpDecorationGroup
      OpDecorate %1 RelaxedPrecision
@@ -302,7 +366,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpDecorationGroupBad) {
+TEST_P(ValidateIdWithMessage, OpDecorationGroupBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpDecorationGroup
      OpDecorate %1 RelaxedPrecision
@@ -312,11 +376,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Result id of OpDecorationGroup can only "
-                        "be targeted by OpName, OpGroupDecorate, "
-                        "OpDecorate, OpDecorateId, and OpGroupMemberDecorate"));
+              HasSubstr(make_message(
+                  "Result id of OpDecorationGroup can only "
+                  "be targeted by OpName, OpGroupDecorate, "
+                  "OpDecorate, OpDecorateId, and OpGroupMemberDecorate")));
 }
-TEST_F(ValidateIdWithMessage, OpGroupDecorateDecorationGroupBad) {
+TEST_P(ValidateIdWithMessage, OpGroupDecorateDecorationGroupBad) {
   std::string spirv = R"(
     OpCapability Shader
     OpCapability Linkage
@@ -328,10 +393,11 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpGroupDecorate Decoration group <id> '1[%1]' is not "
-                        "a decoration group."));
+              HasSubstr(make_message(
+                  "OpGroupDecorate Decoration group <id> '1[%1]' is not "
+                  "a decoration group.")));
 }
-TEST_F(ValidateIdWithMessage, OpGroupDecorateTargetBad) {
+TEST_P(ValidateIdWithMessage, OpGroupDecorateTargetBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpDecorationGroup
      OpDecorate %1 RelaxedPrecision
@@ -340,10 +406,11 @@
 %2 = OpTypeInt 32 0)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("forward referenced IDs have not been defined"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("forward referenced IDs have not been defined")));
 }
-TEST_F(ValidateIdWithMessage, OpGroupMemberDecorateDecorationGroupBad) {
+TEST_P(ValidateIdWithMessage, OpGroupMemberDecorateDecorationGroupBad) {
   std::string spirv = R"(
     OpCapability Shader
     OpCapability Linkage
@@ -354,10 +421,11 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpGroupMemberDecorate Decoration group <id> '1[%1]' "
-                        "is not a decoration group."));
+              HasSubstr(make_message(
+                  "OpGroupMemberDecorate Decoration group <id> '1[%1]' "
+                  "is not a decoration group.")));
 }
-TEST_F(ValidateIdWithMessage, OpGroupMemberDecorateIdNotStructBad) {
+TEST_P(ValidateIdWithMessage, OpGroupMemberDecorateIdNotStructBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
      %1 = OpDecorationGroup
      OpGroupMemberDecorate %1 %2 0
@@ -365,10 +433,11 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpGroupMemberDecorate Structure type <id> '2[%uint]' "
-                        "is not a struct type."));
+              HasSubstr(make_message(
+                  "OpGroupMemberDecorate Structure type <id> '2[%uint]' "
+                  "is not a struct type.")));
 }
-TEST_F(ValidateIdWithMessage, OpGroupMemberDecorateIndexOutOfBoundBad) {
+TEST_P(ValidateIdWithMessage, OpGroupMemberDecorateIndexOutOfBoundBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
   OpDecorate %1 Offset 0
   %1 = OpDecorationGroup
@@ -379,14 +448,15 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Index 3 provided in OpGroupMemberDecorate for struct "
-                        "<id> 2[%_struct_2] is out of bounds. The structure "
-                        "has 3 members. Largest valid index is 2."));
+              HasSubstr(make_message(
+                  "Index 3 provided in OpGroupMemberDecorate for struct "
+                  "<id> '2[%_struct_2]' is out of bounds. The structure "
+                  "has 3 members. Largest valid index is 2.")));
 }
 
 // TODO: OpExtInst
 
-TEST_F(ValidateIdWithMessage, OpEntryPointGood) {
+TEST_P(ValidateIdWithMessage, OpEntryPointGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpEntryPoint GLCompute %3 ""
 %1 = OpTypeVoid
@@ -399,17 +469,18 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpEntryPointFunctionBad) {
+TEST_P(ValidateIdWithMessage, OpEntryPointFunctionBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpEntryPoint GLCompute %1 ""
 %1 = OpTypeVoid)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpEntryPoint Entry Point <id> '1[%void]' is not a "
-                        "function."));
+              HasSubstr(make_message(
+                  "OpEntryPoint Entry Point <id> '1[%void]' is not a "
+                  "function.")));
 }
-TEST_F(ValidateIdWithMessage, OpEntryPointParameterCountBad) {
+TEST_P(ValidateIdWithMessage, OpEntryPointParameterCountBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpEntryPoint GLCompute %1 ""
 %2 = OpTypeVoid
@@ -420,11 +491,12 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpEntryPoint Entry Point <id> '1[%1]'s function "
-                        "parameter count is not zero"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
+                             "parameter count is not zero")));
 }
-TEST_F(ValidateIdWithMessage, OpEntryPointReturnTypeBad) {
+TEST_P(ValidateIdWithMessage, OpEntryPointReturnTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpEntryPoint GLCompute %1 ""
 %2 = OpTypeInt 32 0
@@ -436,11 +508,12 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpEntryPoint Entry Point <id> '1[%1]'s function "
-                        "return type is not void."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
+                             "return type is not void.")));
 }
-TEST_F(ValidateIdWithMessage, OpEntryPointParameterCountBadInVulkan) {
+TEST_P(ValidateIdWithMessage, OpEntryPointParameterCountBadInVulkan) {
   std::string spirv = R"(
      OpCapability Shader
      OpMemoryModel Logical GLSL450
@@ -455,11 +528,12 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
               AnyVUID("VUID-StandaloneSpirv-None-04633"));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpEntryPoint Entry Point <id> '1[%1]'s function "
-                        "parameter count is not zero"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
+                             "parameter count is not zero")));
 }
-TEST_F(ValidateIdWithMessage, OpEntryPointReturnTypeBadInVulkan) {
+TEST_P(ValidateIdWithMessage, OpEntryPointReturnTypeBadInVulkan) {
   std::string spirv = R"(
      OpCapability Shader
      OpMemoryModel Logical GLSL450
@@ -475,12 +549,13 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
               AnyVUID("VUID-StandaloneSpirv-None-04633"));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpEntryPoint Entry Point <id> '1[%1]'s function "
-                        "return type is not void."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
+                             "return type is not void.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpEntryPointInterfaceIsNotVariableTypeBad) {
+TEST_P(ValidateIdWithMessage, OpEntryPointInterfaceIsNotVariableTypeBad) {
   std::string spirv = R"(
                OpCapability Shader
                OpCapability Geometry
@@ -502,11 +577,12 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Interfaces passed to OpEntryPoint must be of type "
-                        "OpTypeVariable. Found OpTypePointer."));
+              HasSubstr(make_message(
+                  "Interfaces passed to OpEntryPoint must be of type "
+                  "OpTypeVariable. Found OpTypePointer.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpEntryPointInterfaceStorageClassBad) {
+TEST_P(ValidateIdWithMessage, OpEntryPointInterfaceStorageClassBad) {
   std::string spirv = R"(
                OpCapability Shader
                OpCapability Geometry
@@ -529,12 +605,13 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpEntryPoint interfaces must be OpVariables with "
-                        "Storage Class of Input(1) or Output(3). Found Storage "
-                        "Class 2 for Entry Point id 1."));
+              HasSubstr(make_message(
+                  "OpEntryPoint interfaces must be OpVariables with "
+                  "Storage Class of Input(1) or Output(3). Found Storage "
+                  "Class 2 for Entry Point id 1.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpExecutionModeGood) {
+TEST_P(ValidateIdWithMessage, OpExecutionModeGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpEntryPoint GLCompute %3 ""
      OpExecutionMode %3 LocalSize 1 1 1
@@ -548,7 +625,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpExecutionModeEntryPointMissing) {
+TEST_P(ValidateIdWithMessage, OpExecutionModeEntryPointMissing) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpExecutionMode %3 LocalSize 1 1 1
 %1 = OpTypeVoid
@@ -560,11 +637,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpExecutionMode Entry Point <id> '1[%1]' is not the "
-                        "Entry Point operand of an OpEntryPoint."));
+              HasSubstr(make_message(
+                  "OpExecutionMode Entry Point <id> '1[%1]' is not the "
+                  "Entry Point operand of an OpEntryPoint.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpExecutionModeEntryPointBad) {
+TEST_P(ValidateIdWithMessage, OpExecutionModeEntryPointBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpEntryPoint GLCompute %3 "" %a
      OpExecutionMode %a LocalSize 1 1 1
@@ -579,11 +657,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpExecutionMode Entry Point <id> '2[%2]' is not the "
-                        "Entry Point operand of an OpEntryPoint."));
+              HasSubstr(make_message(
+                  "OpExecutionMode Entry Point <id> '2[%2]' is not the "
+                  "Entry Point operand of an OpEntryPoint.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeVectorFloat) {
+TEST_P(ValidateIdWithMessage, OpTypeVectorFloat) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 4)";
@@ -591,7 +670,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeVectorInt) {
+TEST_P(ValidateIdWithMessage, OpTypeVectorInt) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeVector %1 4)";
@@ -599,7 +678,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeVectorUInt) {
+TEST_P(ValidateIdWithMessage, OpTypeVectorUInt) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 64 0
 %2 = OpTypeVector %1 4)";
@@ -607,7 +686,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeVectorBool) {
+TEST_P(ValidateIdWithMessage, OpTypeVectorBool) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeBool
 %2 = OpTypeVector %1 4)";
@@ -615,20 +694,20 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeVectorComponentTypeBad) {
+TEST_P(ValidateIdWithMessage, OpTypeVectorComponentTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypePointer UniformConstant %1
 %3 = OpTypeVector %2 4)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpTypeVector Component Type <id> "
-                "'2[%_ptr_UniformConstant_float]' is not a scalar type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpTypeVector Component Type <id> "
+                  "'2[%_ptr_UniformConstant_float]' is not a scalar type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeVectorColumnCountLessThanTwoBad) {
+TEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountLessThanTwoBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 1)";
@@ -636,11 +715,12 @@
   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Illegal number of components (1) for TypeVector\n  %v1float = "
-                "OpTypeVector %float 1\n"));
+      HasSubstr(make_message(
+          "Illegal number of components (1) for TypeVector\n  %v1float = "
+          "OpTypeVector %float 1\n")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeVectorColumnCountGreaterThanFourBad) {
+TEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountGreaterThanFourBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 5)";
@@ -648,24 +728,25 @@
   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Illegal number of components (5) for TypeVector\n  %v5float = "
-                "OpTypeVector %float 5\n"));
+      HasSubstr(make_message(
+          "Illegal number of components (5) for TypeVector\n  %v5float = "
+          "OpTypeVector %float 5\n")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeVectorColumnCountEightWithoutVector16Bad) {
+TEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountEightWithoutVector16Bad) {
   std::string spirv = kGLSL450MemoryModelWithoutVector16 + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 8)";
 
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Having 8 components for TypeVector requires the Vector16 "
-                "capability\n  %v8float = OpTypeVector %float 8\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "Having 8 components for TypeVector requires the Vector16 "
+                  "capability\n  %v8float = OpTypeVector %float 8\n")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpTypeVectorColumnCountSixteenWithoutVector16Bad) {
   std::string spirv = kGLSL450MemoryModelWithoutVector16 + R"(
 %1 = OpTypeFloat 32
@@ -673,13 +754,13 @@
 
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Having 16 components for TypeVector requires the Vector16 "
-                "capability\n  %v16float = OpTypeVector %float 16\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "Having 16 components for TypeVector requires the Vector16 "
+                  "capability\n  %v16float = OpTypeVector %float 16\n")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeVectorColumnCountOfEightWithVector16Good) {
+TEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountOfEightWithVector16Good) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 8)";
@@ -687,7 +768,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpTypeVectorColumnCountOfSixteenWithVector16Good) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
@@ -696,7 +777,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeMatrixGood) {
+TEST_P(ValidateIdWithMessage, OpTypeMatrixGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 2
@@ -705,32 +786,32 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeMatrixColumnTypeNonVectorBad) {
+TEST_P(ValidateIdWithMessage, OpTypeMatrixColumnTypeNonVectorBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeMatrix %1 3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("olumns in a matrix must be of type vector.\n  %mat3float = "
-                "OpTypeMatrix %float 3\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "olumns in a matrix must be of type vector.\n  %mat3float = "
+                  "OpTypeMatrix %float 3\n")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeMatrixVectorTypeNonFloatBad) {
+TEST_P(ValidateIdWithMessage, OpTypeMatrixVectorTypeNonFloatBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 16 0
 %2 = OpTypeVector %1 2
 %3 = OpTypeMatrix %2 2)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Matrix types can only be parameterized with floating-point "
-                "types.\n  %mat2v2ushort = OpTypeMatrix %v2ushort 2\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "Matrix types can only be parameterized with floating-point "
+                  "types.\n  %mat2v2ushort = OpTypeMatrix %v2ushort 2\n")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeMatrixColumnCountLessThanTwoBad) {
+TEST_P(ValidateIdWithMessage, OpTypeMatrixColumnCountLessThanTwoBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 2
@@ -739,11 +820,12 @@
   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Matrix types can only be parameterized as having only 2, 3, "
-                "or 4 columns.\n  %mat1v2float = OpTypeMatrix %v2float 1\n"));
+      HasSubstr(make_message(
+          "Matrix types can only be parameterized as having only 2, 3, "
+          "or 4 columns.\n  %mat1v2float = OpTypeMatrix %v2float 1\n")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeMatrixColumnCountGreaterThanFourBad) {
+TEST_P(ValidateIdWithMessage, OpTypeMatrixColumnCountGreaterThanFourBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 2
@@ -752,11 +834,12 @@
   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Matrix types can only be parameterized as having only 2, 3, "
-                "or 4 columns.\n  %mat8v2float = OpTypeMatrix %v2float 8\n"));
+      HasSubstr(make_message(
+          "Matrix types can only be parameterized as having only 2, 3, "
+          "or 4 columns.\n  %mat8v2float = OpTypeMatrix %v2float 8\n")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeSamplerGood) {
+TEST_P(ValidateIdWithMessage, OpTypeSamplerGood) {
   // In Rev31, OpTypeSampler takes no arguments.
   std::string spirv = kGLSL450MemoryModel + R"(
 %s = OpTypeSampler)";
@@ -764,7 +847,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeArrayGood) {
+TEST_P(ValidateIdWithMessage, OpTypeArrayGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 1
@@ -773,7 +856,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeArrayElementTypeBad) {
+TEST_P(ValidateIdWithMessage, OpTypeArrayElementTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 1
@@ -781,8 +864,9 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpTypeArray Element Type <id> '2[%uint_1]' is not a "
-                        "type."));
+              HasSubstr(make_message(
+                  "OpTypeArray Element Type <id> '2[%uint_1]' is not a "
+                  "type.")));
 }
 
 // Signed or unsigned.
@@ -962,20 +1046,19 @@
 INSTANTIATE_TEST_SUITE_P(Widths, OpTypeArrayLengthTest,
                          ValuesIn(std::vector<int>{16, 32, 64}));
 
-TEST_F(ValidateIdWithMessage, OpTypeArrayLengthNull) {
+TEST_P(ValidateIdWithMessage, OpTypeArrayLengthNull) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %i32 = OpTypeInt 32 0
 %len = OpConstantNull %i32
 %ary = OpTypeArray %i32 %len)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "OpTypeArray Length <id> '2[%2]' default value must be at least 1."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("OpTypeArray Length <id> '2[%2]' default "
+                                     "value must be at least 1.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeArrayLengthSpecConst) {
+TEST_P(ValidateIdWithMessage, OpTypeArrayLengthSpecConst) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %i32 = OpTypeInt 32 0
 %len = OpSpecConstant %i32 2
@@ -984,7 +1067,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeArrayLengthSpecConstOp) {
+TEST_P(ValidateIdWithMessage, OpTypeArrayLengthSpecConstOp) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %i32 = OpTypeInt 32 0
 %c1 = OpConstant %i32 1
@@ -995,29 +1078,29 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeRuntimeArrayGood) {
+TEST_P(ValidateIdWithMessage, OpTypeRuntimeArrayGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeRuntimeArray %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpTypeRuntimeArrayBad) {
+TEST_P(ValidateIdWithMessage, OpTypeRuntimeArrayBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 0
 %3 = OpTypeRuntimeArray %2)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpTypeRuntimeArray Element Type <id> '2[%uint_0]' is not a "
-                "type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpTypeRuntimeArray Element Type <id> '2[%uint_0]' is not a "
+                  "type.")));
 }
 // TODO: Object of this type can only be created with OpVariable using the
 // Uniform Storage Class
 
-TEST_F(ValidateIdWithMessage, OpTypeStructGood) {
+TEST_P(ValidateIdWithMessage, OpTypeStructGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeFloat 64
@@ -1026,7 +1109,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpTypeStructMemberTypeBad) {
+TEST_P(ValidateIdWithMessage, OpTypeStructMemberTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeFloat 64
@@ -1035,11 +1118,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpTypeStruct Member Type <id> '3[%double_0]' is not "
-                        "a type."));
+              HasSubstr(make_message(
+                  "OpTypeStruct Member Type <id> '3[%double_0]' is not "
+                  "a type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeStructOpaqueTypeBad) {
+TEST_P(ValidateIdWithMessage, OpTypeStructOpaqueTypeBad) {
   std::string spirv = R"(
                OpCapability Shader
                OpMemoryModel Logical GLSL450
@@ -1057,37 +1141,39 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
               AnyVUID("VUID-StandaloneSpirv-None-04667"));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpTypeStruct must not contain an opaque type"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpTypeStruct must not contain an opaque type")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypePointerGood) {
+TEST_P(ValidateIdWithMessage, OpTypePointerGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypePointer Input %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpTypePointerBad) {
+TEST_P(ValidateIdWithMessage, OpTypePointerBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 0
 %3 = OpTypePointer Input %2)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpTypePointer Type <id> '2[%uint_0]' is not a "
-                        "type."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpTypePointer Type <id> '2[%uint_0]' is not a "
+                             "type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeFunctionGood) {
+TEST_P(ValidateIdWithMessage, OpTypeFunctionGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpTypeFunctionReturnTypeBad) {
+TEST_P(ValidateIdWithMessage, OpTypeFunctionReturnTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 0
@@ -1095,10 +1181,11 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpTypeFunction Return Type <id> '2[%uint_0]' is not "
-                        "a type."));
+              HasSubstr(make_message(
+                  "OpTypeFunction Return Type <id> '2[%uint_0]' is not "
+                  "a type.")));
 }
-TEST_F(ValidateIdWithMessage, OpTypeFunctionParameterBad) {
+TEST_P(ValidateIdWithMessage, OpTypeFunctionParameterBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -1106,13 +1193,13 @@
 %4 = OpTypeFunction %1 %2 %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpTypeFunction Parameter Type <id> '3[%uint_0]' is not a "
-                "type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpTypeFunction Parameter Type <id> '3[%uint_0]' is not a "
+                  "type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeFunctionParameterTypeVoidBad) {
+TEST_P(ValidateIdWithMessage, OpTypeFunctionParameterTypeVoidBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -1120,11 +1207,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpTypeFunction Parameter Type <id> '1[%void]' cannot "
-                        "be OpTypeVoid."));
+              HasSubstr(make_message(
+                  "OpTypeFunction Parameter Type <id> '1[%void]' cannot "
+                  "be OpTypeVoid.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypePipeGood) {
+TEST_P(ValidateIdWithMessage, OpTypePipeGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 16
@@ -1133,33 +1221,33 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantTrueGood) {
+TEST_P(ValidateIdWithMessage, OpConstantTrueGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeBool
 %2 = OpConstantTrue %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantTrueBad) {
+TEST_P(ValidateIdWithMessage, OpConstantTrueBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpConstantTrue %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpConstantTrue Result Type <id> '1[%void]' is not a boolean "
-                "type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpConstantTrue Result Type <id> '1[%void]' is not a boolean "
+                  "type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantFalseGood) {
+TEST_P(ValidateIdWithMessage, OpConstantFalseGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeBool
 %2 = OpConstantTrue %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantFalseBad) {
+TEST_P(ValidateIdWithMessage, OpConstantFalseBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpConstantFalse %1)";
@@ -1167,18 +1255,19 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("OpConstantFalse Result Type <id> '1[%void]' is not a boolean "
-                "type."));
+      HasSubstr(make_message(
+          "OpConstantFalse Result Type <id> '1[%void]' is not a boolean "
+          "type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantGood) {
+TEST_P(ValidateIdWithMessage, OpConstantGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantBad) {
+TEST_P(ValidateIdWithMessage, OpConstantBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpConstant !1 !0)";
@@ -1189,7 +1278,7 @@
   EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorGood) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeVectorGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 4
@@ -1198,7 +1287,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorWithUndefGood) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeVectorWithUndefGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 4
@@ -1208,7 +1297,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorResultTypeBad) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeVectorResultTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 4
@@ -1216,12 +1305,12 @@
 %4 = OpConstantComposite %1 %3 %3 %3 %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpConstantComposite Result Type <id> '1[%float]' is not a "
-                "composite type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpConstantComposite Result Type <id> '1[%float]' is not a "
+                  "composite type.")));
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorConstituentTypeBad) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeVectorConstituentTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 4
@@ -1231,13 +1320,13 @@
 %6 = OpConstantComposite %2 %3 %5 %3 %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpConstantComposite Constituent <id> '5[%uint_42]'s type "
-                "does not match Result Type <id> '2[%v4float]'s vector "
-                "element type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpConstantComposite Constituent <id> '5[%uint_42]'s type "
+                  "does not match Result Type <id> '2[%v4float]'s vector "
+                  "element type.")));
 }
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpConstantCompositeVectorConstituentUndefTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
@@ -1250,10 +1339,11 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("OpConstantComposite Constituent <id> '5[%5]'s type does not "
-                "match Result Type <id> '2[%v4float]'s vector element type."));
+      HasSubstr(make_message(
+          "OpConstantComposite Constituent <id> '5[%5]'s type does not "
+          "match Result Type <id> '2[%v4float]'s vector element type.")));
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixGood) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeMatrixGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
  %2 = OpTypeVector %1 4
@@ -1268,7 +1358,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixUndefGood) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeMatrixUndefGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
  %2 = OpTypeVector %1 4
@@ -1283,7 +1373,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixConstituentTypeBad) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeMatrixConstituentTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
  %2 = OpTypeVector %1 4
@@ -1299,11 +1389,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpConstantComposite Constituent <id> '10[%10]' vector "
-                        "component count does not match Result Type <id> "
-                        "'4[%mat4v4float]'s vector component count."));
+              HasSubstr(make_message(
+                  "OpConstantComposite Constituent <id> '10[%10]' vector "
+                  "component count does not match Result Type <id> "
+                  "'4[%mat4v4float]'s vector component count.")));
 }
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpConstantCompositeMatrixConstituentUndefTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
@@ -1320,11 +1411,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpConstantComposite Constituent <id> '10[%10]' vector "
-                        "component count does not match Result Type <id> "
-                        "'4[%mat4v4float]'s vector component count."));
+              HasSubstr(make_message(
+                  "OpConstantComposite Constituent <id> '10[%10]' vector "
+                  "component count does not match Result Type <id> "
+                  "'4[%mat4v4float]'s vector component count.")));
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayGood) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 4
@@ -1333,7 +1425,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayWithUndefGood) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayWithUndefGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 4
@@ -1344,7 +1436,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentTypeBad) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 4
@@ -1352,10 +1444,11 @@
 %4 = OpConstantComposite %3 %2 %2 %2 %1)";  // Uses a type as operand
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 1[%uint] cannot be a "
-                                               "type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("Operand '1[%uint]' cannot be a "
+                                     "type")));
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentBad) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 4
@@ -1366,10 +1459,11 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpConstantComposite Constituent <id> '5[%5]' is not a "
-                        "constant or undef."));
+              HasSubstr(make_message(
+                  "OpConstantComposite Constituent <id> '5[%5]' is not a "
+                  "constant or undef.")));
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentTypeBad) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstituentTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 4
@@ -1380,12 +1474,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpConstantComposite Constituent <id> "
-                        "'5[%float_3_1400001]'s type does not match Result "
-                        "Type <id> '3[%_arr_uint_uint_4]'s array element "
-                        "type."));
+              HasSubstr(make_message(
+                  "OpConstantComposite Constituent <id> "
+                  "'5[%float_3_1400001]'s type does not match Result "
+                  "Type <id> '3[%_arr_uint_uint_4]'s array element "
+                  "type.")));
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentUndefTypeBad) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstituentUndefTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 4
@@ -1395,13 +1490,14 @@
 %4 = OpConstantComposite %3 %2 %2 %2 %6)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpConstantComposite Constituent <id> "
-                        "'5[%5]'s type does not match Result "
-                        "Type <id> '3[%_arr_uint_uint_4]'s array element "
-                        "type."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpConstantComposite Constituent <id> "
+                             "'5[%5]'s type does not match Result "
+                             "Type <id> '3[%_arr_uint_uint_4]'s array element "
+                             "type.")));
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeStructGood) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeStructGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeInt 64 0
@@ -1412,7 +1508,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeStructUndefGood) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeStructUndefGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeInt 64 0
@@ -1423,7 +1519,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantCompositeStructMemberTypeBad) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeStructMemberTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeInt 64 0
@@ -1434,12 +1530,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpConstantComposite Constituent <id> "
-                        "'5[%ulong_4300000000]' type does not match the "
-                        "Result Type <id> '3[%_struct_3]'s member type."));
+              HasSubstr(make_message(
+                  "OpConstantComposite Constituent <id> "
+                  "'5[%ulong_4300000000]' type does not match the "
+                  "Result Type <id> '3[%_struct_3]'s member type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantCompositeStructMemberUndefTypeBad) {
+TEST_P(ValidateIdWithMessage, OpConstantCompositeStructMemberUndefTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeInt 64 0
@@ -1450,12 +1547,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpConstantComposite Constituent <id> '5[%5]' type "
-                        "does not match the Result Type <id> '3[%_struct_3]'s "
-                        "member type."));
+              HasSubstr(make_message(
+                  "OpConstantComposite Constituent <id> '5[%5]' type "
+                  "does not match the Result Type <id> '3[%_struct_3]'s "
+                  "member type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantSamplerGood) {
+TEST_P(ValidateIdWithMessage, OpConstantSamplerGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %float = OpTypeFloat 32
 %samplerType = OpTypeSampler
@@ -1463,7 +1561,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpConstantSamplerResultTypeBad) {
+TEST_P(ValidateIdWithMessage, OpConstantSamplerResultTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpConstantSampler %1 Clamp 0 Nearest)";
@@ -1471,12 +1569,12 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
+      HasSubstr(make_message(
           "OpConstantSampler Result Type <id> '1[%float]' is not a sampler "
-          "type."));
+          "type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantNullGood) {
+TEST_P(ValidateIdWithMessage, OpConstantNullGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeBool
  %2 = OpConstantNull %1
@@ -1512,7 +1610,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantNullBasicBad) {
+TEST_P(ValidateIdWithMessage, OpConstantNullBasicBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpConstantNull %1)";
@@ -1520,11 +1618,12 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("OpConstantNull Result Type <id> '1[%void]' cannot have a null "
-                "value."));
+      HasSubstr(make_message(
+          "OpConstantNull Result Type <id> '1[%void]' cannot have a null "
+          "value.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantNullArrayBad) {
+TEST_P(ValidateIdWithMessage, OpConstantNullArrayBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %2 = OpTypeInt 32 0
 %3 = OpTypeSampler
@@ -1535,24 +1634,25 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
+      HasSubstr(make_message(
           "OpConstantNull Result Type <id> '4[%_arr_2_uint_4]' cannot have a "
-          "null value."));
+          "null value.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantNullStructBad) {
+TEST_P(ValidateIdWithMessage, OpConstantNullStructBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %2 = OpTypeSampler
 %3 = OpTypeStruct %2 %2
 %4 = OpConstantNull %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpConstantNull Result Type <id> '2[%_struct_2]' "
-                        "cannot have a null value."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpConstantNull Result Type <id> '2[%_struct_2]' "
+                             "cannot have a null value.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpConstantNullRuntimeArrayBad) {
+TEST_P(ValidateIdWithMessage, OpConstantNullRuntimeArrayBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %bool = OpTypeBool
 %array = OpTypeRuntimeArray %bool
@@ -1561,56 +1661,57 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
+      HasSubstr(make_message(
           "OpConstantNull Result Type <id> '2[%_runtimearr_bool]' cannot have "
-          "a null value."));
+          "a null value.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpSpecConstantTrueGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantTrueGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeBool
 %2 = OpSpecConstantTrue %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpSpecConstantTrueBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantTrueBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpSpecConstantTrue %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantTrue Result Type <id> '1[%void]' is not "
-                        "a boolean type"));
+              HasSubstr(make_message(
+                  "OpSpecConstantTrue Result Type <id> '1[%void]' is not "
+                  "a boolean type")));
 }
 
-TEST_F(ValidateIdWithMessage, OpSpecConstantFalseGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantFalseGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeBool
 %2 = OpSpecConstantFalse %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpSpecConstantFalseBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantFalseBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpSpecConstantFalse %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpSpecConstantFalse Result Type <id> '1[%void]' is not "
-                "a boolean type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpSpecConstantFalse Result Type <id> '1[%void]' is not "
+                  "a boolean type")));
 }
 
-TEST_F(ValidateIdWithMessage, OpSpecConstantGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpSpecConstant %1 42)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpSpecConstantBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpSpecConstant !1 !4)";
@@ -1619,12 +1720,13 @@
   // change over time, but this must always fail.
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Type Id 1 is not a scalar numeric type"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("Type Id 1 is not a scalar numeric type")));
 }
 
 // Valid: SpecConstantComposite specializes to a vector.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 4
@@ -1636,7 +1738,7 @@
 }
 
 // Valid: Vector of floats and Undefs.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorWithUndefGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorWithUndefGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 4
@@ -1649,7 +1751,7 @@
 }
 
 // Invalid: result type is float.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorResultTypeBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorResultTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 4
@@ -1657,11 +1759,12 @@
 %4 = OpSpecConstantComposite %1 %3 %3 %3 %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a composite type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("is not a composite type")));
 }
 
 // Invalid: Vector contains a mix of Int and Float.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorConstituentTypeBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorConstituentTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 4
@@ -1672,13 +1775,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> "
-                        "'5[%uint_42]'s type does not match Result Type <id> "
-                        "'2[%v4float]'s vector element type."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> "
+                  "'5[%uint_42]'s type does not match Result Type <id> "
+                  "'2[%v4float]'s vector element type.")));
 }
 
 // Invalid: Constituent is not a constant
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpSpecConstantCompositeVectorConstituentNotConstantBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
@@ -1691,12 +1795,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '6[%6]' is "
-                        "not a constant or undef."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '6[%6]' is "
+                  "not a constant or undef.")));
 }
 
 // Invalid: Vector contains a mix of Undef-int and Float.
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpSpecConstantCompositeVectorConstituentUndefTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
@@ -1708,13 +1813,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '5[%5]'s "
-                        "type does not match Result Type <id> '2[%v4float]'s "
-                        "vector element type."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '5[%5]'s "
+                  "type does not match Result Type <id> '2[%v4float]'s "
+                  "vector element type.")));
 }
 
 // Invalid: Vector expects 3 components, but 4 specified.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorNumComponentsBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorNumComponentsBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeVector %1 3
@@ -1724,13 +1830,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> count does "
-                        "not match Result Type <id> '2[%v3float]'s vector "
-                        "component count."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> count does "
+                  "not match Result Type <id> '2[%v3float]'s vector "
+                  "component count.")));
 }
 
 // Valid: 4x4 matrix of floats
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
  %2 = OpTypeVector %1 4
@@ -1747,7 +1854,7 @@
 }
 
 // Valid: Matrix in which one column is Undef
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixUndefGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixUndefGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
  %2 = OpTypeVector %1 4
@@ -1764,7 +1871,7 @@
 }
 
 // Invalid: Matrix in which the sizes of column vectors are not equal.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixConstituentTypeBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixConstituentTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
  %2 = OpTypeVector %1 4
@@ -1780,13 +1887,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '10[%10]' "
-                        "vector component count does not match Result Type "
-                        "<id> '4[%mat4v4float]'s vector component count."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '10[%10]' "
+                  "vector component count does not match Result Type "
+                  "<id> '4[%mat4v4float]'s vector component count.")));
 }
 
 // Invalid: Matrix type expects 4 columns but only 3 specified.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixNumColsBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixNumColsBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
  %2 = OpTypeVector %1 4
@@ -1799,15 +1907,15 @@
 %10 = OpSpecConstantComposite %3 %6 %7 %8)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpSpecConstantComposite Constituent <id> count does "
-                "not match Result Type <id> '3[%mat4v4float]'s matrix column "
-                "count."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> count does "
+                  "not match Result Type <id> '3[%mat4v4float]'s matrix column "
+                  "count.")));
 }
 
 // Invalid: Composite contains a non-const/undef component
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpSpecConstantCompositeMatrixConstituentNotConstBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
@@ -1821,12 +1929,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '7[%7]' is "
-                        "not a constant or undef."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '7[%7]' is "
+                  "not a constant or undef.")));
 }
 
 // Invalid: Composite contains a column that is *not* a vector (it's an array)
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColTypeBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
  %2 = OpTypeInt 32 0
@@ -1841,13 +1950,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '8[%8]' type "
-                        "does not match Result Type <id> '7[%mat4v4float]'s "
-                        "matrix column type."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '8[%8]' type "
+                  "does not match Result Type <id> '7[%mat4v4float]'s "
+                  "matrix column type.")));
 }
 
 // Invalid: Matrix with an Undef column of the wrong size.
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpSpecConstantCompositeMatrixConstituentUndefTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeFloat 32
@@ -1864,13 +1974,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '10[%10]' "
-                        "vector component count does not match Result Type "
-                        "<id> '4[%mat4v4float]'s vector component count."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '10[%10]' "
+                  "vector component count does not match Result Type "
+                  "<id> '4[%mat4v4float]'s vector component count.")));
 }
 
 // Invalid: Matrix in which some columns are Int and some are Float.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColumnTypeBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColumnTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeInt 32 0
  %2 = OpTypeFloat 32
@@ -1885,13 +1996,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '8[%8]' "
-                        "component type does not match Result Type <id> "
-                        "'5[%mat2v2float]'s matrix column component type."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '8[%8]' "
+                  "component type does not match Result Type <id> "
+                  "'5[%mat2v2float]'s matrix column component type.")));
 }
 
 // Valid: Array of integers
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpSpecConstant %1 4
@@ -1905,7 +2017,7 @@
 }
 
 // Invalid: Expecting an array of 4 components, but 3 specified.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayNumComponentsBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayNumComponentsBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 4
@@ -1914,13 +2026,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent count does not "
-                        "match Result Type <id> '3[%_arr_uint_uint_4]'s array "
-                        "length."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent count does not "
+                  "match Result Type <id> '3[%_arr_uint_uint_4]'s array "
+                  "length.")));
 }
 
 // Valid: Array of Integers and Undef-int
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayWithUndefGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayWithUndefGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpSpecConstant %1 4
@@ -1932,7 +2045,7 @@
 }
 
 // Invalid: Array uses a type as operand.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstConstituentBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstConstituentBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 4
@@ -1943,12 +2056,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '5[%5]' is "
-                        "not a constant or undef."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '5[%5]' is "
+                  "not a constant or undef.")));
 }
 
 // Invalid: Array has a mix of Int and Float components.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstituentTypeBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstituentTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpConstant %1 4
@@ -1959,13 +2073,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '5[%5]'s "
-                        "type does not match Result Type <id> "
-                        "'3[%_arr_uint_uint_4]'s array element type."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '5[%5]'s "
+                  "type does not match Result Type <id> "
+                  "'3[%_arr_uint_uint_4]'s array element type.")));
 }
 
 // Invalid: Array has a mix of Int and Undef-float.
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpSpecConstantCompositeArrayConstituentUndefTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
@@ -1977,13 +2092,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '5[%5]'s "
-                        "type does not match Result Type <id> "
-                        "'3[%_arr_uint_2]'s array element type."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '5[%5]'s "
+                  "type does not match Result Type <id> "
+                  "'3[%_arr_uint_2]'s array element type.")));
 }
 
 // Valid: Struct of {Int32,Int32,Int64}.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeInt 64 0
@@ -1996,7 +2112,7 @@
 }
 
 // Invalid: missing one int32 struct member.
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpSpecConstantCompositeStructMissingComponentBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
@@ -2006,14 +2122,15 @@
 %6 = OpSpecConstantComposite %3 %4 %5)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> "
-                        "'2[%_struct_2]' count does not match Result Type "
-                        "<id> '2[%_struct_2]'s struct member count."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpSpecConstantComposite Constituent <id> "
+                             "'2[%_struct_2]' count does not match Result Type "
+                             "<id> '2[%_struct_2]'s struct member count.")));
 }
 
 // Valid: Struct uses Undef-int64.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructUndefGood) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructUndefGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeInt 64 0
@@ -2026,7 +2143,7 @@
 }
 
 // Invalid: Composite contains non-const/undef component.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructNonConstBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructNonConstBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeInt 64 0
@@ -2039,13 +2156,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '7[%7]' is "
-                        "not a constant or undef."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '7[%7]' is "
+                  "not a constant or undef.")));
 }
 
 // Invalid: Struct component type does not match expected specialization type.
 // Second component was expected to be Int32, but got Int64.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberTypeBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeInt 64 0
@@ -2056,13 +2174,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '5[%5]' type "
-                        "does not match the Result Type <id> '3[%_struct_3]'s "
-                        "member type."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '5[%5]' type "
+                  "does not match the Result Type <id> '3[%_struct_3]'s "
+                  "member type.")));
 }
 
 // Invalid: Undef-int64 used when Int32 was expected.
-TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberUndefTypeBad) {
+TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberUndefTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeInt 64 0
@@ -2073,14 +2192,15 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpSpecConstantComposite Constituent <id> '5[%5]' type "
-                        "does not match the Result Type <id> '3[%_struct_3]'s "
-                        "member type."));
+              HasSubstr(make_message(
+                  "OpSpecConstantComposite Constituent <id> '5[%5]' type "
+                  "does not match the Result Type <id> '3[%_struct_3]'s "
+                  "member type.")));
 }
 
 // TODO: OpSpecConstantOp
 
-TEST_F(ValidateIdWithMessage, OpVariableGood) {
+TEST_P(ValidateIdWithMessage, OpVariableGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypePointer Input %1
@@ -2088,16 +2208,16 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpVariableInitializerConstantGood) {
+TEST_P(ValidateIdWithMessage, OpVariableInitializerConstantGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
-%2 = OpTypePointer Input %1
+%2 = OpTypePointer Output %1
 %3 = OpConstant %1 42
-%4 = OpVariable %2 Input %3)";
+%4 = OpVariable %2 Output %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpVariableInitializerGlobalVariableGood) {
+TEST_P(ValidateIdWithMessage, OpVariableInitializerGlobalVariableGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypePointer Uniform %1
@@ -2109,29 +2229,30 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 // TODO: Positive test OpVariable with OpConstantNull of OpTypePointer
-TEST_F(ValidateIdWithMessage, OpVariableResultTypeBad) {
+TEST_P(ValidateIdWithMessage, OpVariableResultTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpVariable %1 Input)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpVariable Result Type <id> '1[%uint]' is not a pointer "
-                "type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpVariable Result Type <id> '1[%uint]' is not a pointer "
+                  "type.")));
 }
-TEST_F(ValidateIdWithMessage, OpVariableInitializerIsTypeBad) {
+TEST_P(ValidateIdWithMessage, OpVariableInitializerIsTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypePointer Input %1
 %3 = OpVariable %2 Input %2)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 2[%_ptr_Input_uint] "
-                                               "cannot be a type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("Operand '2[%_ptr_Input_uint]' "
+                                     "cannot be a type")));
 }
 
-TEST_F(ValidateIdWithMessage, OpVariableInitializerIsFunctionVarBad) {
+TEST_P(ValidateIdWithMessage, OpVariableInitializerIsFunctionVarBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %int = OpTypeInt 32 0
 %ptrint = OpTypePointer Function %int
@@ -2148,11 +2269,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpVariable Initializer <id> '8[%8]' is not a constant "
-                        "or module-scope variable"));
+              HasSubstr(make_message(
+                  "OpVariable Initializer <id> '8[%8]' is not a constant "
+                  "or module-scope variable")));
 }
 
-TEST_F(ValidateIdWithMessage, OpVariableInitializerIsModuleVarGood) {
+TEST_P(ValidateIdWithMessage, OpVariableInitializerIsModuleVarGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %int = OpTypeInt 32 0
 %ptrint = OpTypePointer Uniform %int
@@ -2170,7 +2292,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpVariableContainsBoolBad) {
+TEST_P(ValidateIdWithMessage, OpVariableContainsBoolBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %bool = OpTypeBool
 %int = OpTypeInt 32 0
@@ -2187,14 +2309,36 @@
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("If OpTypeBool is stored in conjunction with OpVariable"
-                        ", it can only be used with non-externally visible "
-                        "shader Storage Classes: Workgroup, CrossWorkgroup, "
-                        "Private, and Function"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message(
+          "If OpTypeBool is stored in conjunction with OpVariable, it can only "
+          "be used with non-externally visible shader Storage Classes: "
+          "Workgroup, CrossWorkgroup, Private, Function, Input, Output, "
+          "RayPayloadKHR, IncomingRayPayloadKHR, HitAttributeKHR, "
+          "CallableDataKHR, or IncomingCallableDataKHR")));
 }
 
-TEST_F(ValidateIdWithMessage, OpVariableContainsBoolPointerGood) {
+TEST_P(ValidateIdWithMessage, OpVariableContainsBoolPrivateGood) {
+  std::string spirv = kGLSL450MemoryModel + R"(
+%bool = OpTypeBool
+%int = OpTypeInt 32 0
+%block = OpTypeStruct %bool %int
+%_ptr_Private_block = OpTypePointer Private %block
+%var = OpVariable %_ptr_Private_block Private
+%void = OpTypeVoid
+%fnty = OpTypeFunction %void
+%main = OpFunction %void None %fnty
+%entry = OpLabel
+%load = OpLoad %block %var
+OpReturn
+OpFunctionEnd
+)";
+  CompileSuccessfully(spirv.c_str());
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_P(ValidateIdWithMessage, OpVariableContainsBoolPointerGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %bool = OpTypeBool
 %boolptr = OpTypePointer Uniform %bool
@@ -2214,7 +2358,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpVariableContainsBuiltinBoolGood) {
+TEST_P(ValidateIdWithMessage, OpVariableContainsBuiltinBoolGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 OpMemberDecorate %input 0 BuiltIn FrontFacing
 %bool = OpTypeBool
@@ -2233,7 +2377,59 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpVariableContainsRayPayloadBoolGood) {
+TEST_P(ValidateIdWithMessage, OpVariableContainsNoBuiltinBoolBad) {
+  std::string spirv = kGLSL450MemoryModel + R"(
+%bool = OpTypeBool
+%input = OpTypeStruct %bool
+%_ptr_input = OpTypePointer Input %input
+%var = OpVariable %_ptr_input Input
+%void = OpTypeVoid
+%fnty = OpTypeFunction %void
+%main = OpFunction %void None %fnty
+%entry = OpLabel
+%load = OpLoad %input %var
+OpReturn
+OpFunctionEnd
+)";
+  CompileSuccessfully(spirv.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message(
+          "If OpTypeBool is stored in conjunction with OpVariable using Input "
+          "or Output Storage Classes it requires a BuiltIn decoration")));
+}
+
+TEST_P(ValidateIdWithMessage, OpVariableContainsNoBuiltinBoolBadVulkan) {
+  std::string spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %var
+OpExecutionMode %main OriginUpperLeft
+%bool = OpTypeBool
+%input = OpTypeStruct %bool
+%_ptr_input = OpTypePointer Input %input
+%var = OpVariable %_ptr_input Input
+%void = OpTypeVoid
+%fnty = OpTypeFunction %void
+%main = OpFunction %void None %fnty
+%entry = OpLabel
+%load = OpLoad %input %var
+OpReturn
+OpFunctionEnd
+)";
+  CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Input-07290"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message(
+          "If OpTypeBool is stored in conjunction with OpVariable using Input "
+          "or Output Storage Classes it requires a BuiltIn decoration")));
+}
+
+TEST_P(ValidateIdWithMessage, OpVariableContainsRayPayloadBoolGood) {
   std::string spirv = R"(
 OpCapability RayTracingNV
 OpCapability Shader
@@ -2256,7 +2452,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpVariablePointerNoVariablePointersBad) {
+TEST_P(ValidateIdWithMessage, OpVariablePointerNoVariablePointersBad) {
   const std::string spirv = R"(
 OpCapability Shader
 OpCapability Linkage
@@ -2277,11 +2473,11 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
-          "In Logical addressing, variables may not allocate a pointer type"));
+      HasSubstr(make_message(
+          "In Logical addressing, variables may not allocate a pointer type")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpVariablePointerNoVariablePointersRelaxedLogicalGood) {
   const std::string spirv = R"(
 OpCapability Shader
@@ -2305,7 +2501,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpFunctionWithNonMemoryObject) {
+TEST_P(ValidateIdWithMessage, OpFunctionWithNonMemoryObject) {
   // DXC generates code that looks like when given something like:
   //   T t;
   //   t.s.fn_1();
@@ -2346,7 +2542,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        OpVariablePointerVariablePointersStorageBufferGood) {
   const std::string spirv = R"(
 OpCapability Shader
@@ -2370,7 +2566,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpVariablePointerVariablePointersGood) {
+TEST_P(ValidateIdWithMessage, OpVariablePointerVariablePointersGood) {
   const std::string spirv = R"(
 OpCapability Shader
 OpCapability Linkage
@@ -2393,7 +2589,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpVariablePointerVariablePointersBad) {
+TEST_P(ValidateIdWithMessage, OpVariablePointerVariablePointersBad) {
   const std::string spirv = R"(
 OpCapability Shader
 OpCapability VariablePointers
@@ -2409,12 +2605,13 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("In Logical addressing with variable pointers, "
-                        "variables that allocate pointers must be in Function "
-                        "or Private storage classes"));
+              HasSubstr(make_message(
+                  "In Logical addressing with variable pointers, "
+                  "variables that allocate pointers must be in Function "
+                  "or Private storage classes")));
 }
 
-TEST_F(ValidateIdWithMessage, OpLoadGood) {
+TEST_P(ValidateIdWithMessage, OpLoadGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeVoid
  %2 = OpTypeInt 32 0
@@ -2487,7 +2684,7 @@
 
 // With the VariablePointer Capability, OpLoad should allow loading a
 // VaiablePointer. In this test the variable pointer is obtained by an OpSelect
-TEST_F(ValidateIdWithMessage, OpLoadVarPtrOpSelectGood) {
+TEST_P(ValidateIdWithMessage, OpLoadVarPtrOpSelectGood) {
   std::string result_strategy = R"(
     %isneg     = OpSLessThan %bool %i %zero
     %varptr    = OpSelect %f32ptr %isneg %ptr1 %ptr2
@@ -2506,7 +2703,7 @@
 // through a variable pointer.
 // Disabled since using OpSelect with pointers without VariablePointers will
 // fail LogicalsPass.
-TEST_F(ValidateIdWithMessage, DISABLED_OpLoadVarPtrOpSelectBad) {
+TEST_P(ValidateIdWithMessage, DISABLED_OpLoadVarPtrOpSelectBad) {
   std::string result_strategy = R"(
     %isneg     = OpSLessThan %bool %i %zero
     %varptr    = OpSelect %f32ptr %isneg %ptr1 %ptr2
@@ -2519,12 +2716,13 @@
                                     false /* Use Helper Function? */);
   CompileSuccessfully(spirv.str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a logical pointer."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("is not a logical pointer.")));
 }
 
 // With the VariablePointer Capability, OpLoad should allow loading a
 // VaiablePointer. In this test the variable pointer is obtained by an OpPhi
-TEST_F(ValidateIdWithMessage, OpLoadVarPtrOpPhiGood) {
+TEST_P(ValidateIdWithMessage, OpLoadVarPtrOpPhiGood) {
   std::string result_strategy = R"(
     %is_neg      = OpSLessThan %bool %i %zero
     OpSelectionMerge %end_label None
@@ -2548,7 +2746,7 @@
 
 // Without the VariablePointers Capability, OpPhi can have a pointer result
 // type.
-TEST_F(ValidateIdWithMessage, OpPhiBad) {
+TEST_P(ValidateIdWithMessage, OpPhiBad) {
   std::string result_strategy = R"(
     %is_neg      = OpSLessThan %bool %i %zero
     OpSelectionMerge %end_label None
@@ -2569,14 +2767,15 @@
   CompileSuccessfully(spirv.str());
   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Using pointers with OpPhi requires capability "
-                        "VariablePointers or VariablePointersStorageBuffer"));
+              HasSubstr(make_message(
+                  "Using pointers with OpPhi requires capability "
+                  "VariablePointers or VariablePointersStorageBuffer")));
 }
 
 // With the VariablePointer Capability, OpLoad should allow loading through a
 // VaiablePointer. In this test the variable pointer is obtained from an
 // OpFunctionCall (return value from a function)
-TEST_F(ValidateIdWithMessage, OpLoadVarPtrOpFunctionCallGood) {
+TEST_P(ValidateIdWithMessage, OpLoadVarPtrOpFunctionCallGood) {
   std::ostringstream spirv;
   std::string result_strategy = R"(
     %isneg     = OpSLessThan %bool %i %zero
@@ -2591,7 +2790,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpLoadResultTypeBad) {
+TEST_P(ValidateIdWithMessage, OpLoadResultTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -2606,13 +2805,14 @@
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpLoad Result Type <id> "
-                        "'3[%_ptr_UniformConstant_uint]' does not match "
-                        "Pointer <id> '5[%5]'s type."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpLoad Result Type <id> "
+                             "'3[%_ptr_UniformConstant_uint]' does not match "
+                             "Pointer <id> '5[%5]'s type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpLoadPointerBad) {
+TEST_P(ValidateIdWithMessage, OpLoadPointerBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -2628,12 +2828,13 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   // Prove that SSA checks trigger for a bad Id value.
   // The next test case show the not-a-logical-pointer case.
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 8[%8] has not been "
-                                               "defined"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("ID '8[%8]' has not been "
+                                     "defined")));
 }
 
 // Disabled as bitcasting type to object is now not valid.
-TEST_F(ValidateIdWithMessage, DISABLED_OpLoadLogicalPointerBad) {
+TEST_P(ValidateIdWithMessage, DISABLED_OpLoadLogicalPointerBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -2655,10 +2856,11 @@
   // I don't know if it's possible to generate a bad case
   // if/when the validator is complete.
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpLoad Pointer <id> '9' is not a logical pointer."));
+              HasSubstr(make_message(
+                  "OpLoad Pointer <id> '9' is not a logical pointer.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpStoreGood) {
+TEST_P(ValidateIdWithMessage, OpStoreGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -2674,7 +2876,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpStorePointerBad) {
+TEST_P(ValidateIdWithMessage, OpStorePointerBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -2691,12 +2893,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpStore Pointer <id> '7[%uint_0]' is not a logical "
-                        "pointer."));
+              HasSubstr(make_message(
+                  "OpStore Pointer <id> '7[%uint_0]' is not a logical "
+                  "pointer.")));
 }
 
 // Disabled as bitcasting type to object is now not valid.
-TEST_F(ValidateIdWithMessage, DISABLED_OpStoreLogicalPointerBad) {
+TEST_P(ValidateIdWithMessage, DISABLED_OpStoreLogicalPointerBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -2715,14 +2918,15 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpStore Pointer <id> '10' is not a logical pointer."));
+              HasSubstr(make_message(
+                  "OpStore Pointer <id> '10' is not a logical pointer.")));
 }
 
 // Without the VariablePointer Capability, OpStore should may not store
 // through a variable pointer.
 // Disabled since using OpSelect with pointers without VariablePointers will
 // fail LogicalsPass.
-TEST_F(ValidateIdWithMessage, DISABLED_OpStoreVarPtrBad) {
+TEST_P(ValidateIdWithMessage, DISABLED_OpStoreVarPtrBad) {
   std::string result_strategy = R"(
     %isneg     = OpSLessThan %bool %i %zero
     %varptr    = OpSelect %f32ptr %isneg %ptr1 %ptr2
@@ -2735,12 +2939,13 @@
       false /* Use Helper Function? */);
   CompileSuccessfully(spirv.str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a logical pointer."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("is not a logical pointer.")));
 }
 
 // With the VariablePointer Capability, OpStore should allow storing through a
 // variable pointer.
-TEST_F(ValidateIdWithMessage, OpStoreVarPtrGood) {
+TEST_P(ValidateIdWithMessage, OpStoreVarPtrGood) {
   std::string result_strategy = R"(
     %isneg     = OpSLessThan %bool %i %zero
     %varptr    = OpSelect %f32ptr %isneg %ptr1 %ptr2
@@ -2755,7 +2960,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpStoreObjectGood) {
+TEST_P(ValidateIdWithMessage, OpStoreObjectGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -2775,10 +2980,11 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpStore Object <id> '9[%9]'s type is void."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpStore Object <id> '9[%9]'s type is void.")));
 }
-TEST_F(ValidateIdWithMessage, OpStoreTypeBad) {
+TEST_P(ValidateIdWithMessage, OpStoreTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -2795,8 +3001,9 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpStore Pointer <id> '7[%7]'s type does not match "
-                        "Object <id> '6[%float_3_1400001]'s type."));
+              HasSubstr(make_message(
+                  "OpStore Pointer <id> '7[%7]'s type does not match "
+                  "Object <id> '6[%float_3_1400001]'s type.")));
 }
 
 // The next series of test check test a relaxation of the rules for stores to
@@ -2805,7 +3012,7 @@
 // TODO: Add tests for layout compatible arrays and matricies when the validator
 //       relaxes the rules for them as well.  Also need test to check for layout
 //       decorations specific to those types.
-TEST_F(ValidateIdWithMessage, OpStoreTypeBadStruct) {
+TEST_P(ValidateIdWithMessage, OpStoreTypeBadStruct) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberDecorate %1 0 Offset 0
      OpMemberDecorate %1 1 Offset 4
@@ -2828,13 +3035,14 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpStore Pointer <id> '8[%8]'s type does not match "
-                        "Object <id> '11[%11]'s type."));
+              HasSubstr(make_message(
+                  "OpStore Pointer <id> '8[%8]'s type does not match "
+                  "Object <id> '11[%11]'s type.")));
 }
 
 // Same code as the last test.  The difference is that we relax the rule.
 // Because the structs %3 and %5 are defined the same way.
-TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedStruct) {
+TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedStruct) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberDecorate %1 0 Offset 0
      OpMemberDecorate %1 1 Offset 4
@@ -2861,7 +3069,7 @@
 
 // Same code as the last test except for an extra decoration on one of the
 // members. With the relaxed rules, the code is still valid.
-TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedStructWithExtraDecoration) {
+TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedStructWithExtraDecoration) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberDecorate %1 0 Offset 0
      OpMemberDecorate %1 1 Offset 4
@@ -2889,7 +3097,7 @@
 
 // This test check that we recursively traverse the struct to check if they are
 // interchangable.
-TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedNestedStruct) {
+TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedNestedStruct) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberDecorate %1 0 Offset 0
      OpMemberDecorate %1 1 Offset 4
@@ -2925,7 +3133,7 @@
 
 // This test check that the even with the relaxed rules an error is identified
 // if the members of the struct are in a different order.
-TEST_F(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct1) {
+TEST_P(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct1) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberDecorate %1 0 Offset 0
      OpMemberDecorate %1 1 Offset 4
@@ -2959,13 +3167,14 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("OpStore Pointer <id> '13[%13]'s layout does not match Object "
-                "<id> '16[%16]'s layout."));
+      HasSubstr(make_message(
+          "OpStore Pointer <id> '13[%13]'s layout does not match Object "
+          "<id> '16[%16]'s layout.")));
 }
 
 // This test check that the even with the relaxed rules an error is identified
 // if the members of the struct are at different offsets.
-TEST_F(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct2) {
+TEST_P(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct2) {
   std::string spirv = kGLSL450MemoryModel + R"(
      OpMemberDecorate %1 0 Offset 4
      OpMemberDecorate %1 1 Offset 0
@@ -2999,11 +3208,12 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("OpStore Pointer <id> '13[%13]'s layout does not match Object "
-                "<id> '16[%16]'s layout."));
+      HasSubstr(make_message(
+          "OpStore Pointer <id> '13[%13]'s layout does not match Object "
+          "<id> '16[%16]'s layout.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerReturnPointer) {
+TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerReturnPointer) {
   const std::string spirv = R"(
      OpCapability Shader
      OpCapability Linkage
@@ -3022,7 +3232,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerAllocPointer) {
+TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerAllocPointer) {
   const std::string spirv = R"(
       OpCapability Shader
       OpCapability Linkage
@@ -3045,7 +3255,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpStoreVoid) {
+TEST_P(ValidateIdWithMessage, OpStoreVoid) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3060,11 +3270,12 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpStore Object <id> '8[%8]'s type is void."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpStore Object <id> '8[%8]'s type is void.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpStoreLabel) {
+TEST_P(ValidateIdWithMessage, OpStoreLabel) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3079,12 +3290,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 7[%7] requires a type"));
+              HasSubstr(make_message("Operand '7[%7]' requires a type")));
 }
 
 // TODO: enable when this bug is fixed:
 // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
-TEST_F(ValidateIdWithMessage, DISABLED_OpStoreFunction) {
+TEST_P(ValidateIdWithMessage, DISABLED_OpStoreFunction) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %2 = OpTypeInt 32 0
 %3 = OpTypePointer UniformConstant %2
@@ -3100,7 +3311,7 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpStoreBuiltin) {
+TEST_P(ValidateIdWithMessage, OpStoreBuiltin) {
   std::string spirv = R"(
                OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
@@ -3135,10 +3346,11 @@
 
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("storage class is read-only"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("storage class is read-only")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemoryGood) {
+TEST_P(ValidateIdWithMessage, OpCopyMemoryGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeVoid
  %2 = OpTypeInt 32 0
@@ -3158,7 +3370,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemoryNonPointerTarget) {
+TEST_P(ValidateIdWithMessage, OpCopyMemoryNonPointerTarget) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3175,11 +3387,12 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Target operand <id> '6[%6]' is not a pointer."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("Target operand <id> '6[%6]' is not a pointer.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemoryNonPointerSource) {
+TEST_P(ValidateIdWithMessage, OpCopyMemoryNonPointerSource) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3196,11 +3409,12 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Source operand <id> '6[%6]' is not a pointer."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("Source operand <id> '6[%6]' is not a pointer.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemoryBad) {
+TEST_P(ValidateIdWithMessage, OpCopyMemoryBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeVoid
  %2 = OpTypeInt 32 0
@@ -3220,11 +3434,11 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Target <id> '5[%5]'s type does not match "
-                        "Source <id> '2[%uint]'s type."));
+              HasSubstr(make_message("Target <id> '5[%5]'s type does not match "
+                                     "Source <id> '2[%uint]'s type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemoryVoidTarget) {
+TEST_P(ValidateIdWithMessage, OpCopyMemoryVoidTarget) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3242,12 +3456,13 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Target operand <id> '7[%7]' cannot be a void "
-                        "pointer."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("Target operand <id> '7[%7]' cannot be a void "
+                             "pointer.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemoryVoidSource) {
+TEST_P(ValidateIdWithMessage, OpCopyMemoryVoidSource) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3265,12 +3480,13 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Source operand <id> '7[%7]' cannot be a void "
-                        "pointer."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("Source operand <id> '7[%7]' cannot be a void "
+                             "pointer.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedGood) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeVoid
  %2 = OpTypeInt 32 0
@@ -3288,7 +3504,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedTargetBad) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedTargetBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3305,9 +3521,10 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Target operand <id> '5[%uint_4]' is not a pointer."));
+              HasSubstr(make_message(
+                  "Target operand <id> '5[%uint_4]' is not a pointer.")));
 }
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSourceBad) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSourceBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3324,9 +3541,10 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Source operand <id> '5[%uint_4]' is not a pointer."));
+              HasSubstr(make_message(
+                  "Source operand <id> '5[%uint_4]' is not a pointer.")));
 }
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeBad) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeVoid
  %2 = OpTypeInt 32 0
@@ -3343,11 +3561,11 @@
       OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Size operand <id> '6[%6]' must be a scalar integer type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "Size operand <id> '6[%6]' must be a scalar integer type.")));
 }
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeTypeBad) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
  %1 = OpTypeVoid
  %2 = OpTypeInt 32 0
@@ -3366,13 +3584,13 @@
       OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Size operand <id> '9[%float_1]' must be a scalar integer "
-                "type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "Size operand <id> '9[%float_1]' must be a scalar integer "
+                  "type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNull) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNull) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3392,12 +3610,13 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Size operand <id> '3[%3]' cannot be a constant "
-                        "zero."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("Size operand <id> '3[%3]' cannot be a constant "
+                             "zero.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3418,11 +3637,12 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Size operand <id> '3[%uint_0]' cannot be a constant "
-                        "zero."));
+              HasSubstr(make_message(
+                  "Size operand <id> '3[%uint_0]' cannot be a constant "
+                  "zero.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero64) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero64) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 64 0
@@ -3443,11 +3663,12 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Size operand <id> '3[%ulong_0]' cannot be a constant "
-                        "zero."));
+              HasSubstr(make_message(
+                  "Size operand <id> '3[%ulong_0]' cannot be a constant "
+                  "zero.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 1
@@ -3467,13 +3688,13 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Size operand <id> '3[%int_n1]' cannot have the sign bit set "
-                "to 1."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "Size operand <id> '3[%int_n1]' cannot have the sign bit set "
+                  "to 1.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative64) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative64) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 64 1
@@ -3495,11 +3716,12 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Size operand <id> '3[%long_n1]' cannot have the sign bit set "
-                "to 1."));
+      HasSubstr(make_message(
+          "Size operand <id> '3[%long_n1]' cannot have the sign bit set "
+          "to 1.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -3521,7 +3743,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative64) {
+TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative64) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 64 0
@@ -3656,7 +3878,7 @@
   )";
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 1[%void] cannot be a "
+  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '1[%void]' cannot be a "
                                                "type"));
 }
 
@@ -3675,7 +3897,7 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 8[%_ptr_Private_float] cannot be a type"));
+              HasSubstr("Operand '8[%_ptr_Private_float]' cannot be a type"));
 }
 
 // Invalid: The storage class of Base and Result do not match.
@@ -3759,8 +3981,11 @@
 TEST_P(AccessChainInstructionTest, AccessChainTooManyIndexesGood) {
   const std::string instr = GetParam();
   const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
+  const std::string arrayStride =
+      " OpDecorate %_ptr_Uniform_deep_struct ArrayStride 8 ";
   int depth = 255;
-  std::string header = kGLSL450MemoryModel + kDeeplyNestedStructureSetup;
+  std::string header =
+      kGLSL450MemoryModel + arrayStride + kDeeplyNestedStructureSetup;
   header.erase(header.find("%func"));
   std::ostringstream spirv;
   spirv << header << "\n";
@@ -3822,8 +4047,11 @@
 TEST_P(AccessChainInstructionTest, CustomizedAccessChainTooManyIndexesGood) {
   const std::string instr = GetParam();
   const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
+  const std::string arrayStride =
+      " OpDecorate %_ptr_Uniform_deep_struct ArrayStride 8 ";
   int depth = 10;
-  std::string header = kGLSL450MemoryModel + kDeeplyNestedStructureSetup;
+  std::string header =
+      kGLSL450MemoryModel + arrayStride + kDeeplyNestedStructureSetup;
   header.erase(header.find("%func"));
   std::ostringstream spirv;
   spirv << header << "\n";
@@ -3995,8 +4223,11 @@
   // 0 will select the element at the index 0 of the vector. (which is a float).
   const std::string instr = GetParam();
   const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
+  const std::string arrayStride =
+      " OpDecorate %_ptr_Uniform_blockName ArrayStride 8 ";
   std::ostringstream spirv;
-  spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup << std::endl;
+  spirv << kGLSL450MemoryModel << arrayStride << kDeeplyNestedStructureSetup
+        << std::endl;
   spirv << "%ss = " << instr << " %_ptr_Uniform_struct_s %blockName_var "
         << elem << "%int_0" << std::endl;
   spirv << "%sa = " << instr << " %_ptr_Uniform_array5_mat4x3 %blockName_var "
@@ -4019,9 +4250,12 @@
 TEST_P(AccessChainInstructionTest, AccessChainIndexIntoRuntimeArrayGood) {
   const std::string instr = GetParam();
   const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
-  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
-%runtime_arr_entry = )" +
-                      instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
+  const std::string arrayStride =
+      " OpDecorate %_ptr_Uniform_blockName ArrayStride 8 ";
+  std::string spirv = kGLSL450MemoryModel + arrayStride +
+                      kDeeplyNestedStructureSetup + R"(
+%runtime_arr_entry = )" + instr +
+                      R"( %_ptr_Uniform_float %blockName_var )" + elem +
                       R"(%int_2 %int_0
 OpReturn
 OpFunctionEnd
@@ -4100,7 +4334,7 @@
 // TODO: OpImagePointer
 // TODO: OpGenericPtrMemSemantics
 
-TEST_F(ValidateIdWithMessage, OpFunctionGood) {
+TEST_P(ValidateIdWithMessage, OpFunctionGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4112,7 +4346,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpFunctionResultTypeBad) {
+TEST_P(ValidateIdWithMessage, OpFunctionResultTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4124,12 +4358,13 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpFunction Result Type <id> '2[%uint]' does not "
-                        "match the Function Type's return type <id> "
-                        "'1[%void]'."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpFunction Result Type <id> '2[%uint]' does not "
+                             "match the Function Type's return type <id> "
+                             "'1[%void]'.")));
 }
-TEST_F(ValidateIdWithMessage, OpReturnValueTypeBad) {
+TEST_P(ValidateIdWithMessage, OpReturnValueTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeInt 32 0
 %2 = OpTypeFloat 32
@@ -4142,10 +4377,11 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpReturnValue Value <id> '3[%float_0]'s type does "
-                        "not match OpFunction's return type."));
+              HasSubstr(make_message(
+                  "OpReturnValue Value <id> '3[%float_0]'s type does "
+                  "not match OpFunction's return type.")));
 }
-TEST_F(ValidateIdWithMessage, OpFunctionFunctionTypeBad) {
+TEST_P(ValidateIdWithMessage, OpFunctionFunctionTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4155,13 +4391,13 @@
 OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpFunction Function Type <id> '2[%uint]' is not a function "
-                "type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpFunction Function Type <id> '2[%uint]' is not a function "
+                  "type.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpFunctionUseBad) {
+TEST_P(ValidateIdWithMessage, OpFunctionUseBad) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeFloat 32
 %2 = OpTypeFunction %1
@@ -4173,11 +4409,12 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Invalid use of function result id 3[%3]."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("Invalid use of function result id '3[%3]'.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpFunctionParameterGood) {
+TEST_P(ValidateIdWithMessage, OpFunctionParameterGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4190,7 +4427,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpFunctionParameterMultipleGood) {
+TEST_P(ValidateIdWithMessage, OpFunctionParameterMultipleGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4204,7 +4441,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpFunctionParameterResultTypeBad) {
+TEST_P(ValidateIdWithMessage, OpFunctionParameterResultTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4218,11 +4455,12 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("OpFunctionParameter Result Type <id> '1[%void]' does not "
-                "match the OpTypeFunction parameter type of the same index."));
+      HasSubstr(make_message(
+          "OpFunctionParameter Result Type <id> '1[%void]' does not "
+          "match the OpTypeFunction parameter type of the same index.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpFunctionCallGood) {
+TEST_P(ValidateIdWithMessage, OpFunctionCallGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4244,7 +4482,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpFunctionCallResultTypeBad) {
+TEST_P(ValidateIdWithMessage, OpFunctionCallResultTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4266,12 +4504,13 @@
       OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpFunctionCall Result Type <id> '1[%void]'s type "
-                        "does not match Function <id> '2[%uint]'s return "
-                        "type."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpFunctionCall Result Type <id> '1[%void]'s type "
+                             "does not match Function <id> '2[%uint]'s return "
+                             "type.")));
 }
-TEST_F(ValidateIdWithMessage, OpFunctionCallFunctionBad) {
+TEST_P(ValidateIdWithMessage, OpFunctionCallFunctionBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4287,10 +4526,11 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpFunctionCall Function <id> '5[%uint_42]' is not a "
-                        "function."));
+              HasSubstr(make_message(
+                  "OpFunctionCall Function <id> '5[%uint_42]' is not a "
+                  "function.")));
 }
-TEST_F(ValidateIdWithMessage, OpFunctionCallArgumentTypeBad) {
+TEST_P(ValidateIdWithMessage, OpFunctionCallArgumentTypeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4316,14 +4556,15 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpFunctionCall Argument <id> '7[%float_3_1400001]'s "
-                        "type does not match Function <id> '2[%uint]'s "
-                        "parameter type."));
+              HasSubstr(make_message(
+                  "OpFunctionCall Argument <id> '7[%float_3_1400001]'s "
+                  "type does not match Function <id> '2[%uint]'s "
+                  "parameter type.")));
 }
 
 // Valid: OpSampledImage result <id> is used in the same block by
 // OpImageSampleImplictLod
-TEST_F(ValidateIdWithMessage, OpSampledImageGood) {
+TEST_P(ValidateIdWithMessage, OpSampledImageGood) {
   std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
 %si_lod    = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1
@@ -4335,7 +4576,7 @@
 
 // Invalid: OpSampledImage result <id> is defined in one block and used in a
 // different block.
-TEST_F(ValidateIdWithMessage, OpSampledImageUsedInDifferentBlockBad) {
+TEST_P(ValidateIdWithMessage, OpSampledImageUsedInDifferentBlockBad) {
   std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
 OpBranch %label_2
@@ -4347,10 +4588,11 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("All OpSampledImage instructions must be in the same block in "
-                "which their Result <id> are consumed. OpSampledImage Result "
-                "Type <id> '23[%23]' has a consumer in a different basic "
-                "block. The consumer instruction <id> is '25[%25]'."));
+      HasSubstr(make_message(
+          "All OpSampledImage instructions must be in the same block in "
+          "which their Result <id> are consumed. OpSampledImage Result "
+          "Type <id> '23[%23]' has a consumer in a different basic "
+          "block. The consumer instruction <id> is '25[%25]'.")));
 }
 
 // Invalid: OpSampledImage result <id> is used by OpSelect
@@ -4361,7 +4603,7 @@
 // updated, the error message for this test may change.
 //
 // Disabled since OpSelect catches this now.
-TEST_F(ValidateIdWithMessage, DISABLED_OpSampledImageUsedInOpSelectBad) {
+TEST_P(ValidateIdWithMessage, DISABLED_OpSampledImageUsedInOpSelectBad) {
   std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
 %smpld_img  = OpSampledImage %sampled_image_type %image_inst %sampler_inst
 %select_img = OpSelect %sampled_image_type %spec_true %smpld_img %smpld_img
@@ -4370,12 +4612,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Result <id> from OpSampledImage instruction must not "
-                        "appear as operands of OpSelect. Found result <id> "
-                        "'23' as an operand of <id> '24'."));
+              HasSubstr(make_message(
+                  "Result <id> from OpSampledImage instruction must not "
+                  "appear as operands of OpSelect. Found result <id> "
+                  "'23' as an operand of <id> '24'.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpCopyObjectSampledImageGood) {
+TEST_P(ValidateIdWithMessage, OpCopyObjectSampledImageGood) {
   std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
 %smpld_img  = OpSampledImage %sampled_image_type %image_inst %sampler_inst
 %smpld_img2 = OpCopyObject %sampled_image_type %smpld_img
@@ -4388,7 +4631,7 @@
 
 // Valid: Get a float in a matrix using CompositeExtract.
 // Valid: Insert float into a matrix using CompositeInsert.
-TEST_F(ValidateIdWithMessage, CompositeExtractInsertGood) {
+TEST_P(ValidateIdWithMessage, CompositeExtractInsertGood) {
   std::ostringstream spirv;
   spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup << std::endl;
   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
@@ -4404,7 +4647,7 @@
 }
 
 #if 0
-TEST_F(ValidateIdWithMessage, OpFunctionCallArgumentCountBar) {
+TEST_P(ValidateIdWithMessage, OpFunctionCallArgumentCountBar) {
   const char *spirv = R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -4471,7 +4714,7 @@
 // TODO: OpVectorExtractDynamic
 // TODO: OpVectorInsertDynamic
 
-TEST_F(ValidateIdWithMessage, OpVectorShuffleIntGood) {
+TEST_P(ValidateIdWithMessage, OpVectorShuffleIntGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %int = OpTypeInt 32 0
 %ivec3 = OpTypeVector %int 3
@@ -4494,7 +4737,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpVectorShuffleFloatGood) {
+TEST_P(ValidateIdWithMessage, OpVectorShuffleFloatGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %float = OpTypeFloat 32
 %vec2 = OpTypeVector %float 2
@@ -4520,7 +4763,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpVectorShuffleScalarResultType) {
+TEST_P(ValidateIdWithMessage, OpVectorShuffleScalarResultType) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %float = OpTypeFloat 32
 %vec2 = OpTypeVector %float 2
@@ -4538,12 +4781,12 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Result Type of OpVectorShuffle must be OpTypeVector."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "Result Type of OpVectorShuffle must be OpTypeVector.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpVectorShuffleComponentCount) {
+TEST_P(ValidateIdWithMessage, OpVectorShuffleComponentCount) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %int = OpTypeInt 32 0
 %ivec3 = OpTypeVector %int 3
@@ -4562,13 +4805,13 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpVectorShuffle component literals count does not match "
-                "Result Type <id> '2[%v3uint]'s vector component count."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpVectorShuffle component literals count does not match "
+                  "Result Type <id> '2[%v3uint]'s vector component count.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpVectorShuffleVector1Type) {
+TEST_P(ValidateIdWithMessage, OpVectorShuffleVector1Type) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %int = OpTypeInt 32 0
 %ivec2 = OpTypeVector %int 2
@@ -4585,11 +4828,12 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("The type of Vector 1 must be OpTypeVector."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("The type of Vector 1 must be OpTypeVector.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpVectorShuffleVector2Type) {
+TEST_P(ValidateIdWithMessage, OpVectorShuffleVector2Type) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %int = OpTypeInt 32 0
 %ivec2 = OpTypeVector %int 2
@@ -4607,11 +4851,12 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("The type of Vector 2 must be OpTypeVector."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("The type of Vector 2 must be OpTypeVector.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpVectorShuffleVector1ComponentType) {
+TEST_P(ValidateIdWithMessage, OpVectorShuffleVector1ComponentType) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %int = OpTypeInt 32 0
 %ivec3 = OpTypeVector %int 3
@@ -4640,11 +4885,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("The Component Type of Vector 1 must be the same as "
-                        "ResultType."));
+              HasSubstr(make_message(
+                  "The Component Type of Vector 1 must be the same as "
+                  "ResultType.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpVectorShuffleVector2ComponentType) {
+TEST_P(ValidateIdWithMessage, OpVectorShuffleVector2ComponentType) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %int = OpTypeInt 32 0
 %ivec3 = OpTypeVector %int 3
@@ -4673,11 +4919,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("The Component Type of Vector 2 must be the same as "
-                        "ResultType."));
+              HasSubstr(make_message(
+                  "The Component Type of Vector 2 must be the same as "
+                  "ResultType.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpVectorShuffleLiterals) {
+TEST_P(ValidateIdWithMessage, OpVectorShuffleLiterals) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %float = OpTypeFloat 32
 %vec2 = OpTypeVector %float 2
@@ -4703,9 +4950,9 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
+      HasSubstr(make_message(
           "Component index 8 is out of bounds for combined (Vector1 + Vector2) "
-          "size of 5."));
+          "size of 5.")));
 }
 
 // TODO: OpCompositeConstruct
@@ -4792,7 +5039,7 @@
 // TODO: OpSelectionMerge
 // TODO: OpBranch
 
-TEST_F(ValidateIdWithMessage, OpPhiNotAType) {
+TEST_P(ValidateIdWithMessage, OpPhiNotAType) {
   std::string spirv = kOpenCLMemoryModel32 + R"(
 %2 = OpTypeBool
 %3 = OpConstantTrue %2
@@ -4809,11 +5056,12 @@
 
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 3[%true] is not a type "
-                                               "id"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("ID '3[%true]' is not a type "
+                                     "id")));
 }
 
-TEST_F(ValidateIdWithMessage, OpPhiSamePredecessor) {
+TEST_P(ValidateIdWithMessage, OpPhiSamePredecessor) {
   std::string spirv = kOpenCLMemoryModel32 + R"(
 %2 = OpTypeBool
 %3 = OpConstantTrue %2
@@ -4832,7 +5080,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpPhiOddArgumentNumber) {
+TEST_P(ValidateIdWithMessage, OpPhiOddArgumentNumber) {
   std::string spirv = kOpenCLMemoryModel32 + R"(
 %2 = OpTypeBool
 %3 = OpConstantTrue %2
@@ -4849,12 +5097,13 @@
 
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpPhi does not have an equal number of incoming "
-                        "values and basic blocks."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpPhi does not have an equal number of incoming "
+                             "values and basic blocks.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpPhiTooFewPredecessors) {
+TEST_P(ValidateIdWithMessage, OpPhiTooFewPredecessors) {
   std::string spirv = kOpenCLMemoryModel32 + R"(
 %2 = OpTypeBool
 %3 = OpConstantTrue %2
@@ -4872,11 +5121,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpPhi's number of incoming blocks (0) does not match "
-                        "block's predecessor count (1)."));
+              HasSubstr(make_message(
+                  "OpPhi's number of incoming blocks (0) does not match "
+                  "block's predecessor count (1).")));
 }
 
-TEST_F(ValidateIdWithMessage, OpPhiTooManyPredecessors) {
+TEST_P(ValidateIdWithMessage, OpPhiTooManyPredecessors) {
   std::string spirv = kOpenCLMemoryModel32 + R"(
 %2 = OpTypeBool
 %3 = OpConstantTrue %2
@@ -4896,11 +5146,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpPhi's number of incoming blocks (2) does not match "
-                        "block's predecessor count (1)."));
+              HasSubstr(make_message(
+                  "OpPhi's number of incoming blocks (2) does not match "
+                  "block's predecessor count (1).")));
 }
 
-TEST_F(ValidateIdWithMessage, OpPhiMismatchedTypes) {
+TEST_P(ValidateIdWithMessage, OpPhiMismatchedTypes) {
   std::string spirv = kOpenCLMemoryModel32 + R"(
 %2 = OpTypeBool
 %3 = OpConstantTrue %2
@@ -4922,12 +5173,13 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpPhi's result type <id> 2[%bool] does not match "
-                        "incoming value <id> 6[%uint_0] type <id> "
-                        "5[%uint]."));
+              HasSubstr(make_message(
+                  "OpPhi's result type <id> '2[%bool]' does not match "
+                  "incoming value <id> '6[%uint_0]' type <id> "
+                  "'5[%uint]'.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpPhiPredecessorNotABlock) {
+TEST_P(ValidateIdWithMessage, OpPhiPredecessorNotABlock) {
   std::string spirv = kOpenCLMemoryModel32 + R"(
 %2 = OpTypeBool
 %3 = OpConstantTrue %2
@@ -4949,11 +5201,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpPhi's incoming basic block <id> 3[%true] is not an "
-                        "OpLabel."));
+              HasSubstr(make_message(
+                  "OpPhi's incoming basic block <id> '3[%true]' is not an "
+                  "OpLabel.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpPhiNotAPredecessor) {
+TEST_P(ValidateIdWithMessage, OpPhiNotAPredecessor) {
   std::string spirv = kOpenCLMemoryModel32 + R"(
 %2 = OpTypeBool
 %3 = OpConstantTrue %2
@@ -4975,11 +5228,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpPhi's incoming basic block <id> 9[%9] is not a "
-                        "predecessor of <id> 8[%8]."));
+              HasSubstr(make_message(
+                  "OpPhi's incoming basic block <id> '9[%9]' is not a "
+                  "predecessor of <id> '8[%8]'.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpBranchConditionalGood) {
+TEST_P(ValidateIdWithMessage, OpBranchConditionalGood) {
   std::string spirv = BranchConditionalSetup + R"(
     %branch_cond = OpINotEqual %bool %i0 %i1
                    OpSelectionMerge %end None
@@ -4990,7 +5244,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
 }
 
-TEST_F(ValidateIdWithMessage, OpBranchConditionalWithWeightsGood) {
+TEST_P(ValidateIdWithMessage, OpBranchConditionalWithWeightsGood) {
   std::string spirv = BranchConditionalSetup + R"(
     %branch_cond = OpINotEqual %bool %i0 %i1
                    OpSelectionMerge %end None
@@ -5001,7 +5255,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
 }
 
-TEST_F(ValidateIdWithMessage, OpBranchConditional_CondIsScalarInt) {
+TEST_P(ValidateIdWithMessage, OpBranchConditional_CondIsScalarInt) {
   std::string spirv = BranchConditionalSetup + R"(
                    OpSelectionMerge %end None
                    OpBranchConditional %i0 %target_t %target_f
@@ -5011,11 +5265,11 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
-          "Condition operand for OpBranchConditional must be of boolean type"));
+      HasSubstr(make_message("Condition operand for OpBranchConditional must "
+                             "be of boolean type")));
 }
 
-TEST_F(ValidateIdWithMessage, OpBranchConditional_TrueTargetIsNotLabel) {
+TEST_P(ValidateIdWithMessage, OpBranchConditional_TrueTargetIsNotLabel) {
   std::string spirv = BranchConditionalSetup + R"(
                    OpSelectionMerge %end None
                    OpBranchConditional %true %i0 %target_f
@@ -5024,11 +5278,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("The 'True Label' operand for OpBranchConditional must "
-                        "be the ID of an OpLabel instruction"));
+              HasSubstr(make_message(
+                  "The 'True Label' operand for OpBranchConditional must "
+                  "be the ID of an OpLabel instruction")));
 }
 
-TEST_F(ValidateIdWithMessage, OpBranchConditional_FalseTargetIsNotLabel) {
+TEST_P(ValidateIdWithMessage, OpBranchConditional_FalseTargetIsNotLabel) {
   std::string spirv = BranchConditionalSetup + R"(
                    OpSelectionMerge %end None
                    OpBranchConditional %true %target_t %i0
@@ -5037,11 +5292,12 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("The 'False Label' operand for OpBranchConditional "
-                        "must be the ID of an OpLabel instruction"));
+              HasSubstr(make_message(
+                  "The 'False Label' operand for OpBranchConditional "
+                  "must be the ID of an OpLabel instruction")));
 }
 
-TEST_F(ValidateIdWithMessage, OpBranchConditional_NotEnoughWeights) {
+TEST_P(ValidateIdWithMessage, OpBranchConditional_NotEnoughWeights) {
   std::string spirv = BranchConditionalSetup + R"(
     %branch_cond = OpINotEqual %bool %i0 %i1
                    OpSelectionMerge %end None
@@ -5050,12 +5306,12 @@
 
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpBranchConditional requires either 3 or 5 parameters"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpBranchConditional requires either 3 or 5 parameters")));
 }
 
-TEST_F(ValidateIdWithMessage, OpBranchConditional_TooManyWeights) {
+TEST_P(ValidateIdWithMessage, OpBranchConditional_TooManyWeights) {
   std::string spirv = BranchConditionalSetup + R"(
     %branch_cond = OpINotEqual %bool %i0 %i1
                    OpSelectionMerge %end None
@@ -5064,25 +5320,26 @@
 
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpBranchConditional requires either 3 or 5 parameters"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpBranchConditional requires either 3 or 5 parameters")));
 }
 
-TEST_F(ValidateIdWithMessage, OpBranchConditional_ConditionIsAType) {
+TEST_P(ValidateIdWithMessage, OpBranchConditional_ConditionIsAType) {
   std::string spirv = BranchConditionalSetup + R"(
 OpBranchConditional %bool %target_t %target_f
 )" + BranchConditionalTail;
 
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 3[%bool] cannot be a "
-                                               "type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("Operand '3[%bool]' cannot be a "
+                                     "type")));
 }
 
 // TODO: OpSwitch
 
-TEST_F(ValidateIdWithMessage, OpReturnValueConstantGood) {
+TEST_P(ValidateIdWithMessage, OpReturnValueConstantGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -5096,7 +5353,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpReturnValueVariableGood) {
+TEST_P(ValidateIdWithMessage, OpReturnValueVariableGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0 ;10
@@ -5113,7 +5370,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpReturnValueExpressionGood) {
+TEST_P(ValidateIdWithMessage, OpReturnValueExpressionGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -5128,7 +5385,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpReturnValueIsType) {
+TEST_P(ValidateIdWithMessage, OpReturnValueIsType) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -5139,11 +5396,12 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 1[%void] cannot be a "
-                                               "type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("Operand '1[%void]' cannot be a "
+                                     "type")));
 }
 
-TEST_F(ValidateIdWithMessage, OpReturnValueIsLabel) {
+TEST_P(ValidateIdWithMessage, OpReturnValueIsLabel) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -5155,10 +5413,10 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 5[%5] requires a type"));
+              HasSubstr(make_message("Operand '5[%5]' requires a type")));
 }
 
-TEST_F(ValidateIdWithMessage, OpReturnValueIsVoid) {
+TEST_P(ValidateIdWithMessage, OpReturnValueIsVoid) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -5170,13 +5428,13 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpReturnValue value's type <id> '1[%void]' is missing or "
-                "void."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpReturnValue value's type <id> '1[%void]' is missing or "
+                  "void.")));
 }
 
-TEST_F(ValidateIdWithMessage, OpReturnValueIsVariableInPhysical) {
+TEST_P(ValidateIdWithMessage, OpReturnValueIsVariableInPhysical) {
   // It's valid to return a pointer in a physical addressing model.
   std::string spirv = kOpCapabilitySetup + R"(
      OpMemoryModel Physical32 OpenCL
@@ -5193,7 +5451,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpReturnValueIsVariableInLogical) {
+TEST_P(ValidateIdWithMessage, OpReturnValueIsVariableInLogical) {
   // It's invalid to return a pointer in a physical addressing model.
   std::string spirv = kOpCapabilitySetup + R"(
      OpMemoryModel Logical GLSL450
@@ -5208,15 +5466,16 @@
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpReturnValue value's type <id> "
-                        "'3[%_ptr_Function_uint]' is a pointer, which is "
-                        "invalid in the Logical addressing model."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("OpReturnValue value's type <id> "
+                             "'3[%_ptr_Function_uint]' is a pointer, which is "
+                             "invalid in the Logical addressing model.")));
 }
 
 // With the VariablePointer Capability, the return value of a function is
 // allowed to be a pointer.
-TEST_F(ValidateIdWithMessage, OpReturnValueVarPtrGood) {
+TEST_P(ValidateIdWithMessage, OpReturnValueVarPtrGood) {
   std::ostringstream spirv;
   createVariablePointerSpirvProgram(&spirv,
                                     "" /* Instructions to add to "main" */,
@@ -5230,7 +5489,7 @@
 // *not* allowed to be a pointer.
 // Disabled since using OpSelect with pointers without VariablePointers will
 // fail LogicalsPass.
-TEST_F(ValidateIdWithMessage, DISABLED_OpReturnValueVarPtrBad) {
+TEST_P(ValidateIdWithMessage, DISABLED_OpReturnValueVarPtrBad) {
   std::ostringstream spirv;
   createVariablePointerSpirvProgram(&spirv,
                                     "" /* Instructions to add to "main" */,
@@ -5239,13 +5498,14 @@
   CompileSuccessfully(spirv.str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpReturnValue value's type <id> '7' is a pointer, "
-                        "which is invalid in the Logical addressing model."));
+              HasSubstr(make_message(
+                  "OpReturnValue value's type <id> '7' is a pointer, "
+                  "which is invalid in the Logical addressing model.")));
 }
 
 // TODO: enable when this bug is fixed:
 // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
-TEST_F(ValidateIdWithMessage, DISABLED_OpReturnValueIsFunction) {
+TEST_P(ValidateIdWithMessage, DISABLED_OpReturnValueIsFunction) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeInt 32 0
@@ -5258,17 +5518,18 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, UndefinedTypeId) {
+TEST_P(ValidateIdWithMessage, UndefinedTypeId) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %s = OpTypeStruct %i32
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 2[%2] requires a previous definition"));
+              HasSubstr(make_message(
+                  "Operand '2[%2]' requires a previous definition")));
 }
 
-TEST_F(ValidateIdWithMessage, UndefinedIdScope) {
+TEST_P(ValidateIdWithMessage, UndefinedIdScope) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %u32    = OpTypeInt 32 0
 %memsem = OpConstant %u32 0
@@ -5282,11 +5543,12 @@
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 7[%7] has not been "
-                                               "defined"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("ID '7[%7]' has not been "
+                                     "defined")));
 }
 
-TEST_F(ValidateIdWithMessage, UndefinedIdMemSem) {
+TEST_P(ValidateIdWithMessage, UndefinedIdMemSem) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %u32    = OpTypeInt 32 0
 %scope  = OpConstant %u32 0
@@ -5300,11 +5562,12 @@
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 7[%7] has not been "
-                                               "defined"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("ID '7[%7]' has not been "
+                                     "defined")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        KernelOpEntryPointAndOpInBoundsPtrAccessChainGood) {
   std::string spirv = kOpenCLMemoryModel32 + R"(
       OpEntryPoint Kernel %2 "simple_kernel"
@@ -5337,7 +5600,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpPtrAccessChainGood) {
+TEST_P(ValidateIdWithMessage, OpPtrAccessChainGood) {
   std::string spirv = kOpenCLMemoryModel64 + R"(
       OpEntryPoint Kernel %2 "another_kernel"
       OpSource OpenCL_C 200000
@@ -5372,7 +5635,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, StgBufOpPtrAccessChainGood) {
+TEST_P(ValidateIdWithMessage, StgBufOpPtrAccessChainGood) {
   std::string spirv = R"(
      OpCapability Shader
      OpCapability Linkage
@@ -5380,6 +5643,7 @@
      OpExtension "SPV_KHR_variable_pointers"
      OpMemoryModel Logical GLSL450
      OpEntryPoint GLCompute %3 ""
+     OpDecorate %ptr ArrayStride 8
 %int = OpTypeInt 32 0
 %int_2 = OpConstant %int 2
 %int_4 = OpConstant %int 4
@@ -5399,7 +5663,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-TEST_F(ValidateIdWithMessage, OpLoadBitcastPointerGood) {
+TEST_P(ValidateIdWithMessage, OpLoadBitcastPointerGood) {
   std::string spirv = kOpenCLMemoryModel64 + R"(
 %2  = OpTypeVoid
 %3  = OpTypeInt 32 0
@@ -5417,7 +5681,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpLoadBitcastNonPointerBad) {
+TEST_P(ValidateIdWithMessage, OpLoadBitcastNonPointerBad) {
   std::string spirv = kOpenCLMemoryModel64 + R"(
 %2  = OpTypeVoid
 %3  = OpTypeInt 32 0
@@ -5434,12 +5698,12 @@
       OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpLoad type for pointer <id> '11[%11]' is not a pointer "
-                "type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpLoad type for pointer <id> '11[%11]' is not a pointer "
+                  "type.")));
 }
-TEST_F(ValidateIdWithMessage, OpStoreBitcastPointerGood) {
+TEST_P(ValidateIdWithMessage, OpStoreBitcastPointerGood) {
   std::string spirv = kOpenCLMemoryModel64 + R"(
 %2  = OpTypeVoid
 %3  = OpTypeInt 32 0
@@ -5458,7 +5722,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
-TEST_F(ValidateIdWithMessage, OpStoreBitcastNonPointerBad) {
+TEST_P(ValidateIdWithMessage, OpStoreBitcastNonPointerBad) {
   std::string spirv = kOpenCLMemoryModel64 + R"(
 %2  = OpTypeVoid
 %3  = OpTypeInt 32 0
@@ -5475,15 +5739,15 @@
       OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("OpStore type for pointer <id> '11[%11]' is not a pointer "
-                "type."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "OpStore type for pointer <id> '11[%11]' is not a pointer "
+                  "type.")));
 }
 
 // Result <id> resulting from an instruction within a function may not be used
 // outside that function.
-TEST_F(ValidateIdWithMessage, ResultIdUsedOutsideOfFunctionBad) {
+TEST_P(ValidateIdWithMessage, ResultIdUsedOutsideOfFunctionBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1
@@ -5502,14 +5766,13 @@
   )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "ID 7[%7] defined in block 6[%6] does not dominate its use in block "
-          "9[%9]"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("ID '7[%7]' defined in block '6[%6]' does "
+                                     "not dominate its use in block "
+                                     "'9[%9]'")));
 }
 
-TEST_F(ValidateIdWithMessage, SpecIdTargetNotSpecializationConstant) {
+TEST_P(ValidateIdWithMessage, SpecIdTargetNotSpecializationConstant) {
   std::string spirv = kGLSL450MemoryModel + R"(
 OpDecorate %1 SpecId 200
 %void = OpTypeVoid
@@ -5523,13 +5786,14 @@
   )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("SpecId decoration on target <id> "
-                        "'1[%uint_3]' must be a scalar specialization "
-                        "constant"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("SpecId decoration on target <id> "
+                             "'1[%uint_3]' must be a scalar specialization "
+                             "constant")));
 }
 
-TEST_F(ValidateIdWithMessage, SpecIdTargetOpSpecConstantOpBad) {
+TEST_P(ValidateIdWithMessage, SpecIdTargetOpSpecConstantOpBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 OpDecorate %1 SpecId 200
 %void = OpTypeVoid
@@ -5545,12 +5809,13 @@
   )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("SpecId decoration on target <id> '1[%1]' "
-                        "must be a scalar specialization constant"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("SpecId decoration on target <id> '1[%1]' "
+                             "must be a scalar specialization constant")));
 }
 
-TEST_F(ValidateIdWithMessage, SpecIdTargetOpSpecConstantCompositeBad) {
+TEST_P(ValidateIdWithMessage, SpecIdTargetOpSpecConstantCompositeBad) {
   std::string spirv = kGLSL450MemoryModel + R"(
 OpDecorate %1 SpecId 200
 %void = OpTypeVoid
@@ -5565,12 +5830,13 @@
   )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("SpecId decoration on target <id> '1[%1]' "
-                        "must be a scalar specialization constant"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("SpecId decoration on target <id> '1[%1]' "
+                             "must be a scalar specialization constant")));
 }
 
-TEST_F(ValidateIdWithMessage, SpecIdTargetGood) {
+TEST_P(ValidateIdWithMessage, SpecIdTargetGood) {
   std::string spirv = kGLSL450MemoryModel + R"(
 OpDecorate %3 SpecId 200
 OpDecorate %4 SpecId 201
@@ -5591,7 +5857,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
 }
 
-TEST_F(ValidateIdWithMessage, CorrectErrorForShuffle) {
+TEST_P(ValidateIdWithMessage, CorrectErrorForShuffle) {
   std::string spirv = kGLSL450MemoryModel + R"(
    %uint = OpTypeInt 32 0
   %float = OpTypeFloat 32
@@ -5612,13 +5878,13 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
+      HasSubstr(make_message(
           "Component index 4 is out of bounds for combined (Vector1 + Vector2) "
-          "size of 4."));
+          "size of 4.")));
   EXPECT_EQ(25, getErrorPosition().index);
 }
 
-TEST_F(ValidateIdWithMessage, VoidStructMember) {
+TEST_P(ValidateIdWithMessage, VoidStructMember) {
   const std::string spirv = kGLSL450MemoryModel + R"(
 %void = OpTypeVoid
 %struct = OpTypeStruct %void
@@ -5626,11 +5892,12 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Structures cannot contain a void type."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("Structures cannot contain a void type.")));
 }
 
-TEST_F(ValidateIdWithMessage, TypeFunctionBadUse) {
+TEST_P(ValidateIdWithMessage, TypeFunctionBadUse) {
   std::string spirv = kGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1
@@ -5643,10 +5910,11 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Invalid use of function type result id 2[%2]."));
+              HasSubstr(make_message(
+                  "Invalid use of function type result id '2[%2]'.")));
 }
 
-TEST_F(ValidateIdWithMessage, BadTypeId) {
+TEST_P(ValidateIdWithMessage, BadTypeId) {
   std::string spirv = kGLSL450MemoryModel + R"(
           %1 = OpTypeVoid
           %2 = OpTypeFunction %1
@@ -5661,11 +5929,12 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 4[%float_0] is not a type "
-                                               "id"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("ID '4[%float_0]' is not a type "
+                                     "id")));
 }
 
-TEST_F(ValidateIdWithMessage, VulkanMemoryModelLoadMakePointerVisibleGood) {
+TEST_P(ValidateIdWithMessage, VulkanMemoryModelLoadMakePointerVisibleGood) {
   std::string spirv = R"(
 OpCapability Shader
 OpCapability VulkanMemoryModelKHR
@@ -5689,7 +5958,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelLoadMakePointerVisibleMissingNonPrivatePointer) {
   std::string spirv = R"(
 OpCapability Shader
@@ -5712,12 +5981,13 @@
 
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR must be specified if "
-                        "MakePointerVisibleKHR is specified."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
+                             "MakePointerVisibleKHR is specified.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelLoadNonPrivatePointerBadStorageClass) {
   std::string spirv = R"(
 OpCapability Shader
@@ -5741,12 +6011,13 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, "
-                        "Workgroup, CrossWorkgroup, Generic, Image or "
-                        "StorageBuffer storage classes."));
+              HasSubstr(make_message(
+                  "NonPrivatePointerKHR requires a pointer in Uniform, "
+                  "Workgroup, CrossWorkgroup, Generic, Image or "
+                  "StorageBuffer storage classes.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelLoadMakePointerAvailableCannotBeUsed) {
   std::string spirv = R"(
 OpCapability Shader
@@ -5770,10 +6041,11 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("MakePointerAvailableKHR cannot be used with OpLoad"));
+              HasSubstr(make_message(
+                  "MakePointerAvailableKHR cannot be used with OpLoad")));
 }
 
-TEST_F(ValidateIdWithMessage, VulkanMemoryModelStoreMakePointerAvailableGood) {
+TEST_P(ValidateIdWithMessage, VulkanMemoryModelStoreMakePointerAvailableGood) {
   std::string spirv = R"(
 OpCapability Shader
 OpCapability VulkanMemoryModelKHR
@@ -5797,7 +6069,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelStoreMakePointerAvailableMissingNonPrivatePointer) {
   std::string spirv = R"(
 OpCapability Shader
@@ -5820,12 +6092,13 @@
 
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR must be specified if "
-                        "MakePointerAvailableKHR is specified."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
+                             "MakePointerAvailableKHR is specified.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelStoreNonPrivatePointerBadStorageClass) {
   std::string spirv = R"(
 OpCapability Shader
@@ -5849,12 +6122,13 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, "
-                        "Workgroup, CrossWorkgroup, Generic, Image or "
-                        "StorageBuffer storage classes."));
+              HasSubstr(make_message(
+                  "NonPrivatePointerKHR requires a pointer in Uniform, "
+                  "Workgroup, CrossWorkgroup, Generic, Image or "
+                  "StorageBuffer storage classes.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelStoreMakePointerVisibleCannotBeUsed) {
   std::string spirv = R"(
 OpCapability Shader
@@ -5878,10 +6152,11 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("MakePointerVisibleKHR cannot be used with OpStore."));
+              HasSubstr(make_message(
+                  "MakePointerVisibleKHR cannot be used with OpStore.")));
 }
 
-TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailable) {
+TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailable) {
   std::string spirv = R"(
 OpCapability Shader
 OpCapability Linkage
@@ -5908,7 +6183,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryVisible) {
+TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryVisible) {
   std::string spirv = R"(
 OpCapability Shader
 OpCapability Linkage
@@ -5935,7 +6210,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailableAndVisible) {
+TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailableAndVisible) {
   std::string spirv = R"(
 OpCapability Shader
 OpCapability Linkage
@@ -5962,7 +6237,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelCopyMemoryAvailableMissingNonPrivatePointer) {
   std::string spirv = R"(
 OpCapability Shader
@@ -5988,12 +6263,13 @@
 
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR must be specified if "
-                        "MakePointerAvailableKHR is specified."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
+                             "MakePointerAvailableKHR is specified.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelCopyMemoryVisibleMissingNonPrivatePointer) {
   std::string spirv = R"(
 OpCapability Shader
@@ -6019,12 +6295,13 @@
 
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR must be specified if "
-                        "MakePointerVisibleKHR is specified."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
+                             "MakePointerVisibleKHR is specified.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelCopyMemoryAvailableBadStorageClass) {
   std::string spirv = R"(
 OpCapability Shader
@@ -6051,12 +6328,13 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, "
-                        "Workgroup, CrossWorkgroup, Generic, Image or "
-                        "StorageBuffer storage classes."));
+              HasSubstr(make_message(
+                  "NonPrivatePointerKHR requires a pointer in Uniform, "
+                  "Workgroup, CrossWorkgroup, Generic, Image or "
+                  "StorageBuffer storage classes.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelCopyMemoryVisibleBadStorageClass) {
   std::string spirv = R"(
 OpCapability Shader
@@ -6083,12 +6361,13 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, "
-                        "Workgroup, CrossWorkgroup, Generic, Image or "
-                        "StorageBuffer storage classes."));
+              HasSubstr(make_message(
+                  "NonPrivatePointerKHR requires a pointer in Uniform, "
+                  "Workgroup, CrossWorkgroup, Generic, Image or "
+                  "StorageBuffer storage classes.")));
 }
 
-TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedAvailable) {
+TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedAvailable) {
   std::string spirv = R"(
 OpCapability Shader
 OpCapability Linkage
@@ -6116,7 +6395,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedVisible) {
+TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedVisible) {
   std::string spirv = R"(
 OpCapability Shader
 OpCapability Linkage
@@ -6144,7 +6423,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelCopyMemorySizedAvailableAndVisible) {
   std::string spirv = R"(
 OpCapability Shader
@@ -6173,7 +6452,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelCopyMemorySizedAvailableMissingNonPrivatePointer) {
   std::string spirv = R"(
 OpCapability Shader
@@ -6200,12 +6479,13 @@
 
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR must be specified if "
-                        "MakePointerAvailableKHR is specified."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
+                             "MakePointerAvailableKHR is specified.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelCopyMemorySizedVisibleMissingNonPrivatePointer) {
   std::string spirv = R"(
 OpCapability Shader
@@ -6232,12 +6512,13 @@
 
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR must be specified if "
-                        "MakePointerVisibleKHR is specified."));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
+                             "MakePointerVisibleKHR is specified.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelCopyMemorySizedAvailableBadStorageClass) {
   std::string spirv = R"(
 OpCapability Shader
@@ -6265,12 +6546,13 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, "
-                        "Workgroup, CrossWorkgroup, Generic, Image or "
-                        "StorageBuffer storage classes."));
+              HasSubstr(make_message(
+                  "NonPrivatePointerKHR requires a pointer in Uniform, "
+                  "Workgroup, CrossWorkgroup, Generic, Image or "
+                  "StorageBuffer storage classes.")));
 }
 
-TEST_F(ValidateIdWithMessage,
+TEST_P(ValidateIdWithMessage,
        VulkanMemoryModelCopyMemorySizedVisibleBadStorageClass) {
   std::string spirv = R"(
 OpCapability Shader
@@ -6298,12 +6580,13 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("NonPrivatePointerKHR requires a pointer in Uniform, "
-                        "Workgroup, CrossWorkgroup, Generic, Image or "
-                        "StorageBuffer storage classes."));
+              HasSubstr(make_message(
+                  "NonPrivatePointerKHR requires a pointer in Uniform, "
+                  "Workgroup, CrossWorkgroup, Generic, Image or "
+                  "StorageBuffer storage classes.")));
 }
 
-TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock1) {
+TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock1) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1
@@ -6325,11 +6608,12 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ID 8[%8] defined in block 7[%7] does not dominate its "
-                        "use in block 10[%10]\n  %10 = OpLabel"));
+              HasSubstr(make_message(
+                  "ID '8[%8]' defined in block '7[%7]' does not dominate its "
+                  "use in block '10[%10]'\n  %10 = OpLabel")));
 }
 
-TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock2) {
+TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock2) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1
@@ -6351,11 +6635,12 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ID 8[%8] defined in block 7[%7] does not dominate its "
-                        "use in block 10[%10]\n  %10 = OpLabel"));
+              HasSubstr(make_message(
+                  "ID '8[%8]' defined in block '7[%7]' does not dominate its "
+                  "use in block '10[%10]'\n  %10 = OpLabel")));
 }
 
-TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock3) {
+TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock3) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1
@@ -6377,11 +6662,12 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ID 8[%8] defined in block 7[%7] does not dominate its "
-                        "use in block 10[%10]\n  %10 = OpLabel"));
+              HasSubstr(make_message(
+                  "ID '8[%8]' defined in block '7[%7]' does not dominate its "
+                  "use in block '10[%10]'\n  %10 = OpLabel")));
 }
 
-TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock4) {
+TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock4) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1
@@ -6401,7 +6687,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock5) {
+TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock5) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1
@@ -6423,7 +6709,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage, IdDefInUnreachableBlock6) {
+TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock6) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1
@@ -6444,11 +6730,12 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ID 9[%9] defined in block 8[%8] does not dominate its "
-                        "use in block 7[%7]\n  %7 = OpLabel"));
+              HasSubstr(make_message(
+                  "ID '9[%9]' defined in block '8[%8]' does not dominate its "
+                  "use in block '7[%7]'\n  %7 = OpLabel")));
 }
 
-TEST_F(ValidateIdWithMessage, ReachableDefUnreachableUse) {
+TEST_P(ValidateIdWithMessage, ReachableDefUnreachableUse) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
 %1 = OpTypeVoid
 %2 = OpTypeFunction %1
@@ -6468,7 +6755,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
-TEST_F(ValidateIdWithMessage, UnreachableDefUsedInPhi) {
+TEST_P(ValidateIdWithMessage, UnreachableDefUsedInPhi) {
   const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
        %void = OpTypeVoid
           %3 = OpTypeFunction %void
@@ -6496,12 +6783,13 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("In OpPhi instruction 14[%14], ID 13[%13] definition does not "
-                "dominate its parent 7[%7]\n  %14 = OpPhi %float %11 %10 %13 "
-                "%7"));
+      HasSubstr(make_message(
+          "In OpPhi instruction '14[%14]', ID '13[%13]' definition does not "
+          "dominate its parent '7[%7]'\n  %14 = OpPhi %float %11 %10 %13 "
+          "%7")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeForwardPointerNotAPointerType) {
+TEST_P(ValidateIdWithMessage, OpTypeForwardPointerNotAPointerType) {
   std::string spirv = R"(
      OpCapability GenericPointer
      OpCapability VariablePointersStorageBuffer
@@ -6520,11 +6808,12 @@
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Pointer type in OpTypeForwardPointer is not a pointer "
-                        "type.\n  OpTypeForwardPointer %void CrossWorkgroup"));
+              HasSubstr(make_message(
+                  "Pointer type in OpTypeForwardPointer is not a pointer "
+                  "type.\n  OpTypeForwardPointer %void CrossWorkgroup")));
 }
 
-TEST_F(ValidateIdWithMessage, OpTypeForwardPointerWrongStorageClass) {
+TEST_P(ValidateIdWithMessage, OpTypeForwardPointerWrongStorageClass) {
   std::string spirv = R"(
      OpCapability GenericPointer
      OpCapability VariablePointersStorageBuffer
@@ -6544,14 +6833,14 @@
 
   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Storage class in OpTypeForwardPointer does not match the "
-                "pointer definition.\n  OpTypeForwardPointer "
-                "%_ptr_Function_int CrossWorkgroup"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message(
+                  "Storage class in OpTypeForwardPointer does not match the "
+                  "pointer definition.\n  OpTypeForwardPointer "
+                  "%_ptr_Function_int CrossWorkgroup")));
 }
 
-TEST_F(ValidateIdWithMessage, MissingForwardPointer) {
+TEST_P(ValidateIdWithMessage, MissingForwardPointer) {
   const std::string spirv = R"(
                OpCapability Linkage
                OpCapability Shader
@@ -6564,13 +6853,12 @@
 
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "Operand 3[%_ptr_Uniform__struct_2] requires a previous definition"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(make_message("Operand '3[%_ptr_Uniform__struct_2]' "
+                                     "requires a previous definition")));
 }
 
-TEST_F(ValidateIdWithMessage, NVBindlessSamplerInStruct) {
+TEST_P(ValidateIdWithMessage, NVBindlessSamplerInStruct) {
   std::string spirv = R"(
             OpCapability Shader
             OpCapability BindlessTextureNV
@@ -6599,6 +6887,8 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
+INSTANTIATE_TEST_SUITE_P(, ValidateIdWithMessage, ::testing::Bool());
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_image_test.cpp b/third_party/SPIRV-Tools/test/val/val_image_test.cpp
index c4de60a..a97ef7c 100644
--- a/third_party/SPIRV-Tools/test/val/val_image_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_image_test.cpp
@@ -149,6 +149,7 @@
 %u32vec4 = OpTypeVector %u32 4
 %s32vec4 = OpTypeVector %s32 4
 %f32vec4 = OpTypeVector %f32 4
+%boolvec4 = OpTypeVector %bool 4
 
 %f32_0 = OpConstant %f32 0
 %f32_1 = OpConstant %f32 1
@@ -175,6 +176,8 @@
 %u64_0 = OpConstant %u64 0
 %u64_1 = OpConstant %u64 1
 
+%bool_t = OpConstantTrue %bool
+
 %u32vec2arr4 = OpTypeArray %u32vec2 %u32_4
 %u32vec2arr3 = OpTypeArray %u32vec2 %u32_3
 %u32arr4 = OpTypeArray %u32 %u32_4
@@ -217,6 +220,8 @@
 
 %f32vec4_0000 = OpConstantComposite %f32vec4 %f32_0 %f32_0 %f32_0 %f32_0
 
+%boolvec4_tttt = OpConstantComposite %boolvec4 %bool_t %bool_t %bool_t %bool_t
+
 %const_offsets = OpConstantComposite %u32vec2arr4 %u32vec2_01 %u32vec2_12 %u32vec2_01 %u32vec2_12
 %const_offsets3x2 = OpConstantComposite %u32vec2arr3 %u32vec2_01 %u32vec2_12 %u32vec2_01
 %const_offsets4xu = OpConstantComposite %u32arr4 %u32_0 %u32_0 %u32_0 %u32_0
@@ -1120,8 +1125,9 @@
 
   CompileSuccessfully(GenerateShaderCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 145[%145] cannot be a "
-                                               "type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Operand '148[%148]' cannot be a "
+                        "type"));
 }
 
 TEST_F(ValidateImage, ImageTexelPointerImageNotImage) {
@@ -3746,6 +3752,17 @@
                         "but given only 1"));
 }
 
+TEST_F(ValidateImage, WriteTexelScalarSuccess) {
+  const std::string body = R"(
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
+OpImageWrite %img %u32vec2_01 %u32_2
+)";
+
+  const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
+  CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
 TEST_F(ValidateImage, WriteTexelWrongType) {
   const std::string body = R"(
 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
@@ -3759,17 +3776,17 @@
               HasSubstr("Expected Texel to be int or float vector or scalar"));
 }
 
-TEST_F(ValidateImage, DISABLED_WriteTexelNotVector4) {
+TEST_F(ValidateImage, WriteTexelNonNumericalType) {
   const std::string body = R"(
 %img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
-OpImageWrite %img %u32vec2_01 %u32vec3_012
+OpImageWrite %img %u32vec2_01 %boolvec4_tttt
 )";
 
   const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
   CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Expected Texel to have 4 components"));
+              HasSubstr("Expected Texel to be int or float vector or scalar"));
 }
 
 TEST_F(ValidateImage, WriteTexelWrongComponentType) {
diff --git a/third_party/SPIRV-Tools/test/val/val_interfaces_test.cpp b/third_party/SPIRV-Tools/test/val/val_interfaces_test.cpp
index d9c3748..1756528 100644
--- a/third_party/SPIRV-Tools/test/val/val_interfaces_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_interfaces_test.cpp
@@ -217,7 +217,7 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("Non-unique OpEntryPoint interface 2[%var] is disallowed"));
+      HasSubstr("Non-unique OpEntryPoint interface '2[%var]' is disallowed"));
 }
 
 TEST_F(ValidateInterfacesTest, MissingGlobalVarSPV1p3) {
@@ -1456,7 +1456,7 @@
 OpMemberDecorate %struct 0 Location 0
 OpMemberDecorate %struct 0 Component 0
 OpMemberDecorate %struct 1 Location 0
-OpMemberDecorate %struct 1 Component 1
+OpMemberDecorate %struct 1 Component 2
 %void = OpTypeVoid
 %void_fn = OpTypeFunction %void
 %float = OpTypeFloat 32
diff --git a/third_party/SPIRV-Tools/test/val/val_memory_test.cpp b/third_party/SPIRV-Tools/test/val/val_memory_test.cpp
index ec1a000..d0735dc 100644
--- a/third_party/SPIRV-Tools/test/val/val_memory_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_memory_test.cpp
@@ -472,6 +472,55 @@
                 "= OpVariable %_ptr_Input_float Input %float_1\n"));
 }
 
+TEST_F(ValidateMemory, UniversalInitializerWithDisallowedStorageClassesBad) {
+  std::string spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %func "func"
+OpExecutionMode %func OriginUpperLeft
+%float = OpTypeFloat 32
+%float_ptr = OpTypePointer Input %float
+%init_val = OpConstant %float 1.0
+%1 = OpVariable %float_ptr Input %init_val
+%void = OpTypeVoid
+%functy = OpTypeFunction %void
+%func = OpFunction %void None %functy
+%2 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+  CompileSuccessfully(spirv.c_str(), SPV_ENV_UNIVERSAL_1_3);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpVariable, <id> '5[%5]', initializer are not allowed for Input"));
+}
+
+TEST_F(ValidateMemory, InitializerWithTaskPayloadWorkgroupEXT) {
+  std::string spirv = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TaskEXT %main "main" %payload
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+%_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
+     %uint_1 = OpConstant %uint 1
+    %payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT %uint_1
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+  CompileSuccessfully(spirv.c_str(), SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpVariable, <id> '2[%2]', initializer are not allowed "
+                        "for TaskPayloadWorkgroupEXT"));
+}
+
 TEST_F(ValidateMemory, ArrayLenCorrectResultType) {
   std::string spirv = R"(
                OpCapability Shader
@@ -644,7 +693,7 @@
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("The Struture's type in OpArrayLength <id> '11[%11]' "
+              HasSubstr("The Structure's type in OpArrayLength <id> '11[%11]' "
                         "must be a pointer to an OpTypeStruct."));
 }
 
@@ -674,7 +723,7 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("The Struture's last member in OpArrayLength <id> '11[%11]' "
+      HasSubstr("The Structure's last member in OpArrayLength <id> '11[%11]' "
                 "must be an OpTypeRuntimeArray.\n  %11 = OpArrayLength %uint "
                 "%10 0\n"));
 }
@@ -705,7 +754,7 @@
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("The Struture's last member in OpArrayLength <id> '11[%11]' "
+      HasSubstr("The Structure's last member in OpArrayLength <id> '11[%11]' "
                 "must be an OpTypeRuntimeArray.\n  %11 = OpArrayLength %uint "
                 "%10 1\n"));
 }
@@ -769,7 +818,7 @@
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
-          "The Struture's type in OpArrayLength <id> '12[%12]' must be a "
+          "The Structure's type in OpArrayLength <id> '12[%12]' must be a "
           "pointer to an OpTypeStruct.\n  %12 = OpArrayLength %uint %11 0\n"));
 }
 
@@ -793,8 +842,9 @@
 
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 4[%float] cannot be a "
-                                               "type"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Operand '4[%float]' cannot be a "
+                        "type"));
 }
 
 TEST_F(ValidateMemory, PushConstantNotStructGood) {
@@ -1602,7 +1652,7 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 1[%incorrect] requires a type"));
+              HasSubstr("Operand '1[%incorrect]' requires a type"));
 }
 
 TEST_F(ValidateMemory, PSBLoadAlignedSuccess) {
@@ -4662,6 +4712,224 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
+TEST_F(ValidateMemory, PtrAccessChainArrayStrideBad) {
+  const std::string spirv = R"(
+               OpCapability Shader
+               OpCapability VariablePointersStorageBuffer
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpExtension "SPV_KHR_variable_pointers"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "foo" %var
+               OpExecutionMode %main LocalSize 1 1 1
+               OpDecorate %var DescriptorSet 0
+               OpDecorate %var Binding 0
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+        %ptr = OpTypePointer StorageBuffer %uint
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+        %var = OpVariable %ptr StorageBuffer
+       %main = OpFunction %void None %func
+      %label = OpLabel
+     %access = OpAccessChain %ptr %var
+ %ptr_access = OpPtrAccessChain %ptr %access %uint_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpPtrAccessChain must have a Base whose type is "
+                        "decorated with ArrayStride"));
+}
+
+TEST_F(ValidateMemory, PtrAccessChainArrayStrideSuccess) {
+  const std::string spirv = R"(
+               OpCapability Shader
+               OpCapability VariablePointersStorageBuffer
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpExtension "SPV_KHR_variable_pointers"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "foo" %var
+               OpExecutionMode %main LocalSize 1 1 1
+               OpDecorate %var DescriptorSet 0
+               OpDecorate %var Binding 00
+               OpDecorate %ptr ArrayStride 4
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+        %ptr = OpTypePointer StorageBuffer %uint
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+        %var = OpVariable %ptr StorageBuffer
+       %main = OpFunction %void None %func
+      %label = OpLabel
+     %access = OpAccessChain %ptr %var
+ %ptr_access = OpPtrAccessChain %ptr %access %uint_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
+TEST_F(ValidateMemory, VulkanPtrAccessChainStorageBufferSuccess) {
+  const std::string spirv = R"(
+               OpCapability Shader
+               OpCapability VariablePointersStorageBuffer
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpExtension "SPV_KHR_variable_pointers"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "foo" %var
+               OpExecutionMode %main LocalSize 1 1 1
+               OpDecorate %_runtimearr_uint ArrayStride 4
+               OpMemberDecorate %_struct_10 0 Offset 0
+               OpDecorate %_struct_10 Block
+               OpDecorate %var DescriptorSet 0
+               OpDecorate %var Binding 0
+               OpDecorate %_ptr_StorageBuffer_uint ArrayStride 4
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+%_runtimearr_uint = OpTypeRuntimeArray %uint
+ %_struct_10 = OpTypeStruct %_runtimearr_uint
+%_ptr_StorageBuffer__struct_10 = OpTypePointer StorageBuffer %_struct_10
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+       %void = OpTypeVoid
+      %func2 = OpTypeFunction %void %_ptr_StorageBuffer_uint
+      %func1 = OpTypeFunction %void
+         %var = OpVariable %_ptr_StorageBuffer__struct_10 StorageBuffer
+     %called = OpFunction %void None %func2
+      %param = OpFunctionParameter %_ptr_StorageBuffer_uint
+     %label2 = OpLabel
+ %ptr_access = OpPtrAccessChain %_ptr_StorageBuffer_uint %param %uint_1
+               OpReturn
+               OpFunctionEnd
+       %main = OpFunction %void None %func1
+     %label1 = OpLabel
+     %access = OpAccessChain %_ptr_StorageBuffer_uint %var %uint_0 %uint_0
+       %call = OpFunctionCall %void %called %access
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+}
+
+TEST_F(ValidateMemory, VulkanPtrAccessChainStorageBufferCapability) {
+  const std::string spirv = R"(
+               OpCapability Shader
+               OpCapability PhysicalStorageBufferAddresses
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpExtension "SPV_KHR_variable_pointers"
+               OpMemoryModel PhysicalStorageBuffer64 GLSL450
+               OpEntryPoint GLCompute %main "foo" %var
+               OpExecutionMode %main LocalSize 1 1 1
+               OpDecorate %_runtimearr_uint ArrayStride 4
+               OpMemberDecorate %_struct_10 0 Offset 0
+               OpDecorate %_struct_10 Block
+               OpDecorate %var DescriptorSet 0
+               OpDecorate %var Binding 0
+               OpDecorate %_ptr_StorageBuffer_uint ArrayStride 4
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+%_runtimearr_uint = OpTypeRuntimeArray %uint
+ %_struct_10 = OpTypeStruct %_runtimearr_uint
+%_ptr_StorageBuffer__struct_10 = OpTypePointer StorageBuffer %_struct_10
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+         %var = OpVariable %_ptr_StorageBuffer__struct_10 StorageBuffer
+       %main = OpFunction %void None %func
+      %label = OpLabel
+     %access = OpAccessChain %_ptr_StorageBuffer_uint %var %uint_0 %uint_0
+ %ptr_access = OpPtrAccessChain %_ptr_StorageBuffer_uint %access %uint_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Base-07652"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpPtrAccessChain Base operand pointing to "
+                        "StorageBuffer storage class must use VariablePointers "
+                        "or VariablePointersStorageBuffer capability"));
+}
+
+TEST_F(ValidateMemory, VulkanPtrAccessChainWorkgroupCapability) {
+  const std::string spirv = R"(
+               OpCapability Shader
+               OpCapability VariablePointersStorageBuffer
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpExtension "SPV_KHR_variable_pointers"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "foo" %var
+               OpExecutionMode %main LocalSize 1 1 1
+               OpDecorate %_ptr_Workgroup_uint ArrayStride 4
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+%_arr_uint = OpTypeArray %uint %uint_1
+%_ptr_Workgroup__arr_uint = OpTypePointer Workgroup %_arr_uint
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+        %var = OpVariable %_ptr_Workgroup__arr_uint Workgroup
+       %main = OpFunction %void None %func
+      %label = OpLabel
+     %access = OpAccessChain %_ptr_Workgroup_uint %var %uint_0
+ %ptr_access = OpPtrAccessChain %_ptr_Workgroup_uint %access %uint_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-Base-07651"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpPtrAccessChain Base operand pointing to Workgroup "
+                        "storage class must use VariablePointers capability"));
+}
+
+TEST_F(ValidateMemory, VulkanPtrAccessChainWorkgroupNoArrayStrideSuccess) {
+  const std::string spirv = R"(
+               OpCapability Shader
+               OpCapability VariablePointers
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpExtension "SPV_KHR_variable_pointers"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "foo" %var
+               OpExecutionMode %main LocalSize 1 1 1
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+%_arr_uint = OpTypeArray %uint %uint_1
+%_ptr_Workgroup__arr_uint = OpTypePointer Workgroup %_arr_uint
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+        %var = OpVariable %_ptr_Workgroup__arr_uint Workgroup
+       %main = OpFunction %void None %func
+      %label = OpLabel
+     %access = OpAccessChain %_ptr_Workgroup_uint %var %uint_0
+ %ptr_access = OpPtrAccessChain %_ptr_Workgroup_uint %access %uint_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_mesh_shading_test.cpp b/third_party/SPIRV-Tools/test/val/val_mesh_shading_test.cpp
new file mode 100644
index 0000000..ce6999d
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/val/val_mesh_shading_test.cpp
@@ -0,0 +1,604 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Tests instructions from SPV_EXT_mesh_shader
+
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "test/val/val_fixtures.h"
+
+namespace spvtools {
+namespace val {
+namespace {
+
+using ::testing::HasSubstr;
+using ::testing::Values;
+
+using ValidateMeshShading = spvtest::ValidateBase<bool>;
+
+TEST_F(ValidateMeshShading, EmitMeshTasksEXTNotLastInstructionUniversal) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TaskEXT %main "main" %p
+               OpExecutionModeId %main LocalSizeId %uint_1 %uint_1 %uint_1
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+      %float = OpTypeFloat 32
+  %arr_float = OpTypeArray %float %uint_1
+    %Payload = OpTypeStruct %arr_float
+%ptr_Payload = OpTypePointer TaskPayloadWorkgroupEXT %Payload
+          %p = OpVariable %ptr_Payload TaskPayloadWorkgroupEXT
+       %main = OpFunction %void None %func
+     %label1 = OpLabel
+               OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %p
+               OpBranch %label2
+     %label2 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_4);
+  EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Branch must appear in a block"));
+}
+
+TEST_F(ValidateMeshShading, EmitMeshTasksEXTNotLastInstructionVulkan) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TaskEXT %main "main" %p
+               OpExecutionModeId %main LocalSizeId %uint_1 %uint_1 %uint_1
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+      %float = OpTypeFloat 32
+  %arr_float = OpTypeArray %float %uint_1
+    %Payload = OpTypeStruct %arr_float
+%ptr_Payload = OpTypePointer TaskPayloadWorkgroupEXT %Payload
+          %p = OpVariable %ptr_Payload TaskPayloadWorkgroupEXT
+       %main = OpFunction %void None %func
+     %label1 = OpLabel
+               OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %p
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Return must appear in a block"));
+}
+
+TEST_F(ValidateMeshShading, BasicTaskSuccess) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TaskEXT %main "main"
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
+TEST_F(ValidateMeshShading, BasicMeshSuccess) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %main "main"
+               OpExecutionMode %main OutputVertices 1
+               OpExecutionMode %main OutputPrimitivesEXT 1
+               OpExecutionMode %main OutputTrianglesEXT
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
+TEST_F(ValidateMeshShading, VulkanBasicMeshAndTaskSuccess) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpExtension "SPV_NV_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %mainMesh "mainMesh"
+               OpEntryPoint TaskEXT %mainTask "mainTask"
+               OpExecutionMode %mainMesh OutputVertices 1
+               OpExecutionMode %mainMesh OutputPrimitivesEXT 1
+               OpExecutionMode %mainMesh OutputTrianglesEXT
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+   %mainMesh = OpFunction %void None %func
+  %labelMesh = OpLabel
+               OpReturn
+               OpFunctionEnd
+   %mainTask = OpFunction %void None %func
+  %labelTask = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+}
+
+TEST_F(ValidateMeshShading, VulkanBasicMeshAndTaskBad) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpCapability MeshShadingNV
+               OpExtension "SPV_EXT_mesh_shader"
+               OpExtension "SPV_NV_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %mainMesh "mainMesh"
+               OpEntryPoint TaskNV %mainTask "mainTask"
+               OpExecutionMode %mainMesh OutputVertices 1
+               OpExecutionMode %mainMesh OutputPrimitivesEXT 1
+               OpExecutionMode %mainMesh OutputTrianglesEXT
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+   %mainMesh = OpFunction %void None %func
+  %labelMesh = OpLabel
+               OpReturn
+               OpFunctionEnd
+   %mainTask = OpFunction %void None %func
+  %labelTask = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-MeshEXT-07102"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Module can't mix MeshEXT/TaskEXT with MeshNV/TaskNV "
+                        "Execution Model."));
+}
+
+TEST_F(ValidateMeshShading, MeshMissingOutputVertices) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %main "main"
+               OpExecutionMode %main OutputPrimitivesEXT 1
+               OpExecutionMode %main OutputTrianglesEXT
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("MeshEXT execution model entry points must specify both "
+                "OutputPrimitivesEXT and OutputVertices Execution Modes."));
+}
+
+TEST_F(ValidateMeshShading, MeshMissingOutputPrimitivesEXT) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %main "main"
+               OpExecutionMode %main OutputVertices 1
+               OpExecutionMode %main OutputTrianglesEXT
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("MeshEXT execution model entry points must specify both "
+                "OutputPrimitivesEXT and OutputVertices Execution Modes."));
+}
+
+TEST_F(ValidateMeshShading, MeshMissingOutputType) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %main "main"
+               OpExecutionMode %main OutputVertices 1
+               OpExecutionMode %main OutputPrimitivesEXT 1
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("MeshEXT execution model entry points must specify "
+                        "exactly one of OutputPoints, OutputLinesEXT, or "
+                        "OutputTrianglesEXT Execution Modes."));
+}
+
+TEST_F(ValidateMeshShading, MeshMultipleOutputType) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %main "main"
+               OpExecutionMode %main OutputVertices 1
+               OpExecutionMode %main OutputPrimitivesEXT 1
+               OpExecutionMode %main OutputLinesEXT
+               OpExecutionMode %main OutputTrianglesEXT
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("MeshEXT execution model entry points must specify "
+                        "exactly one of OutputPoints, OutputLinesEXT, or "
+                        "OutputTrianglesEXT Execution Modes."));
+}
+
+TEST_F(ValidateMeshShading, BadExecutionModelOutputLinesEXT) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main OutputLinesEXT
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Execution mode can only be used with the MeshEXT or "
+                        "MeshNV execution model."));
+}
+
+TEST_F(ValidateMeshShading, BadExecutionModelOutputTrianglesEXT) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main OutputTrianglesEXT
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Execution mode can only be used with the MeshEXT or "
+                        "MeshNV execution model."));
+}
+
+TEST_F(ValidateMeshShading, BadExecutionModelOutputPrimitivesEXT) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main OutputPrimitivesEXT 1
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Execution mode can only be used with the MeshEXT or "
+                        "MeshNV execution model."));
+}
+
+TEST_F(ValidateMeshShading, OpEmitMeshTasksBadGroupCountSignedInt) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TaskEXT %main "main"
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+       %uint = OpTypeInt 32 0
+      %int_1 = OpConstant %int 1
+     %uint_1 = OpConstant %uint 1
+       %main = OpFunction %void None %func
+       %label = OpLabel
+               OpEmitMeshTasksEXT %int_1 %uint_1 %uint_1
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Group Count X must be a 32-bit unsigned int scalar"));
+}
+
+TEST_F(ValidateMeshShading, OpEmitMeshTasksBadGroupCountVector) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TaskEXT %main "main"
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %v2uint = OpTypeVector %uint 2
+%_ptr_v2uint = OpTypePointer Function %v2uint
+     %uint_1 = OpConstant %uint 1
+  %composite = OpConstantComposite %v2uint %uint_1 %uint_1
+  %_ptr_uint = OpTypePointer Function %uint
+       %main = OpFunction %void None %func
+      %label = OpLabel
+          %x = OpVariable %_ptr_v2uint Function
+               OpStore %x %composite
+         %13 = OpAccessChain %_ptr_uint %x %uint_1
+         %14 = OpLoad %uint %13
+               OpEmitMeshTasksEXT %14 %composite %uint_1
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Group Count Y must be a 32-bit unsigned int scalar"));
+}
+
+TEST_F(ValidateMeshShading, OpEmitMeshTasksBadPayload) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TaskEXT %main "main" %payload
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+       %task = OpTypeStruct %uint
+%_ptr_Uniform = OpTypePointer Uniform %task
+    %payload = OpVariable %_ptr_Uniform Uniform
+     %uint_1 = OpConstant %uint 1
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %payload
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Payload OpVariable must have a storage class of "
+                        "TaskPayloadWorkgroupEXT"));
+}
+
+TEST_F(ValidateMeshShading, TaskPayloadWorkgroupBadExecutionModel) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main" %payload
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+%_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
+    %payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT
+       %main = OpFunction %void None %func
+      %label = OpLabel
+       %load = OpLoad %uint %payload
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("TaskPayloadWorkgroupEXT Storage Class is limited to "
+                        "TaskEXT and MeshKHR execution model"));
+}
+
+TEST_F(ValidateMeshShading, OpSetMeshOutputsBadVertexCount) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %main "main"
+               OpExecutionMode %main OutputVertices 1
+               OpExecutionMode %main OutputPrimitivesNV 1
+               OpExecutionMode %main OutputTrianglesNV
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+       %uint = OpTypeInt 32 0
+  %_ptr_int = OpTypePointer Function %int
+      %int_1 = OpConstant %int 1
+     %uint_1 = OpConstant %uint 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+          %x = OpVariable %_ptr_int Function
+               OpStore %x %int_1
+       %load = OpLoad %int %x
+               OpSetMeshOutputsEXT %load %uint_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Vertex Count must be a 32-bit unsigned int scalar"));
+}
+
+TEST_F(ValidateMeshShading, OpSetMeshOutputsBadPrimitiveCount) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %main "main"
+               OpExecutionMode %main OutputVertices 1
+               OpExecutionMode %main OutputPrimitivesNV 1
+               OpExecutionMode %main OutputTrianglesNV
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+       %uint = OpTypeInt 32 0
+      %int_1 = OpConstant %int 1
+     %uint_1 = OpConstant %uint 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpSetMeshOutputsEXT %uint_1 %int_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Primitive Count must be a 32-bit unsigned int scalar"));
+}
+
+TEST_F(ValidateMeshShading, OpSetMeshOutputsBadExecutionModel) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TaskEXT %main "main"
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpSetMeshOutputsEXT %uint_1 %uint_1
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpSetMeshOutputsEXT requires MeshEXT execution model"));
+}
+
+TEST_F(ValidateMeshShading, OpSetMeshOutputsZeroSuccess) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint MeshEXT %main "main"
+               OpExecutionMode %main OutputVertices 1
+               OpExecutionMode %main OutputPrimitivesNV 1
+               OpExecutionMode %main OutputTrianglesNV
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpSetMeshOutputsEXT %uint_0 %uint_0
+               OpReturn
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
+TEST_F(ValidateMeshShading, OpEmitMeshTasksZeroSuccess) {
+  const std::string body = R"(
+               OpCapability MeshShadingEXT
+               OpExtension "SPV_EXT_mesh_shader"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint TaskEXT %main "main"
+       %void = OpTypeVoid
+       %func = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 1
+       %main = OpFunction %void None %func
+      %label = OpLabel
+               OpEmitMeshTasksEXT %uint_0 %uint_0 %uint_0
+               OpFunctionEnd
+)";
+
+  CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
+}  // namespace
+}  // namespace val
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_non_semantic_test.cpp b/third_party/SPIRV-Tools/test/val/val_non_semantic_test.cpp
index 210cd1a..85362fe 100644
--- a/third_party/SPIRV-Tools/test/val/val_non_semantic_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_non_semantic_test.cpp
@@ -187,7 +187,7 @@
   // there's no specific error for using an OpExtInst too early, it requires a
   // type so by definition any use of a type in it will be an undefined ID
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("ID 2[%2] has not been defined"));
+              HasSubstr("ID '2[%2]' has not been defined"));
 }
 
 TEST_F(ValidateNonSemanticString, MissingOpExtensionPost1p6) {
diff --git a/third_party/SPIRV-Tools/test/val/val_non_uniform_test.cpp b/third_party/SPIRV-Tools/test/val/val_non_uniform_test.cpp
index 3840eec..af571d3 100644
--- a/third_party/SPIRV-Tools/test/val/val_non_uniform_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_non_uniform_test.cpp
@@ -97,24 +97,25 @@
   return ss.str();
 }
 
-SpvScope scopes[] = {SpvScopeCrossDevice, SpvScopeDevice, SpvScopeWorkgroup,
-                     SpvScopeSubgroup, SpvScopeInvocation};
+spv::Scope scopes[] = {spv::Scope::CrossDevice, spv::Scope::Device,
+                       spv::Scope::Workgroup, spv::Scope::Subgroup,
+                       spv::Scope::Invocation};
 
 using ValidateGroupNonUniform = spvtest::ValidateBase<bool>;
 using GroupNonUniform = spvtest::ValidateBase<
-    std::tuple<std::string, std::string, SpvScope, std::string, std::string>>;
+    std::tuple<std::string, std::string, spv::Scope, std::string, std::string>>;
 
-std::string ConvertScope(SpvScope scope) {
+std::string ConvertScope(spv::Scope scope) {
   switch (scope) {
-    case SpvScopeCrossDevice:
+    case spv::Scope::CrossDevice:
       return "%cross_device";
-    case SpvScopeDevice:
+    case spv::Scope::Device:
       return "%device";
-    case SpvScopeWorkgroup:
+    case spv::Scope::Workgroup:
       return "%workgroup";
-    case SpvScopeSubgroup:
+    case spv::Scope::Subgroup:
       return "%subgroup";
-    case SpvScopeInvocation:
+    case spv::Scope::Invocation:
       return "%invocation";
     default:
       return "";
@@ -124,7 +125,7 @@
 TEST_P(GroupNonUniform, Vulkan1p1) {
   std::string opcode = std::get<0>(GetParam());
   std::string type = std::get<1>(GetParam());
-  SpvScope execution_scope = std::get<2>(GetParam());
+  spv::Scope execution_scope = std::get<2>(GetParam());
   std::string args = std::get<3>(GetParam());
   std::string error = std::get<4>(GetParam());
 
@@ -137,7 +138,7 @@
   CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_VULKAN_1_1);
   spv_result_t result = ValidateInstructions(SPV_ENV_VULKAN_1_1);
   if (error == "") {
-    if (execution_scope == SpvScopeSubgroup) {
+    if (execution_scope == spv::Scope::Subgroup) {
       EXPECT_EQ(SPV_SUCCESS, result);
     } else {
       EXPECT_EQ(SPV_ERROR_INVALID_DATA, result);
@@ -157,7 +158,7 @@
 TEST_P(GroupNonUniform, Spirv1p3) {
   std::string opcode = std::get<0>(GetParam());
   std::string type = std::get<1>(GetParam());
-  SpvScope execution_scope = std::get<2>(GetParam());
+  spv::Scope execution_scope = std::get<2>(GetParam());
   std::string args = std::get<3>(GetParam());
   std::string error = std::get<4>(GetParam());
 
@@ -170,8 +171,8 @@
   CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_UNIVERSAL_1_3);
   spv_result_t result = ValidateInstructions(SPV_ENV_UNIVERSAL_1_3);
   if (error == "") {
-    if (execution_scope == SpvScopeSubgroup ||
-        execution_scope == SpvScopeWorkgroup) {
+    if (execution_scope == spv::Scope::Subgroup ||
+        execution_scope == spv::Scope::Workgroup) {
       EXPECT_EQ(SPV_SUCCESS, result);
     } else {
       EXPECT_EQ(SPV_ERROR_INVALID_DATA, result);
@@ -280,12 +281,12 @@
     GroupNonUniformBallotBitCountBadResultType, GroupNonUniform,
     Combine(
         Values("OpGroupNonUniformBallotBitCount"), Values("%float", "%int"),
-        Values(SpvScopeSubgroup), Values("Reduce %u32vec4_null"),
+        Values(spv::Scope::Subgroup), Values("Reduce %u32vec4_null"),
         Values("Expected Result Type to be an unsigned integer type scalar.")));
 
 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCountBadValue, GroupNonUniform,
                          Combine(Values("OpGroupNonUniformBallotBitCount"),
-                                 Values("%u32"), Values(SpvScopeSubgroup),
+                                 Values("%u32"), Values(spv::Scope::Subgroup),
                                  Values("Reduce %u32vec3_null", "Reduce %u32_0",
                                         "Reduce %float_0"),
                                  Values("Expected Value to be a vector of four "
diff --git a/third_party/SPIRV-Tools/test/val/val_ray_query.cpp b/third_party/SPIRV-Tools/test/val/val_ray_query_test.cpp
similarity index 88%
rename from third_party/SPIRV-Tools/test/val/val_ray_query.cpp
rename to third_party/SPIRV-Tools/test/val/val_ray_query_test.cpp
index e9b9696..e0eb067 100644
--- a/third_party/SPIRV-Tools/test/val/val_ray_query.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_ray_query_test.cpp
@@ -18,6 +18,7 @@
 #include <string>
 
 #include "gmock/gmock.h"
+#include "spirv-tools/libspirv.h"
 #include "test/val/val_fixtures.h"
 
 namespace spvtools {
@@ -446,7 +447,7 @@
   CompileSuccessfully(GenerateShaderCode(body).c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("Operand 15[%v2uint] cannot be a type"));
+              HasSubstr("Operand '15[%v2uint]' cannot be a type"));
 }
 
 TEST_F(ValidateRayQuery, InitializeBadCullMask) {
@@ -573,6 +574,58 @@
               HasSubstr("Hit T must be a 32-bit float scalar"));
 }
 
+TEST_F(ValidateRayQuery, RayQueryArraySuccess) {
+  // This shader is slightly different to the ones above, so it doesn't reuse
+  // the shader code generator.
+  const std::string shader = R"(
+                       OpCapability Shader
+                       OpCapability RayQueryKHR
+                       OpExtension "SPV_KHR_ray_query"
+                       OpMemoryModel Logical GLSL450
+                       OpEntryPoint GLCompute %main "main"
+                       OpExecutionMode %main LocalSize 1 1 1
+                       OpSource GLSL 460
+                       OpDecorate %topLevelAS DescriptorSet 0
+                       OpDecorate %topLevelAS Binding 0
+                       OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
+               %void = OpTypeVoid
+               %func = OpTypeFunction %void
+          %ray_query = OpTypeRayQueryKHR
+               %uint = OpTypeInt 32 0
+             %uint_2 = OpConstant %uint 2
+    %ray_query_array = OpTypeArray %ray_query %uint_2
+%ptr_ray_query_array = OpTypePointer Private %ray_query_array
+         %rayQueries = OpVariable %ptr_ray_query_array Private
+                %int = OpTypeInt 32 1
+              %int_0 = OpConstant %int 0
+      %ptr_ray_query = OpTypePointer Private %ray_query
+       %accel_struct = OpTypeAccelerationStructureKHR
+   %ptr_accel_struct = OpTypePointer UniformConstant %accel_struct
+         %topLevelAS = OpVariable %ptr_accel_struct UniformConstant
+             %uint_0 = OpConstant %uint 0
+           %uint_255 = OpConstant %uint 255
+              %float = OpTypeFloat 32
+            %v3float = OpTypeVector %float 3
+            %float_0 = OpConstant %float 0
+          %vec3_zero = OpConstantComposite %v3float %float_0 %float_0 %float_0
+            %float_1 = OpConstant %float 1
+      %vec3_xy_0_z_1 = OpConstantComposite %v3float %float_0 %float_0 %float_1
+           %float_10 = OpConstant %float 10
+             %v3uint = OpTypeVector %uint 3
+             %uint_1 = OpConstant %uint 1
+   %gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
+               %main = OpFunction %void None %func
+         %main_label = OpLabel
+    %first_ray_query = OpAccessChain %ptr_ray_query %rayQueries %int_0
+     %topLevelAS_val = OpLoad %accel_struct %topLevelAS
+                       OpRayQueryInitializeKHR %first_ray_query %topLevelAS_val %uint_0 %uint_255 %vec3_zero %float_0 %vec3_xy_0_z_1 %float_10
+                       OpReturn
+                       OpFunctionEnd
+)";
+  CompileSuccessfully(shader);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_ray_tracing_test.cpp b/third_party/SPIRV-Tools/test/val/val_ray_tracing_test.cpp
new file mode 100644
index 0000000..60f2f89
--- /dev/null
+++ b/third_party/SPIRV-Tools/test/val/val_ray_tracing_test.cpp
@@ -0,0 +1,672 @@
+// Copyright (c) 2022 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Tests ray tracing instructions from SPV_KHR_ray_tracing.
+
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "test/val/val_fixtures.h"
+
+namespace spvtools {
+namespace val {
+namespace {
+
+using ::testing::HasSubstr;
+using ::testing::Values;
+
+using ValidateRayTracing = spvtest::ValidateBase<bool>;
+
+TEST_F(ValidateRayTracing, IgnoreIntersectionSuccess) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint AnyHitKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%main = OpFunction %void None %func
+%label = OpLabel
+OpIgnoreIntersectionKHR
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateRayTracing, IgnoreIntersectionExecutionModel) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint CallableKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%main = OpFunction %void None %func
+%label = OpLabel
+OpIgnoreIntersectionKHR
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpIgnoreIntersectionKHR requires AnyHitKHR execution model"));
+}
+
+TEST_F(ValidateRayTracing, TerminateRaySuccess) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint AnyHitKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%main = OpFunction %void None %func
+%label = OpLabel
+OpIgnoreIntersectionKHR
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateRayTracing, TerminateRayExecutionModel) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint MissKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%main = OpFunction %void None %func
+%label = OpLabel
+OpTerminateRayKHR
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpTerminateRayKHR requires AnyHitKHR execution model"));
+}
+
+TEST_F(ValidateRayTracing, ReportIntersectionRaySuccess) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint IntersectionKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%float = OpTypeFloat 32
+%float_1 = OpConstant %float 1
+%uint = OpTypeInt 32 0
+%uint_1 = OpConstant %uint 1
+%bool = OpTypeBool
+%main = OpFunction %void None %func
+%label = OpLabel
+%report = OpReportIntersectionKHR %bool %float_1 %uint_1
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateRayTracing, ReportIntersectionExecutionModel) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint MissKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%float = OpTypeFloat 32
+%float_1 = OpConstant %float 1
+%uint = OpTypeInt 32 0
+%uint_1 = OpConstant %uint 1
+%bool = OpTypeBool
+%main = OpFunction %void None %func
+%label = OpLabel
+%report = OpReportIntersectionKHR %bool %float_1 %uint_1
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpReportIntersectionKHR requires IntersectionKHR execution model"));
+}
+
+TEST_F(ValidateRayTracing, ReportIntersectionReturnType) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint IntersectionKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%float = OpTypeFloat 32
+%float_1 = OpConstant %float 1
+%uint = OpTypeInt 32 0
+%uint_1 = OpConstant %uint 1
+%main = OpFunction %void None %func
+%label = OpLabel
+%report = OpReportIntersectionKHR %uint %float_1 %uint_1
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("expected Result Type to be bool scalar type"));
+}
+
+TEST_F(ValidateRayTracing, ReportIntersectionHit) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpCapability Float64
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint IntersectionKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%float64 = OpTypeFloat 64
+%float64_1 = OpConstant %float64 1
+%uint = OpTypeInt 32 0
+%uint_1 = OpConstant %uint 1
+%bool = OpTypeBool
+%main = OpFunction %void None %func
+%label = OpLabel
+%report = OpReportIntersectionKHR %bool %float64_1 %uint_1
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Hit must be a 32-bit int scalar"));
+}
+
+TEST_F(ValidateRayTracing, ReportIntersectionHitKind) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint IntersectionKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%float = OpTypeFloat 32
+%float_1 = OpConstant %float 1
+%sint = OpTypeInt 32 1
+%sint_1 = OpConstant %sint 1
+%bool = OpTypeBool
+%main = OpFunction %void None %func
+%label = OpLabel
+%report = OpReportIntersectionKHR %bool %float_1 %sint_1
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Hit Kind must be a 32-bit unsigned int scalar"));
+}
+
+TEST_F(ValidateRayTracing, ExecuteCallableSuccess) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint CallableKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%data_ptr = OpTypePointer CallableDataKHR %int
+%data = OpVariable %data_ptr CallableDataKHR
+%inData_ptr = OpTypePointer IncomingCallableDataKHR %int
+%inData = OpVariable %inData_ptr IncomingCallableDataKHR
+%main = OpFunction %void None %func
+%label = OpLabel
+OpExecuteCallableKHR %uint_0 %data
+OpExecuteCallableKHR %uint_0 %inData
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateRayTracing, ExecuteCallableExecutionModel) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint AnyHitKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%data_ptr = OpTypePointer CallableDataKHR %int
+%data = OpVariable %data_ptr CallableDataKHR
+%inData_ptr = OpTypePointer IncomingCallableDataKHR %int
+%inData = OpVariable %inData_ptr IncomingCallableDataKHR
+%main = OpFunction %void None %func
+%label = OpLabel
+OpExecuteCallableKHR %uint_0 %data
+OpExecuteCallableKHR %uint_0 %inData
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpExecuteCallableKHR requires RayGenerationKHR, "
+                "ClosestHitKHR, MissKHR and CallableKHR execution models"));
+}
+
+TEST_F(ValidateRayTracing, ExecuteCallableStorageClass) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint RayGenerationKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%data_ptr = OpTypePointer RayPayloadKHR %int
+%data = OpVariable %data_ptr RayPayloadKHR
+%main = OpFunction %void None %func
+%label = OpLabel
+OpExecuteCallableKHR %uint_0 %data
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Callable Data must have storage class CallableDataKHR "
+                        "or IncomingCallableDataKHR"));
+}
+
+TEST_F(ValidateRayTracing, ExecuteCallableSbtIndex) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint CallableKHR %main "main"
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%int_1 = OpConstant %int 1
+%data_ptr = OpTypePointer CallableDataKHR %int
+%data = OpVariable %data_ptr CallableDataKHR
+%main = OpFunction %void None %func
+%label = OpLabel
+OpExecuteCallableKHR %int_1 %data
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("SBT Index must be a 32-bit unsigned int scalar"));
+}
+
+std::string GenerateRayTraceCode(
+    const std::string& body,
+    const std::string execution_model = "RayGenerationKHR") {
+  std::ostringstream ss;
+  ss << R"(
+OpCapability RayTracingKHR
+OpCapability Float64
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint )"
+     << execution_model << R"( %main "main"
+OpDecorate %top_level_as DescriptorSet 0
+OpDecorate %top_level_as Binding 0
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%type_as = OpTypeAccelerationStructureKHR
+%as_uc_ptr = OpTypePointer UniformConstant %type_as
+%top_level_as = OpVariable %as_uc_ptr UniformConstant
+%uint = OpTypeInt 32 0
+%uint_1 = OpConstant %uint 1
+%float = OpTypeFloat 32
+%float64 = OpTypeFloat 64
+%f32vec3 = OpTypeVector %float 3
+%f32vec4 = OpTypeVector %float 4
+%float_0 = OpConstant %float 0
+%float64_0 = OpConstant %float64 0
+%v3composite = OpConstantComposite %f32vec3 %float_0 %float_0 %float_0
+%v4composite = OpConstantComposite %f32vec4 %float_0 %float_0 %float_0 %float_0
+%int = OpTypeInt 32 1
+%int_1 = OpConstant %int 1
+%payload_ptr = OpTypePointer RayPayloadKHR %int
+%payload = OpVariable %payload_ptr RayPayloadKHR
+%callable_ptr = OpTypePointer CallableDataKHR %int
+%callable = OpVariable %callable_ptr CallableDataKHR
+%ptr_uint = OpTypePointer Private %uint
+%var_uint = OpVariable %ptr_uint Private
+%ptr_float = OpTypePointer Private %float
+%var_float = OpVariable %ptr_float Private
+%ptr_f32vec3 = OpTypePointer Private %f32vec3
+%var_f32vec3 = OpVariable %ptr_f32vec3 Private
+%main = OpFunction %void None %func
+%label = OpLabel
+)";
+
+  ss << body;
+
+  ss << R"(
+OpReturn
+OpFunctionEnd)";
+  return ss.str();
+}
+
+TEST_F(ValidateRayTracing, TraceRaySuccess) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %uint_1 %uint_1 %v3composite %float_0 %v3composite %float_0 %payload
+
+%_uint = OpLoad %uint %var_uint
+%_float = OpLoad %float %var_float
+%_f32vec3 = OpLoad %f32vec3 %var_f32vec3
+OpTraceRayKHR %as %_uint %_uint %_uint %_uint %_uint %_f32vec3 %_float %_f32vec3 %_float %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateRayTracing, TraceRayExecutionModel) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %uint_1 %uint_1 %v3composite %float_0 %v3composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body, "CallableKHR").c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpTraceRayKHR requires RayGenerationKHR, "
+                        "ClosestHitKHR and MissKHR execution models"));
+}
+
+TEST_F(ValidateRayTracing, TraceRayAccelerationStructure) {
+  const std::string body = R"(
+%_uint = OpLoad %uint %var_uint
+OpTraceRayKHR %_uint %uint_1 %uint_1 %uint_1 %uint_1 %uint_1 %v3composite %float_0 %v3composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected Acceleration Structure to be of type "
+                        "OpTypeAccelerationStructureKHR"));
+}
+
+TEST_F(ValidateRayTracing, TraceRayRayFlags) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %float_0 %uint_1 %uint_1 %uint_1 %uint_1 %v3composite %float_0 %v3composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Ray Flags must be a 32-bit int scalar"));
+}
+
+TEST_F(ValidateRayTracing, TraceRayCullMask) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %float_0 %uint_1 %uint_1 %uint_1 %v3composite %float_0 %v3composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Cull Mask must be a 32-bit int scalar"));
+}
+
+TEST_F(ValidateRayTracing, TraceRaySbtOffest) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %float_0 %uint_1 %uint_1 %v3composite %float_0 %v3composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("SBT Offset must be a 32-bit int scalar"));
+}
+
+TEST_F(ValidateRayTracing, TraceRaySbtStride) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %float_0 %uint_1 %v3composite %float_0 %v3composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("SBT Stride must be a 32-bit int scalar"));
+}
+
+TEST_F(ValidateRayTracing, TraceRayMissIndex) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %uint_1 %float_0 %v3composite %float_0 %v3composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Miss Index must be a 32-bit int scalar"));
+}
+
+TEST_F(ValidateRayTracing, TraceRayRayOrigin) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %uint_1 %uint_1 %float_0 %float_0 %v3composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Ray Origin must be a 32-bit float 3-component vector"));
+}
+
+TEST_F(ValidateRayTracing, TraceRayRayTMin) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %uint_1 %uint_1 %v3composite %uint_1 %v3composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Ray TMin must be a 32-bit float scalar"));
+}
+
+TEST_F(ValidateRayTracing, TraceRayRayDirection) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %uint_1 %uint_1 %v3composite %float_0 %v4composite %float_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Ray Direction must be a 32-bit float 3-component vector"));
+}
+
+TEST_F(ValidateRayTracing, TraceRayRayTMax) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %uint_1 %uint_1 %v3composite %float_0 %v3composite %float64_0 %payload
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Ray TMax must be a 32-bit float scalar"));
+}
+
+TEST_F(ValidateRayTracing, TraceRayPayload) {
+  const std::string body = R"(
+%as = OpLoad %type_as %top_level_as
+OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %uint_1 %uint_1 %v3composite %float_0 %v3composite %float_0 %callable
+)";
+
+  CompileSuccessfully(GenerateRayTraceCode(body).c_str());
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Payload must have storage class RayPayloadKHR or "
+                        "IncomingRayPayloadKHR"));
+}
+
+TEST_F(ValidateRayTracing, InterfaceIncomingRayPayload) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint CallableKHR %main "main" %inData1 %inData2
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%inData_ptr = OpTypePointer IncomingRayPayloadKHR %int
+%inData1 = OpVariable %inData_ptr IncomingRayPayloadKHR
+%inData2 = OpVariable %inData_ptr IncomingRayPayloadKHR
+%main = OpFunction %void None %func
+%label = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-IncomingRayPayloadKHR-04700"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Entry-point has more than one variable with the "
+                "IncomingRayPayloadKHR storage class in the interface"));
+}
+
+TEST_F(ValidateRayTracing, InterfaceHitAttribute) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint CallableKHR %main "main" %inData1 %inData2
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%inData_ptr = OpTypePointer HitAttributeKHR %int
+%inData1 = OpVariable %inData_ptr HitAttributeKHR
+%inData2 = OpVariable %inData_ptr HitAttributeKHR
+%main = OpFunction %void None %func
+%label = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04702"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Entry-point has more than one variable with the "
+                        "HitAttributeKHR storage class in the interface"));
+}
+
+TEST_F(ValidateRayTracing, InterfaceIncomingCallableData) {
+  const std::string body = R"(
+OpCapability RayTracingKHR
+OpExtension "SPV_KHR_ray_tracing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint CallableKHR %main "main" %inData1 %inData2
+OpName %main "main"
+%void = OpTypeVoid
+%func = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%inData_ptr = OpTypePointer IncomingCallableDataKHR %int
+%inData1 = OpVariable %inData_ptr IncomingCallableDataKHR
+%inData2 = OpVariable %inData_ptr IncomingCallableDataKHR
+%main = OpFunction %void None %func
+%label = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(getDiagnosticString(),
+              AnyVUID("VUID-StandaloneSpirv-IncomingCallableDataKHR-04706"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Entry-point has more than one variable with the "
+                "IncomingCallableDataKHR storage class in the interface"));
+}
+
+}  // namespace
+}  // namespace val
+}  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_ssa_test.cpp b/third_party/SPIRV-Tools/test/val/val_ssa_test.cpp
index 035c710..c22f4ad 100644
--- a/third_party/SPIRV-Tools/test/val/val_ssa_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_ssa_test.cpp
@@ -118,7 +118,7 @@
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              MatchesRegex("ID .\\[%bad\\] has not been defined\n"
+              MatchesRegex("ID '.\\[%bad\\]' has not been defined\n"
                            "  %8 = OpIAdd %uint %uint_1 %bad\n"));
 }
 
@@ -141,7 +141,7 @@
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              MatchesRegex("ID .\\[%sum\\] has not been defined\n"
+              MatchesRegex("ID '.\\[%sum\\]' has not been defined\n"
                            "  %sum = OpIAdd %uint %uint_1 %sum\n"));
 }
 
@@ -204,7 +204,7 @@
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("The following forward referenced IDs have not been "
-                        "defined:\n2[%2]"));
+                        "defined:\n'2[%2]'"));
 }
 
 TEST_F(ValidateSSA, ForwardDecorateGood) {
@@ -1126,8 +1126,8 @@
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      MatchesRegex("ID .\\[%eleven\\] defined in block .\\[%true_block\\] "
-                   "does not dominate its use in block .\\[%false_block\\]\n"
+      MatchesRegex("ID '.\\[%eleven\\]' defined in block '.\\[%true_block\\]' "
+                   "does not dominate its use in block '.\\[%false_block\\]'\n"
                    "  %false_block = OpLabel\n"));
 }
 
@@ -1187,7 +1187,7 @@
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              MatchesRegex("ID .\\[%inew\\] has not been defined\n"
+              MatchesRegex("ID '.\\[%inew\\]' has not been defined\n"
                            "  %19 = OpIAdd %uint %inew %uint_1\n"));
 }
 
@@ -1268,12 +1268,12 @@
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      MatchesRegex("In OpPhi instruction .\\[%phi\\], ID .\\[%true_copy\\] "
-                   "definition does not dominate its parent .\\[%if_false\\]\n"
-                   "  %phi = OpPhi %bool %true_copy %if_false %false_copy "
-                   "%if_true\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              MatchesRegex(
+                  "In OpPhi instruction '.\\[%phi\\]', ID '.\\[%true_copy\\]' "
+                  "definition does not dominate its parent '.\\[%if_false\\]'\n"
+                  "  %phi = OpPhi %bool %true_copy %if_false %false_copy "
+                  "%if_true\n"));
 }
 
 TEST_F(ValidateSSA, PhiVariableDefDominatesButNotDefinedInParentBlock) {
@@ -1396,11 +1396,11 @@
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      MatchesRegex("ID .\\[%first\\] used in function .\\[%func2\\] is used "
-                   "outside of it's defining function .\\[%func\\]\n"
-                   "  %func = OpFunction %void None %14\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              MatchesRegex(
+                  "ID '.\\[%first\\]' used in function '.\\[%func2\\]' is used "
+                  "outside of it's defining function '.\\[%func\\]'\n"
+                  "  %func = OpFunction %void None %14\n"));
 }
 
 TEST_F(ValidateSSA, TypeForwardPointerForwardReference) {
diff --git a/third_party/SPIRV-Tools/test/val/val_state_test.cpp b/third_party/SPIRV-Tools/test/val/val_state_test.cpp
index 65cb1c3..4097a1f 100644
--- a/third_party/SPIRV-Tools/test/val/val_state_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_state_test.cpp
@@ -59,40 +59,41 @@
 
 TEST_F(ValidationState_HasAnyOfCapabilities, EmptyMask) {
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityMatrix);
+  state_.RegisterCapability(spv::Capability::Matrix);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityImageMipmap);
+  state_.RegisterCapability(spv::Capability::ImageMipmap);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityPipes);
+  state_.RegisterCapability(spv::Capability::Pipes);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityStorageImageArrayDynamicIndexing);
+  state_.RegisterCapability(spv::Capability::StorageImageArrayDynamicIndexing);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityClipDistance);
+  state_.RegisterCapability(spv::Capability::ClipDistance);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityStorageImageWriteWithoutFormat);
+  state_.RegisterCapability(spv::Capability::StorageImageWriteWithoutFormat);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
 }
 
 TEST_F(ValidationState_HasAnyOfCapabilities, SingleCapMask) {
-  EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix}));
-  EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap}));
-  state_.RegisterCapability(SpvCapabilityMatrix);
-  EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix}));
-  EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap}));
-  state_.RegisterCapability(SpvCapabilityImageMipmap);
-  EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix}));
-  EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap}));
+  EXPECT_FALSE(state_.HasAnyOfCapabilities({spv::Capability::Matrix}));
+  EXPECT_FALSE(state_.HasAnyOfCapabilities({spv::Capability::ImageMipmap}));
+  state_.RegisterCapability(spv::Capability::Matrix);
+  EXPECT_TRUE(state_.HasAnyOfCapabilities({spv::Capability::Matrix}));
+  EXPECT_FALSE(state_.HasAnyOfCapabilities({spv::Capability::ImageMipmap}));
+  state_.RegisterCapability(spv::Capability::ImageMipmap);
+  EXPECT_TRUE(state_.HasAnyOfCapabilities({spv::Capability::Matrix}));
+  EXPECT_TRUE(state_.HasAnyOfCapabilities({spv::Capability::ImageMipmap}));
 }
 
 TEST_F(ValidationState_HasAnyOfCapabilities, MultiCapMask) {
   const auto set1 =
-      CapabilitySet{SpvCapabilitySampledRect, SpvCapabilityImageBuffer};
-  const auto set2 = CapabilitySet{SpvCapabilityStorageImageWriteWithoutFormat,
-                                  SpvCapabilityStorageImageReadWithoutFormat,
-                                  SpvCapabilityGeometryStreams};
+      CapabilitySet{spv::Capability::SampledRect, spv::Capability::ImageBuffer};
+  const auto set2 =
+      CapabilitySet{spv::Capability::StorageImageWriteWithoutFormat,
+                    spv::Capability::StorageImageReadWithoutFormat,
+                    spv::Capability::GeometryStreams};
   EXPECT_FALSE(state_.HasAnyOfCapabilities(set1));
   EXPECT_FALSE(state_.HasAnyOfCapabilities(set2));
-  state_.RegisterCapability(SpvCapabilityImageBuffer);
+  state_.RegisterCapability(spv::Capability::ImageBuffer);
   EXPECT_TRUE(state_.HasAnyOfCapabilities(set1));
   EXPECT_FALSE(state_.HasAnyOfCapabilities(set2));
 }
@@ -139,50 +140,52 @@
 
 TEST_F(ValidationState_InLayoutState, Variable) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutTypes);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpVariable));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpVariable));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpVariable));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpVariable));
 }
 
 TEST_F(ValidationState_InLayoutState, ExtInst) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutTypes);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpExtInst));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpExtInst));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpExtInst));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpExtInst));
 }
 
 TEST_F(ValidationState_InLayoutState, Undef) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutTypes);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpUndef));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpUndef));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpUndef));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpUndef));
 }
 
 TEST_F(ValidationState_InLayoutState, Function) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDeclarations);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunction));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunction));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunction));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunction));
 }
 
 TEST_F(ValidationState_InLayoutState, FunctionParameter) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDeclarations);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunctionParameter));
+  EXPECT_TRUE(
+      state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunctionParameter));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunctionParameter));
+  EXPECT_TRUE(
+      state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunctionParameter));
 }
 
 TEST_F(ValidationState_InLayoutState, FunctionEnd) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDeclarations);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunctionEnd));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunctionEnd));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunctionEnd));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunctionEnd));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/val/val_storage_test.cpp b/third_party/SPIRV-Tools/test/val/val_storage_test.cpp
index ae4047b..8693e80 100644
--- a/third_party/SPIRV-Tools/test/val/val_storage_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_storage_test.cpp
@@ -251,30 +251,46 @@
               HasSubstr("OpFunctionCall Argument <id> '"));
 }
 
-TEST_P(ValidateStorageExecutionModel, VulkanOutsideStoreFailure) {
-  std::stringstream ss;
+std::string GenerateExecutionModelCode(const std::string& execution_model,
+                                       const std::string& storage_class,
+                                       bool store) {
+  const std::string mode = (execution_model.compare("GLCompute") == 0)
+                               ? "OpExecutionMode %func LocalSize 1 1 1"
+                               : "";
+  const std::string operation =
+      (store) ? "OpStore %var %int0" : "%load = OpLoad %intt %var";
+  std::ostringstream ss;
   ss << R"(
               OpCapability Shader
               OpCapability RayTracingKHR
               OpExtension "SPV_KHR_ray_tracing"
               OpMemoryModel Logical GLSL450
               OpEntryPoint )"
-     << GetParam() << R"(  %func "func" %output
-              OpDecorate %output Location 0
+     << execution_model << R"( %func "func" %var
+              )" << mode << R"(
+              OpDecorate %var Location 0
 %intt       = OpTypeInt 32 0
 %int0       = OpConstant %intt 0
 %voidt      = OpTypeVoid
 %vfunct     = OpTypeFunction %voidt
-%outputptrt = OpTypePointer Output %intt
-%output     = OpVariable %outputptrt Output
+%ptr        = OpTypePointer )"
+     << storage_class << R"( %intt
+%var        = OpVariable %ptr )" << storage_class << R"(
 %func       = OpFunction %voidt None %vfunct
 %funcl      = OpLabel
-              OpStore %output %int0
+              )" << operation << R"(
               OpReturn
               OpFunctionEnd
 )";
 
-  CompileSuccessfully(ss.str(), SPV_ENV_VULKAN_1_0);
+  return ss.str();
+}
+
+TEST_P(ValidateStorageExecutionModel, VulkanOutsideStoreFailure) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(
+      GenerateExecutionModelCode(execution_model, "Output", true).c_str(),
+      SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
   EXPECT_THAT(getDiagnosticString(),
               AnyVUID("VUID-StandaloneSpirv-None-04644"));
@@ -285,11 +301,264 @@
                 "ClosestHitKHR, MissKHR, or CallableKHR execution models"));
 }
 
+TEST_P(ValidateStorageExecutionModel, CallableDataStore) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(
+      GenerateExecutionModelCode(execution_model, "CallableDataKHR", true)
+          .c_str(),
+      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("RayGenerationKHR") == 0 ||
+      execution_model.compare("ClosestHitKHR") == 0 ||
+      execution_model.compare("CallableKHR") == 0 ||
+      execution_model.compare("MissKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-CallableDataKHR-04704"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr(
+            "CallableDataKHR Storage Class is limited to RayGenerationKHR, "
+            "ClosestHitKHR, CallableKHR, and MissKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, CallableDataLoad) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(
+      GenerateExecutionModelCode(execution_model, "CallableDataKHR", false)
+          .c_str(),
+      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("RayGenerationKHR") == 0 ||
+      execution_model.compare("ClosestHitKHR") == 0 ||
+      execution_model.compare("CallableKHR") == 0 ||
+      execution_model.compare("MissKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-CallableDataKHR-04704"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr(
+            "CallableDataKHR Storage Class is limited to RayGenerationKHR, "
+            "ClosestHitKHR, CallableKHR, and MissKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, IncomingCallableDataStore) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(GenerateExecutionModelCode(
+                          execution_model, "IncomingCallableDataKHR", true)
+                          .c_str(),
+                      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("CallableKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-IncomingCallableDataKHR-04705"));
+    EXPECT_THAT(getDiagnosticString(),
+                HasSubstr("IncomingCallableDataKHR Storage Class is limited to "
+                          "CallableKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, IncomingCallableDataLoad) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(GenerateExecutionModelCode(
+                          execution_model, "IncomingCallableDataKHR", false)
+                          .c_str(),
+                      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("CallableKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-IncomingCallableDataKHR-04705"));
+    EXPECT_THAT(getDiagnosticString(),
+                HasSubstr("IncomingCallableDataKHR Storage Class is limited to "
+                          "CallableKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, RayPayloadStore) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(
+      GenerateExecutionModelCode(execution_model, "RayPayloadKHR", true)
+          .c_str(),
+      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("RayGenerationKHR") == 0 ||
+      execution_model.compare("ClosestHitKHR") == 0 ||
+      execution_model.compare("MissKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-RayPayloadKHR-04698"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr("RayPayloadKHR Storage Class is limited to RayGenerationKHR, "
+                  "ClosestHitKHR, and MissKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, RayPayloadLoad) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(
+      GenerateExecutionModelCode(execution_model, "RayPayloadKHR", false)
+          .c_str(),
+      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("RayGenerationKHR") == 0 ||
+      execution_model.compare("ClosestHitKHR") == 0 ||
+      execution_model.compare("MissKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-RayPayloadKHR-04698"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr("RayPayloadKHR Storage Class is limited to RayGenerationKHR, "
+                  "ClosestHitKHR, and MissKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, HitAttributeStore) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(
+      GenerateExecutionModelCode(execution_model, "HitAttributeKHR", true)
+          .c_str(),
+      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("IntersectionKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else if (execution_model.compare("AnyHitKHR") == 0 ||
+             execution_model.compare("ClosestHitKHR") == 0) {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04703"));
+    EXPECT_THAT(getDiagnosticString(),
+                HasSubstr("HitAttributeKHR Storage Class variables are read "
+                          "only with AnyHitKHR and ClosestHitKHR"));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04701"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr(
+            "HitAttributeKHR Storage Class is limited to IntersectionKHR, "
+            "AnyHitKHR, sand ClosestHitKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, HitAttributeLoad) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(
+      GenerateExecutionModelCode(execution_model, "HitAttributeKHR", false)
+          .c_str(),
+      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("IntersectionKHR") == 0 ||
+      execution_model.compare("AnyHitKHR") == 0 ||
+      execution_model.compare("ClosestHitKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04701"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr(
+            "HitAttributeKHR Storage Class is limited to IntersectionKHR, "
+            "AnyHitKHR, sand ClosestHitKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, IncomingRayPayloadStore) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(
+      GenerateExecutionModelCode(execution_model, "IncomingRayPayloadKHR", true)
+          .c_str(),
+      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("AnyHitKHR") == 0 ||
+      execution_model.compare("ClosestHitKHR") == 0 ||
+      execution_model.compare("MissKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr("IncomingRayPayloadKHR Storage Class is limited to "
+                  "AnyHitKHR, ClosestHitKHR, and MissKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, IncomingRayPayloadLoad) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(GenerateExecutionModelCode(execution_model,
+                                                 "IncomingRayPayloadKHR", false)
+                          .c_str(),
+                      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("AnyHitKHR") == 0 ||
+      execution_model.compare("ClosestHitKHR") == 0 ||
+      execution_model.compare("MissKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr("IncomingRayPayloadKHR Storage Class is limited to "
+                  "AnyHitKHR, ClosestHitKHR, and MissKHR execution model"));
+  }
+}
+
+TEST_P(ValidateStorageExecutionModel, ShaderRecordBufferStore) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(
+      GenerateExecutionModelCode(execution_model, "ShaderRecordBufferKHR", true)
+          .c_str(),
+      SPV_ENV_VULKAN_1_2);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("ShaderRecordBufferKHR Storage Class variables are read only"));
+}
+
+TEST_P(ValidateStorageExecutionModel, ShaderRecordBufferLoad) {
+  std::string execution_model = GetParam();
+  CompileSuccessfully(GenerateExecutionModelCode(execution_model,
+                                                 "ShaderRecordBufferKHR", false)
+                          .c_str(),
+                      SPV_ENV_VULKAN_1_2);
+  if (execution_model.compare("RayGenerationKHR") == 0 ||
+      execution_model.compare("IntersectionKHR") == 0 ||
+      execution_model.compare("AnyHitKHR") == 0 ||
+      execution_model.compare("ClosestHitKHR") == 0 ||
+      execution_model.compare("CallableKHR") == 0 ||
+      execution_model.compare("MissKHR") == 0) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+    EXPECT_THAT(getDiagnosticString(),
+                AnyVUID("VUID-StandaloneSpirv-ShaderRecordBufferKHR-07119"));
+    EXPECT_THAT(
+        getDiagnosticString(),
+        HasSubstr("ShaderRecordBufferKHR Storage Class is limited to "
+                  "RayGenerationKHR, IntersectionKHR, AnyHitKHR, "
+                  "ClosestHitKHR, CallableKHR, and MissKHR execution model"));
+  }
+}
+
 INSTANTIATE_TEST_SUITE_P(MatrixExecutionModel, ValidateStorageExecutionModel,
                          ::testing::Values("RayGenerationKHR",
                                            "IntersectionKHR", "AnyHitKHR",
                                            "ClosestHitKHR", "MissKHR",
-                                           "CallableKHR"));
+                                           "CallableKHR", "GLCompute"));
 
 }  // namespace
 }  // namespace val
diff --git a/third_party/SPIRV-Tools/test/val/val_type_unique_test.cpp b/third_party/SPIRV-Tools/test/val/val_type_unique_test.cpp
index 45a4d50..31ad3a6 100644
--- a/third_party/SPIRV-Tools/test/val/val_type_unique_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_type_unique_test.cpp
@@ -90,7 +90,7 @@
 
 // Returns expected error string if |opcode| produces a duplicate type
 // declaration.
-std::string GetErrorString(SpvOp opcode) {
+std::string GetErrorString(spv::Op opcode) {
   return "Duplicate non-aggregate type declarations are not allowed. Opcode: " +
          std::string(spvOpcodeString(opcode));
 }
@@ -107,7 +107,8 @@
 )" + GetBody();
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeVoid)));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(GetErrorString(spv::Op::OpTypeVoid)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_bool) {
@@ -116,7 +117,8 @@
 )" + GetBody();
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeBool)));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(GetErrorString(spv::Op::OpTypeBool)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_int) {
@@ -125,7 +127,8 @@
 )" + GetBody();
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeInt)));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(GetErrorString(spv::Op::OpTypeInt)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_float) {
@@ -134,7 +137,8 @@
 )" + GetBody();
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeFloat)));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(GetErrorString(spv::Op::OpTypeFloat)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_vec3) {
@@ -144,7 +148,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypeVector)));
+              HasSubstr(GetErrorString(spv::Op::OpTypeVector)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_mat33) {
@@ -154,7 +158,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypeMatrix)));
+              HasSubstr(GetErrorString(spv::Op::OpTypeMatrix)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_vfunc) {
@@ -164,7 +168,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypeFunction)));
+              HasSubstr(GetErrorString(spv::Op::OpTypeFunction)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_pipe_storage) {
@@ -181,7 +185,7 @@
   CompileSuccessfully(str.c_str(), SPV_ENV_UNIVERSAL_1_1);
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypePipeStorage)));
+              HasSubstr(GetErrorString(spv::Op::OpTypePipeStorage)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_named_barrier) {
@@ -197,7 +201,7 @@
   CompileSuccessfully(str.c_str(), SPV_ENV_UNIVERSAL_1_1);
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypeNamedBarrier)));
+              HasSubstr(GetErrorString(spv::Op::OpTypeNamedBarrier)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_forward_pointer) {
@@ -234,7 +238,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              Not(HasSubstr(GetErrorString(SpvOpTypeVoid))));
+              Not(HasSubstr(GetErrorString(spv::Op::OpTypeVoid))));
 }
 
 TEST_F(ValidateTypeUnique, DuplicatePointerTypesNoExtension) {
@@ -263,7 +267,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              Not(HasSubstr(GetErrorString(SpvOpTypePointer))));
+              Not(HasSubstr(GetErrorString(spv::Op::OpTypePointer))));
 }
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/val/val_validation_state_test.cpp b/third_party/SPIRV-Tools/test/val/val_validation_state_test.cpp
index 3dd9e64..a5e88de 100644
--- a/third_party/SPIRV-Tools/test/val/val_validation_state_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_validation_state_test.cpp
@@ -180,7 +180,7 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
   EXPECT_EQ(size_t(1), vstate_->entry_points().size());
-  EXPECT_EQ(SpvOpFunction,
+  EXPECT_EQ(spv::Op::OpFunction,
             vstate_->FindDef(vstate_->entry_points()[0])->opcode());
 }
 
diff --git a/third_party/SPIRV-Tools/tools/cfg/bin_to_dot.cpp b/third_party/SPIRV-Tools/tools/cfg/bin_to_dot.cpp
index 72e7693..40a7dc4 100644
--- a/third_party/SPIRV-Tools/tools/cfg/bin_to_dot.cpp
+++ b/third_party/SPIRV-Tools/tools/cfg/bin_to_dot.cpp
@@ -81,26 +81,26 @@
 
 spv_result_t DotConverter::HandleInstruction(
     const spv_parsed_instruction_t& inst) {
-  switch (inst.opcode) {
-    case SpvOpFunction:
+  switch (spv::Op(inst.opcode)) {
+    case spv::Op::OpFunction:
       current_function_id_ = inst.result_id;
       seen_function_entry_block_ = false;
       break;
-    case SpvOpFunctionEnd:
+    case spv::Op::OpFunctionEnd:
       current_function_id_ = 0;
       break;
 
-    case SpvOpLabel:
+    case spv::Op::OpLabel:
       current_block_id_ = inst.result_id;
       break;
 
-    case SpvOpBranch:
+    case spv::Op::OpBranch:
       FlushBlock({inst.words[1]});
       break;
-    case SpvOpBranchConditional:
+    case spv::Op::OpBranchConditional:
       FlushBlock({inst.words[2], inst.words[3]});
       break;
-    case SpvOpSwitch: {
+    case spv::Op::OpSwitch: {
       std::vector<uint32_t> successors{inst.words[2]};
       for (size_t i = 3; i < inst.num_operands; i += 2) {
         successors.push_back(inst.words[inst.operands[i].offset]);
@@ -108,18 +108,18 @@
       FlushBlock(successors);
     } break;
 
-    case SpvOpKill:
-    case SpvOpReturn:
-    case SpvOpUnreachable:
-    case SpvOpReturnValue:
+    case spv::Op::OpKill:
+    case spv::Op::OpReturn:
+    case spv::Op::OpUnreachable:
+    case spv::Op::OpReturnValue:
       FlushBlock({});
       break;
 
-    case SpvOpLoopMerge:
+    case spv::Op::OpLoopMerge:
       merge_ = inst.words[1];
       continue_target_ = inst.words[2];
       break;
-    case SpvOpSelectionMerge:
+    case spv::Op::OpSelectionMerge:
       merge_ = inst.words[1];
       break;
     default:
diff --git a/third_party/SPIRV-Tools/utils/generate_grammar_tables.py b/third_party/SPIRV-Tools/utils/generate_grammar_tables.py
index 74aa282..6b7167b 100755
--- a/third_party/SPIRV-Tools/utils/generate_grammar_tables.py
+++ b/third_party/SPIRV-Tools/utils/generate_grammar_tables.py
@@ -33,6 +33,7 @@
 SPV_KHR_non_semantic_info
 """
 
+OUTPUT_LANGUAGE = 'c'
 
 def make_path_to_file(f):
     """Makes all ancestor directories to the given file, if they don't yet
@@ -76,9 +77,14 @@
       - caps: a sequence of capability names
 
     Returns:
-      a string containing the braced list of SpvCapability* enums named by caps.
+      a string containing the braced list of SpvCapability* or spv::Capability:: enums named by caps.
     """
-    return '{' + ', '.join(['SpvCapability{}'.format(c) for c in caps]) + '}'
+    base_string = 'SpvCapability'
+    global OUTPUT_LANGUAGE
+    if OUTPUT_LANGUAGE == 'c++':
+        base_string = 'spv::Capability::'
+
+    return '{' + ', '.join([(base_string + '{}').format(c) for c in caps]) + '}'
 
 
 def get_capability_array_name(caps):
@@ -99,8 +105,12 @@
       - caps: a sequence of sequence of capability names
     """
     caps = sorted(set([tuple(c) for c in caps if c]))
+    cap_str = 'SpvCapability'
+    global OUTPUT_LANGUAGE
+    if OUTPUT_LANGUAGE == 'c++':
+        cap_str = 'spv::Capability'
     arrays = [
-        'static const SpvCapability {}[] = {};'.format(
+        'static const ' + cap_str + ' {}[] = {};'.format(
             get_capability_array_name(c), compose_capability_list(c))
         for c in caps]
     return '\n'.join(arrays)
@@ -255,7 +265,12 @@
             self.operands.pop()
 
     def __str__(self):
-        template = ['{{"{opname}"', 'SpvOp{opname}',
+        global OUTPUT_LANGUAGE
+        base_str = 'SpvOp'
+        if OUTPUT_LANGUAGE == 'c++':
+            base_str = 'spv::Op::Op'
+
+        template = ['{{"{opname}"', base_str + '{opname}',
                     '{num_caps}', '{caps_mask}',
                     '{num_operands}', '{{{operands}}}',
                     '{def_result_id}', '{ref_type_id}',
@@ -634,9 +649,16 @@
 
     We take care to avoid emitting duplicate values.
     """
-    function = 'const char* CapabilityToString(SpvCapability capability) {\n'
+    cap_str = 'SpvCapability'
+    cap_join = ''
+    global OUTPUT_LANGUAGE
+    if OUTPUT_LANGUAGE == 'c++':
+        cap_str = 'spv::Capability'
+        cap_join = '::'
+
+    function = 'const char* CapabilityToString(' + cap_str + ' capability) {\n'
     function += '  switch (capability) {\n'
-    template = '    case SpvCapability{capability}:\n' \
+    template = '    case ' + cap_str + cap_join + '{capability}:\n' \
         '      return "{capability}";\n'
     emitted = set()  # The values of capabilities we already have emitted
     for capability in get_capabilities(operand_kinds):
@@ -644,8 +666,8 @@
         if value not in emitted:
             emitted.add(value)
             function += template.format(capability=capability.get('enumerant'))
-    function += '    case SpvCapabilityMax:\n' \
-        '      assert(0 && "Attempting to convert SpvCapabilityMax to string");\n' \
+    function += '    case ' + cap_str + cap_join + 'Max:\n' \
+        '      assert(0 && "Attempting to convert ' + cap_str + cap_join + 'Max to string");\n' \
         '      return "";\n'
     function += '  }\n\n  return "";\n}'
     return function
@@ -734,6 +756,10 @@
                         type=str, required=False, default=None,
                         help='input JSON grammar file for OpenCL extended '
                         'instruction set')
+    parser.add_argument('--output-language',
+                        type=str, required=False, default='c',
+                        choices=['c','c++'],
+                        help='specify output language type')
 
     parser.add_argument('--core-insts-output', metavar='<path>',
                         type=str, required=False, default=None,
@@ -765,6 +791,9 @@
                         help='prefix for operand kinds (to disambiguate operand type enums)')
     args = parser.parse_args()
 
+    global OUTPUT_LANGUAGE
+    OUTPUT_LANGUAGE = args.output_language
+
     # The GN build system needs this because it doesn't handle quoting
     # empty string arguments well.
     if args.vendor_operand_kind_prefix == "...nil...":