Update SPIR-V Tools to 0174dd11f

Changes:
    0174dd11ff8 BUILD.gn: Make MSVC report the correct __cplusplus value (#5088)
    64ba112ffb1 build: refactorize update_build_version (#5079)
    96c5dac559f Roll external/re2/ ba541565b..8afcf7fcc (1 commit) (#5085)
    5db6c38e656 Revert "spirv-val: Initial SPV_EXT_mesh_shader builtins (#5080)" (#5084)
    57fb3c7a3f1 Align git-sync-deps and CMake to use external/spirv-headers by default (#4963)
    af15e5adeab Roll external/re2/ 954656f47..ba541565b (1 commit) (#5083)
    7f9184a5b21 kokoro: fix dubious ownership (#5082)
    fe087cd5f0e Revert "kokoro: fix dubious ownership (#5078)" (#5081)
    f0b900ed9a1 spirv-val: Initial SPV_EXT_mesh_shader builtins (#5080)
    8fbb53dae49 kokoro: fix dubious ownership (#5078)
    cdc4e528f3d build: move from c++11 to c++17 (#4983)
    c51e2afe001 Add kokoro:run label to autoroll PRs (#5077)
    b6498eac1e0 Limit when the github action bazel builds run (#5071)
    bb1c885956e Roll external/spirv-headers/ d13b52222..aa331ab0f (5 commits) (#5074)
    bebca22e2d4 Rename bot in autoroll.yml (#5072)
    1e85dca570f Add VS2019 kokoro configs (#5059)
    4683eab649c Create a github action to update DEPS (#5061)
    f36a8d47f73 Start v2023.2 release. (#5066)
    63de608daeb Finalize v2023.1 release. (#5065)
    b184efe2d4c Revert "Finalize v2023.1 release (#5062)" (#5064)
    0fc5526f2b0 Finalize v2023.1 release (#5062)
    30e51ceaab2 Add #5049 to release v2023.1. (#5058)
    ba4c9fe5346 Instrument: Fix bindless checking for BufferDeviceAddress (#5049)
    0e6fbba7762 Prepare for v2023.1 release (#5057)
    1dad9914410 cmake: Modernize install(TARGET) usage (#5056)
    ae893db200e cmake: Remove old policy code (#5055)
    ae8d50709fc Add Github Actions to test Bazel builds. (#5043)
    7e8813bb4cf Validate version 5 of clspv reflection (#5050)
    bfd278617c3 utils: repos use 'main' as main devlopment branch (#5054)
    631f9bcb5e6 Update README.md: Development occurs on the "main" branch (#5053)
    f62e121b0df spirv-val: Use more specific term 'switch header' in error message (#5048)
    d87f61605b3 DEPS: update to last googletest release supporting C++11 (#5045)
    f416d39bb80 Bazel: Use @platforms//os:windows instead of @build_tools//src/conditions:windows (#5042)
    077b09c32a9 Add exported CMake config file for binaries in ./tools/ (#5034)
    bbdd0fefda0 Update minimum required CMake to 3.17.2 (#5041)
    01a3b9bec73 git-sync-deps: Use argparse, and print better help (#5038)
    6b5a00eb2ba Kokoro CI bots use git-sync-deps to get sources (#5031)
    c5d23164305 Enforce layering_check in Bazel build rules. (#5032)
    5bec0884cfa Remove testing support for VS2015 (#5027)
    29375382108 Fix undef behaviour in hex float parsing (#5025)
    025ea891faa Optimize allocation of spvtools::opt::Instruction::operands_ (#5024)
    1c287b03d3d First attempt to set up CI-windows-msvc-2017-release-bazel build (#5023)
    f64a4b64b72 [spirv-opt] Clone names for new struct in EliminateIODeadComponents (#5016)
    cc81529f4b1 Test operator overloads for SPIR-V C++ mask enums (#5021)
    5a78d798f7b Fix layout validation (#5015)
    451ba8ec3df README.md: The validator now handles larger limits (#5003)
    6b2318aec8d Fix for bug https://github.com/KhronosGroup/SPIRV-Tools/issues/5017 (#5019)
    5d6adbdee06 Require C++11 *or later* (#5020)

Commands:
    ./third_party/update-spirvtools.sh

Bug: b/123642959
Change-Id: I0ccf8a7c483f3be9aa37f2e749e02e6d5afdeb5e
diff --git a/third_party/SPIRV-Tools/.bazelversion b/third_party/SPIRV-Tools/.bazelversion
new file mode 100644
index 0000000..28cbf7c
--- /dev/null
+++ b/third_party/SPIRV-Tools/.bazelversion
@@ -0,0 +1 @@
+5.0.0
\ No newline at end of file
diff --git a/third_party/SPIRV-Tools/.github/workflows/autoroll.yml b/third_party/SPIRV-Tools/.github/workflows/autoroll.yml
new file mode 100644
index 0000000..a33034b
--- /dev/null
+++ b/third_party/SPIRV-Tools/.github/workflows/autoroll.yml
@@ -0,0 +1,48 @@
+name: Update dependencies
+
+on:
+  schedule:
+    - cron: '0 2 * * *'
+  workflow_dispatch:
+
+jobs:
+  update-dependencies:
+    name: Update dependencies
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v3
+
+      # Checkout the depot tools they are needed by roll_deps.sh
+      - name: Checkout depot tools
+        run: git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
+
+      - name: Update PATH
+        run: echo "./depot_tools" >> $GITHUB_PATH
+
+      - name: Download dependencies
+        run: python3 utils/git-sync-deps
+
+      - name: Setup git user information
+        run: |
+          git config user.name "GitHub Actions[bot]"
+          git config user.email "<>"
+          git checkout -b roll_deps
+
+      - name: Update dependencies
+        run: |
+          utils/roll_deps.sh
+          if [[ `git diff HEAD..origin/main --name-only | wc -l` == 0 ]]; then
+            echo "changed=false" >> $GITHUB_OUTPUT
+          else
+            echo "changed=true" >> $GITHUB_OUTPUT
+          fi
+        id: update_dependencies
+     
+      - name: Push changes and create PR
+        if: steps.update_dependencies.outputs.changed == 'true'
+        run: |
+          git push --force --set-upstream origin roll_deps
+          gh pr create --label 'kokoro:run' --base main -f -r s-perron
+        env:
+          GITHUB_TOKEN: ${{ github.token }}
diff --git a/third_party/SPIRV-Tools/.github/workflows/bazel.yml b/third_party/SPIRV-Tools/.github/workflows/bazel.yml
new file mode 100644
index 0000000..77ef657
--- /dev/null
+++ b/third_party/SPIRV-Tools/.github/workflows/bazel.yml
@@ -0,0 +1,32 @@
+name: Build and Test with Bazel
+
+on:
+  push:
+    branches:
+      - 'main'
+  pull_request:
+
+jobs:
+  build:
+    timeout-minutes: 120
+    strategy:
+      matrix:
+        os: [ubuntu-latest, macos-latest, windows-latest]
+
+    runs-on: ${{matrix.os}}
+
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: '0'
+      - name: Download dependencies
+        run: python3 utils/git-sync-deps
+      - name: Mount Bazel cache
+        uses: actions/cache@v3
+        with:
+          path: ~/.bazel/cache
+          key: bazel-cache-${{ runner.os }}
+      - name: Build All
+        run: bazel --output_user_root=~/.bazel/cache build //...
+      - name: Test All
+        run: bazel --output_user_root=~/.bazel/cache test //...
diff --git a/third_party/SPIRV-Tools/.github/workflows/wasm.yml b/third_party/SPIRV-Tools/.github/workflows/wasm.yml
index d9a9c5c..fa8951a 100644
--- a/third_party/SPIRV-Tools/.github/workflows/wasm.yml
+++ b/third_party/SPIRV-Tools/.github/workflows/wasm.yml
@@ -1,14 +1,16 @@
 name: Wasm Build
 
-on: [ push, pull_request ]
+on: [push, pull_request]
 
 jobs:
   build:
     runs-on: ubuntu-latest
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: '0'
       - name: Build web
-        run: docker-compose up
+        run: docker-compose -f source/wasm/docker-compose.yml --project-directory . up
       - name: Run tests
         run: node test/wasm/test.js
diff --git a/third_party/SPIRV-Tools/BUILD.bazel b/third_party/SPIRV-Tools/BUILD.bazel
index 0af7700..255d4e7 100644
--- a/third_party/SPIRV-Tools/BUILD.bazel
+++ b/third_party/SPIRV-Tools/BUILD.bazel
@@ -1,27 +1,24 @@
 load(
     ":build_defs.bzl",
+    "CLDEBUGINFO100_GRAMMAR_JSON_FILE",
     "COMMON_COPTS",
     "DEBUGINFO_GRAMMAR_JSON_FILE",
-    "CLDEBUGINFO100_GRAMMAR_JSON_FILE",
     "SHDEBUGINFO100_GRAMMAR_JSON_FILE",
     "TEST_COPTS",
-    "base_test",
     "generate_core_tables",
     "generate_enum_string_mapping",
     "generate_extinst_lang_headers",
     "generate_glsl_tables",
     "generate_opencl_tables",
     "generate_vendor_tables",
-    "link_test",
-    "lint_test",
-    "opt_test",
-    "reduce_test",
-    "util_test",
-    "val_test",
+    "incompatible_with",
 )
 
 package(
     default_visibility = ["//visibility:private"],
+    features = [
+        "layering_check",
+    ],
 )
 
 licenses(["notice"])
@@ -41,35 +38,50 @@
     srcs = ["utils/generate_language_headers.py"],
 )
 
-generate_core_tables("unified1")
+generate_core_tables(version = "unified1")
 
-generate_enum_string_mapping("unified1")
+generate_enum_string_mapping(version = "unified1")
 
-generate_opencl_tables("unified1")
+generate_opencl_tables(version = "unified1")
 
-generate_glsl_tables("unified1")
+generate_glsl_tables(version = "unified1")
 
-generate_vendor_tables("spv-amd-shader-explicit-vertex-parameter")
+generate_vendor_tables(extension = "spv-amd-shader-explicit-vertex-parameter")
 
-generate_vendor_tables("spv-amd-shader-trinary-minmax")
+generate_vendor_tables(extension = "spv-amd-shader-trinary-minmax")
 
-generate_vendor_tables("spv-amd-gcn-shader")
+generate_vendor_tables(extension = "spv-amd-gcn-shader")
 
-generate_vendor_tables("spv-amd-shader-ballot")
+generate_vendor_tables(extension = "spv-amd-shader-ballot")
 
-generate_vendor_tables("debuginfo")
+generate_vendor_tables(extension = "debuginfo")
 
-generate_vendor_tables("opencl.debuginfo.100", "CLDEBUG100_")
+generate_vendor_tables(extension = "nonsemantic.clspvreflection")
 
-generate_vendor_tables("nonsemantic.shader.debuginfo.100", "SHDEBUG100_")
+generate_vendor_tables(
+    extension = "opencl.debuginfo.100",
+    operand_kind_prefix = "CLDEBUG100_",
+)
 
-generate_vendor_tables("nonsemantic.clspvreflection")
+generate_vendor_tables(
+    extension = "nonsemantic.shader.debuginfo.100",
+    operand_kind_prefix = "SHDEBUG100_",
+)
 
-generate_extinst_lang_headers("DebugInfo", DEBUGINFO_GRAMMAR_JSON_FILE)
+generate_extinst_lang_headers(
+    name = "DebugInfo",
+    grammar = DEBUGINFO_GRAMMAR_JSON_FILE,
+)
 
-generate_extinst_lang_headers("OpenCLDebugInfo100", CLDEBUGINFO100_GRAMMAR_JSON_FILE)
+generate_extinst_lang_headers(
+    name = "OpenCLDebugInfo100",
+    grammar = CLDEBUGINFO100_GRAMMAR_JSON_FILE,
+)
 
-generate_extinst_lang_headers("NonSemanticShaderDebugInfo100", SHDEBUGINFO100_GRAMMAR_JSON_FILE)
+generate_extinst_lang_headers(
+    name = "NonSemanticShaderDebugInfo100",
+    grammar = SHDEBUGINFO100_GRAMMAR_JSON_FILE,
+)
 
 py_binary(
     name = "generate_registry_tables",
@@ -77,11 +89,11 @@
 )
 
 genrule(
-    name = "gen_registry_tables",
+    name = "generators_inc",
     srcs = ["@spirv_headers//:spirv_xml_registry"],
     outs = ["generators.inc"],
-    cmd = "$(location generate_registry_tables) --xml=$(location @spirv_headers//:spirv_xml_registry) --generator-output=$(location generators.inc)",
-    cmd_bat = "$(location //:generate_registry_tables) --xml=$(location @spirv_headers//:spirv_xml_registry) --generator-output=$(location generators.inc)",
+    cmd = "$(location :generate_registry_tables) --xml=$(location @spirv_headers//:spirv_xml_registry) --generator-output=$(location generators.inc)",
+    cmd_bat = "$(location :generate_registry_tables) --xml=$(location @spirv_headers//:spirv_xml_registry) --generator-output=$(location generators.inc)",
     exec_tools = [":generate_registry_tables"],
 )
 
@@ -91,120 +103,102 @@
 )
 
 genrule(
-    name = "gen_build_version",
+    name = "build_version_inc",
     srcs = ["CHANGES"],
     outs = ["build-version.inc"],
-    cmd = "SOURCE_DATE_EPOCH=0 $(location update_build_version) $(location CHANGES) $(location build-version.inc)",
-    cmd_bat = "set SOURCE_DATE_EPOCH=0  && $(location //:update_build_version) $(location CHANGES) $(location build-version.inc)",
+    cmd = "SOURCE_DATE_EPOCH=0 $(location :update_build_version) $(location CHANGES) $(location build-version.inc)",
+    cmd_bat = "set SOURCE_DATE_EPOCH=0  && $(location :update_build_version) $(location CHANGES) $(location build-version.inc)",
     exec_tools = [":update_build_version"],
 )
 
 # Libraries
 
 cc_library(
-    name = "generated_headers",
+    name = "spirv_tools",
     hdrs = [
-        ":gen_build_version",
+        "include/spirv-tools/libspirv.h",
+        "include/spirv-tools/libspirv.hpp",
+    ],
+    copts = COMMON_COPTS,
+    includes = ["include"],
+    linkstatic = 1,
+    visibility = ["//visibility:public"],
+    deps = [
+        ":spirv_tools_internal",
+    ],
+)
+
+cc_library(
+    name = "spirv_tools_internal",
+    srcs = glob([
+        "source/*.cpp",
+        "source/util/*.cpp",
+        "source/val/*.cpp",
+    ]) + [
+        ":build_version_inc",
         ":gen_core_tables_unified1",
         ":gen_enum_string_mapping",
         ":gen_extinst_lang_headers_DebugInfo",
-        ":gen_extinst_lang_headers_OpenCLDebugInfo100",
         ":gen_extinst_lang_headers_NonSemanticShaderDebugInfo100",
+        ":gen_extinst_lang_headers_OpenCLDebugInfo100",
         ":gen_glsl_tables_unified1",
         ":gen_opencl_tables_unified1",
-        ":gen_registry_tables",
+        ":generators_inc",
         ":gen_vendor_tables_debuginfo",
         ":gen_vendor_tables_nonsemantic_clspvreflection",
-        ":gen_vendor_tables_opencl_debuginfo_100",
         ":gen_vendor_tables_nonsemantic_shader_debuginfo_100",
+        ":gen_vendor_tables_opencl_debuginfo_100",
         ":gen_vendor_tables_spv_amd_gcn_shader",
         ":gen_vendor_tables_spv_amd_shader_ballot",
         ":gen_vendor_tables_spv_amd_shader_explicit_vertex_parameter",
         ":gen_vendor_tables_spv_amd_shader_trinary_minmax",
     ],
-    copts = COMMON_COPTS,
-)
-
-cc_library(
-    name = "spirv_tools_headers",
-    hdrs = glob([
+    hdrs = [
         "include/spirv-tools/libspirv.h",
         "include/spirv-tools/libspirv.hpp",
+        ":gen_extinst_lang_headers_DebugInfo",
+        ":gen_extinst_lang_headers_NonSemanticShaderDebugInfo100",
+        ":gen_extinst_lang_headers_OpenCLDebugInfo100",
+    ] + glob([
         "source/*.h",
         "source/util/*.h",
         "source/val/*.h",
     ]),
     copts = COMMON_COPTS,
-    includes = ["source"],
-    deps = [
-        "@spirv_headers//:spirv_cpp11_headers",
-    ],
-)
-
-cc_library(
-    name = "spirv_tools",
-    srcs = glob([
-        "source/*.cpp",
-        "source/util/*.cpp",
-        "source/val/*.cpp",
-    ]),
-    hdrs = [
-        "include/spirv-tools/libspirv.h",
-        "include/spirv-tools/libspirv.hpp",
-    ],
-    copts = COMMON_COPTS + select({
-        "@bazel_tools//src/conditions:windows": [""],
-        "//conditions:default": ["-Wno-implicit-fallthrough"],
-    }),
     includes = ["include"],
-    linkstatic = 1,
-    visibility = ["//visibility:public"],
     deps = [
-        ":generated_headers",
-        ":spirv_tools_headers",
+        "@spirv_headers//:spirv_common_headers",
         "@spirv_headers//:spirv_cpp11_headers",
-        "@spirv_headers//:spirv_common_headers",
     ],
 )
 
 cc_library(
-    name = "spirv_tools_comp",
-    srcs = glob([
-        "source/comp/*.cpp",
-        "source/comp/*.h",
-    ]),
-    copts = COMMON_COPTS,
-    linkstatic = 1,
-    visibility = ["//visibility:public"],
-    deps = [
-        ":generated_headers",
-        ":spirv_tools",
-        ":spirv_tools_headers",
-        "@spirv_headers//:spirv_common_headers",
-    ],
-)
-
-cc_library(
-    name = "spirv_tools_opt_headers",
-    hdrs = glob(["source/opt/*.h"]),
-    copts = COMMON_COPTS,
-)
-
-cc_library(
     name = "spirv_tools_opt",
-    srcs = glob(["source/opt/*.cpp"]),
     hdrs = [
         "include/spirv-tools/instrument.hpp",
         "include/spirv-tools/optimizer.hpp",
     ],
     copts = COMMON_COPTS,
-    includes = ["include"],
     linkstatic = 1,
     visibility = ["//visibility:public"],
     deps = [
         ":spirv_tools",
-        ":spirv_tools_headers",
-        ":spirv_tools_opt_headers",
+        ":spirv_tools_opt_internal",
+    ],
+)
+
+cc_library(
+    name = "spirv_tools_opt_internal",
+    srcs = glob(["source/opt/*.cpp"]) + [
+        ":gen_vendor_tables_spv_amd_shader_ballot",
+    ],
+    hdrs = glob(["source/opt/*.h"]) + [
+        "include/spirv-tools/instrument.hpp",
+        "include/spirv-tools/optimizer.hpp",
+    ],
+    copts = COMMON_COPTS,
+    deps = [
+        ":spirv_tools_internal",
         "@spirv_headers//:spirv_common_headers",
     ],
 )
@@ -214,11 +208,9 @@
     srcs = glob(["source/reduce/*.cpp"]),
     hdrs = glob(["source/reduce/*.h"]),
     copts = COMMON_COPTS,
-    linkstatic = 1,
-    visibility = ["//visibility:public"],
     deps = [
-        ":spirv_tools",
-        ":spirv_tools_opt",
+        ":spirv_tools_internal",
+        ":spirv_tools_opt_internal",
     ],
 )
 
@@ -230,21 +222,38 @@
     linkstatic = 1,
     visibility = ["//visibility:public"],
     deps = [
-        ":spirv_tools",
-        ":spirv_tools_opt",
+        ":spirv_tools_internal",
+        ":spirv_tools_opt_internal",
+    ],
+)
+
+cc_library(
+    name = "spirv_tools_lint_internal",
+    srcs = glob([
+        "source/lint/*.cpp",
+        "source/lint/*.h",
+    ]),
+    hdrs = ["include/spirv-tools/linter.hpp"] + glob([
+        "source/lint/*.h",
+    ]),
+    copts = COMMON_COPTS,
+    includes = ["include"],
+    deps = [
+        ":spirv_tools_internal",
+        ":spirv_tools_opt_internal",
     ],
 )
 
 cc_library(
     name = "spirv_tools_lint",
-    srcs = glob(["source/lint/*.cpp", "source/lint/*.h"]),
     hdrs = ["include/spirv-tools/linter.hpp"],
     copts = COMMON_COPTS,
+    includes = ["include"],
     linkstatic = 1,
     visibility = ["//visibility:public"],
     deps = [
         ":spirv_tools",
-        ":spirv_tools_opt",
+        ":spirv_tools_lint_internal",
     ],
 )
 
@@ -253,23 +262,27 @@
     srcs = glob(["tools/util/*.cpp"]),
     hdrs = glob(["tools/util/*.h"]),
     copts = COMMON_COPTS,
-    linkstatic = 1,
-    visibility = ["//visibility:public"],
     deps = [":spirv_tools"],
 )
 
+cc_library(
+    name = "tools_io",
+    hdrs = ["tools/io.h"],
+    copts = COMMON_COPTS,
+)
+
 # Tools
 
 cc_binary(
     name = "spirv-as",
     srcs = [
         "tools/as/as.cpp",
-        "tools/io.h",
     ],
     copts = COMMON_COPTS,
     visibility = ["//visibility:public"],
     deps = [
-        ":spirv_tools",
+        ":spirv_tools_internal",
+        ":tools_io",
     ],
 )
 
@@ -277,25 +290,25 @@
     name = "spirv-dis",
     srcs = [
         "tools/dis/dis.cpp",
-        "tools/io.h",
     ],
     copts = COMMON_COPTS,
     visibility = ["//visibility:public"],
     deps = [
         ":spirv_tools",
+        ":tools_io",
     ],
 )
 
 cc_binary(
     name = "spirv-val",
     srcs = [
-        "tools/io.h",
         "tools/val/val.cpp",
     ],
     copts = COMMON_COPTS,
     visibility = ["//visibility:public"],
     deps = [
-        ":spirv_tools",
+        ":spirv_tools_internal",
+        ":tools_io",
         ":tools_util",
     ],
 )
@@ -303,14 +316,14 @@
 cc_binary(
     name = "spirv-opt",
     srcs = [
-        "tools/io.h",
         "tools/opt/opt.cpp",
     ],
     copts = COMMON_COPTS,
     visibility = ["//visibility:public"],
     deps = [
-        ":spirv_tools",
-        ":spirv_tools_opt",
+        ":spirv_tools_internal",
+        ":spirv_tools_opt_internal",
+        ":tools_io",
         ":tools_util",
     ],
 )
@@ -318,15 +331,15 @@
 cc_binary(
     name = "spirv-reduce",
     srcs = [
-        "tools/io.h",
         "tools/reduce/reduce.cpp",
     ],
     copts = COMMON_COPTS,
     visibility = ["//visibility:public"],
     deps = [
-        ":spirv_tools",
-        ":spirv_tools_opt",
+        ":spirv_tools_internal",
+        ":spirv_tools_opt_internal",
         ":spirv_tools_reduce",
+        ":tools_io",
         ":tools_util",
     ],
 )
@@ -334,28 +347,28 @@
 cc_binary(
     name = "spirv-link",
     srcs = [
-        "tools/io.h",
         "tools/link/linker.cpp",
     ],
     copts = COMMON_COPTS,
     visibility = ["//visibility:public"],
     deps = [
-        ":spirv_tools",
+        ":spirv_tools_internal",
         ":spirv_tools_link",
+        ":tools_io",
     ],
 )
 
 cc_binary(
     name = "spirv-lint",
     srcs = [
-        "tools/io.h",
         "tools/lint/lint.cpp",
     ],
     copts = COMMON_COPTS,
     visibility = ["//visibility:public"],
     deps = [
-        ":spirv_tools",
         ":spirv_tools_lint",
+        ":spirv_tools_opt_internal",
+        ":tools_io",
         ":tools_util",
     ],
 )
@@ -366,50 +379,152 @@
         "tools/cfg/bin_to_dot.cpp",
         "tools/cfg/bin_to_dot.h",
         "tools/cfg/cfg.cpp",
-        "tools/io.h",
     ],
     copts = COMMON_COPTS,
     visibility = ["//visibility:public"],
-    deps = [":spirv_tools"],
+    deps = [
+        ":spirv_tools_internal",
+        ":tools_io",
+    ],
 )
 
 # Unit tests
 
 cc_library(
-    name = "test_common",
+    name = "test_lib",
     testonly = 1,
     srcs = [
-        "test/test_fixture.h",
         "test/unit_spirv.cpp",
+    ],
+    hdrs = [
+        "test/test_fixture.h",
         "test/unit_spirv.h",
     ],
-    compatible_with = [],
     copts = TEST_COPTS,
-    includes = ["test"],
-    linkstatic = 1,
     deps = [
-        ":spirv_tools",
+        ":spirv_tools_internal",
         "@com_google_googletest//:gtest",
     ],
 )
 
-cc_library(
-    name = "link_test_common",
-    testonly = 1,
-    srcs = ["test/link/linker_fixture.h"],
-    compatible_with = [],
+# PCH (precompiled header) tests only work when using CMake and MSVC on Windows,
+# so they will be skipped in the Bazel builds.
+
+[cc_test(
+    name = "base_{testcase}_test".format(testcase = f[len("test/"):-len("_test.cpp")]),
+    size = "small",
+    srcs = [f],
+    copts = TEST_COPTS,
+    linkstatic = 1,
+    target_compatible_with = {
+        "test/timer_test.cpp": incompatible_with(["@bazel_tools//src/conditions:windows"]),
+    }.get(f, []),
+    deps = [
+        ":spirv_tools_internal",
+        ":test_lib",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+) for f in glob(
+    ["test/*_test.cpp"],
+    exclude = [
+        "test/cpp_interface_test.cpp",
+        "test/log_test.cpp",
+        "test/pch_test.cpp",
+    ],
+)]
+
+cc_test(
+    name = "base_cpp_interface_test",
+    size = "small",
+    srcs = ["test/cpp_interface_test.cpp"],
+    linkstatic = 1,
+    deps = [
+        ":spirv_tools_opt_internal",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+        "@spirv_headers//:spirv_cpp11_headers",
+    ],
+)
+
+cc_test(
+    name = "base_ilist_test",
+    size = "small",
+    srcs = ["test/util/ilist_test.cpp"],
     copts = TEST_COPTS,
     linkstatic = 1,
     deps = [
-        ":spirv_tools_link",
-        ":test_common",
+        ":spirv_tools_internal",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "base_log_test",
+    size = "small",
+    srcs = ["test/log_test.cpp"],
+    copts = TEST_COPTS,
+    linkstatic = 1,
+    deps = [
+        ":spirv_tools_opt_internal",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
     ],
 )
 
 cc_library(
-    name = "opt_test_common",
+    name = "link_test_lib",
     testonly = 1,
-    srcs = ["test/opt/pass_utils.cpp"],
+    hdrs = ["test/link/linker_fixture.h"],
+    copts = TEST_COPTS,
+    deps = [
+        ":spirv_tools_internal",
+        ":spirv_tools_link",
+        ":test_lib",
+        "@com_google_effcee//:effcee",
+        "@com_googlesource_code_re2//:re2",
+    ],
+)
+
+[cc_test(
+    name = "link_{testcase}_test".format(testcase = f[len("test/link/"):-len("_test.cpp")]),
+    size = "small",
+    srcs = [f],
+    copts = TEST_COPTS,
+    linkstatic = 1,
+    deps = [
+        ":link_test_lib",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+) for f in glob(
+    ["test/link/*_test.cpp"],
+)]
+
+[cc_test(
+    name = "lint_{testcase}_test".format(testcase = f[len("test/lint/"):-len("_test.cpp")]),
+    size = "small",
+    srcs = [f],
+    copts = TEST_COPTS,
+    linkstatic = 1,
+    deps = [
+        ":spirv_tools",
+        ":spirv_tools_lint_internal",
+        ":spirv_tools_opt_internal",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+) for f in glob(
+    ["test/lint/*_test.cpp"],
+)]
+
+cc_library(
+    name = "opt_test_lib",
+    testonly = 1,
+    srcs = [
+        "test/opt/pass_utils.cpp",
+    ],
     hdrs = [
         "test/opt/assembly_builder.h",
         "test/opt/function_utils.h",
@@ -417,143 +532,181 @@
         "test/opt/pass_fixture.h",
         "test/opt/pass_utils.h",
     ],
-    compatible_with = [],
+    copts = TEST_COPTS,
+    deps = [
+        ":spirv_tools_internal",
+        ":spirv_tools_opt_internal",
+        "@com_google_effcee//:effcee",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+[cc_test(
+    name = "opt_{testcase}_test".format(testcase = f[len("test/opt/"):-len("_test.cpp")]),
+    size = "small",
+    srcs = [f],
     copts = TEST_COPTS,
     linkstatic = 1,
     deps = [
-        ":spirv_tools_opt",
-        ":test_common",
+        ":opt_test_lib",
+        ":spirv_tools_internal",
+        ":spirv_tools_opt_internal",
+        ":test_lib",
+        "@com_google_effcee//:effcee",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
     ],
-)
+) for f in glob(["test/opt/*_test.cpp"])]
 
-cc_library(
-    name = "reduce_test_common",
-    testonly = 1,
-    srcs = [
-        "test/reduce/reduce_test_util.cpp",
-        "tools/io.h",
-    ],
-    hdrs = ["test/reduce/reduce_test_util.h"],
-    compatible_with = [],
+[cc_test(
+    name = "opt_dom_tree_{testcase}_test".format(testcase = f[len("test/opt/dominator_tree/"):-len(".cpp")]),
+    size = "small",
+    srcs = [f],
     copts = TEST_COPTS,
     linkstatic = 1,
     deps = [
-        ":spirv_tools_reduce",
-        ":test_common",
+        ":opt_test_lib",
+        ":spirv_tools_opt_internal",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
     ],
-)
-
-cc_library(
-    name = "val_test_common",
-    testonly = 1,
-    srcs = [
-        "test/val/val_code_generator.cpp",
-        "test/val/val_fixtures.h",
-    ],
-    hdrs = [
-        "test/val/val_code_generator.h",
-    ],
-    compatible_with = [],
-    copts = TEST_COPTS,
-    linkstatic = 1,
-    deps = [":test_common"],
-)
-
-# PCH (precompiled header) tests only work when using CMake and MSVC on Windows,
-# so they will be skipped in the Bazel builds.
-
-[base_test(
-    name = f[5:-4],  # strip test/, .cpp
-    srcs = [f],
-) for f in glob(
-    ["test/*.cpp"],
-    exclude = [
-        "test/cpp_interface_test.cpp", # has its own base_test below.
-        "test/log_test.cpp", # has its own base_test below.
-        "test/pch_test.cpp", # pch tests are skipped.
-        "test/timer_test.cpp", # has its own base_test below.
-    ],
-)]
-
-# This test uses unistd.h and does not run on Windows.
-base_test(
-    name = "timer_test",
-    srcs = select({
-        "@bazel_tools//src/conditions:windows": [],
-        "//conditions:default": ["test/timer_test.cpp"],
-    }),
-)
-
-base_test(
-    name = "cpp_interface_test",
-    srcs = ["test/cpp_interface_test.cpp"],
-    deps = [":spirv_tools_opt"],
-)
-
-base_test(
-    name = "log_test",
-    srcs = ["test/log_test.cpp"],
-    deps = [":spirv_tools_opt"],
-)
-
-[link_test(
-    name = f[10:-4],  # strip test/link/, .cpp
-    srcs = [f],
-) for f in glob(
-    ["test/link/*.cpp"],
-)]
-
-[lint_test(
-    name = f[10:-4],  # strip test/lint/, .cpp
-    srcs = [f],
-) for f in glob(
-    ["test/lint/*.cpp"],
-)]
-
-[opt_test(
-    name = f[9:-4],  # strip test/opt/, .cpp
-    srcs = [f],
-) for f in glob(
-    ["test/opt/*.cpp"],
-    # pch tests are skipped.
-    exclude = ["test/opt/pch_test_opt.cpp"],
-)]
-
-[opt_test(
-    name = "dom_tree_" + f[24:-4],  # strip test/opt/dominator_tree/, .cpp
-    srcs = [f],
 ) for f in glob(
     ["test/opt/dominator_tree/*.cpp"],
-    # pch tests are skipped.
     exclude = ["test/opt/dominator_tree/pch_test_opt_dom.cpp"],
 )]
 
-[opt_test(
-    name = "loop_" + f[28:-4],  # strip test/opt/loop_optimizations/, .cpp
+[cc_test(
+    name = "opt_loop_{testcase}_test".format(testcase = f[len("test/opt/loop_optimizations/"):-len(".cpp")]),
+    size = "small",
     srcs = [f],
+    copts = TEST_COPTS,
+    linkstatic = 1,
+    deps = [
+        ":opt_test_lib",
+        ":spirv_tools",
+        ":spirv_tools_opt_internal",
+        "@com_google_effcee//:effcee",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
 ) for f in glob(
     ["test/opt/loop_optimizations/*.cpp"],
-    # pch tests are skipped.
     exclude = ["test/opt/loop_optimizations/pch_test_opt_loop.cpp"],
 )]
 
-[reduce_test(
-    name = f[12:-4],  # strip test/reduce/, .cpp
-    srcs = [f],
-) for f in glob(["test/reduce/*.cpp"])]
+cc_library(
+    name = "reduce_test_lib",
+    testonly = 1,
+    srcs = [
+        "test/reduce/reduce_test_util.cpp",
+    ],
+    hdrs = ["test/reduce/reduce_test_util.h"],
+    copts = TEST_COPTS,
+    deps = [
+        ":spirv_tools",
+        ":spirv_tools_opt_internal",
+        ":spirv_tools_reduce",
+        ":test_lib",
+        ":tools_io",
+        "@com_google_googletest//:gtest",
+    ],
+)
 
-[util_test(
-    name = f[10:-4],  # strip test/util/, .cpp
+[cc_test(
+    name = "reduce_{testcase}_test".format(testcase = f[len("test/reduce/"):-len("_test.cpp")]),
+    size = "small",
     srcs = [f],
-) for f in glob(["test/util/*.cpp"])]
+    copts = TEST_COPTS,
+    linkstatic = 1,
+    deps = [
+        ":reduce_test_lib",
+        ":spirv_tools_internal",
+        ":spirv_tools_opt_internal",
+        ":spirv_tools_reduce",
+        "@com_google_googletest//:gtest_main",
+    ],
+) for f in glob(["test/reduce/*_test.cpp"])]
 
-[val_test(
-    name = f[9:-4],  # strip test/val/, .cpp
+[cc_test(
+    name = "util_{testcase}_test".format(testcase = f[len("test/util/"):-len("_test.cpp")]),
+    size = "small",
     srcs = [f],
+    copts = TEST_COPTS,
+    linkstatic = 1,
+    deps = [
+        ":spirv_tools_internal",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+) for f in glob(["test/util/*_test.cpp"])]
+
+cc_library(
+    name = "val_test_lib",
+    testonly = 1,
+    srcs = [
+        "test/val/val_code_generator.cpp",
+    ],
+    hdrs = [
+        "test/val/val_code_generator.h",
+        "test/val/val_fixtures.h",
+    ],
+    copts = TEST_COPTS,
+    deps = [
+        ":spirv_tools_internal",
+        ":test_lib",
+    ],
+)
+
+[cc_test(
+    name = "val_{testcase}_test".format(testcase = f[len("test/val/val_"):-len("_test.cpp")]),
+    size = "small",
+    srcs = [f],
+    copts = TEST_COPTS,
+    linkstatic = 1,
+    deps = [
+        ":spirv_tools_internal",
+        ":test_lib",
+        ":val_test_lib",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
 ) for f in glob(
-    ["test/val/*.cpp"],
+    ["test/val/val_*_test.cpp"],
     exclude = [
-        "test/val/pch_test_val.cpp", # pch tests are skipped.
+        "test/val/val_capability_test.cpp",
+        "test/val/val_limits_test.cpp",
     ],
 )]
 
+cc_test(
+    name = "val_capability_test",
+    size = "large",
+    timeout = "long",
+    srcs = ["test/val/val_capability_test.cpp"],
+    copts = TEST_COPTS + ["-O3"],
+    linkstatic = 1,
+    deps = [
+        ":spirv_tools_internal",
+        ":test_lib",
+        ":val_test_lib",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "val_limits_test",
+    size = "large",
+    timeout = "long",
+    srcs = ["test/val/val_limits_test.cpp"],
+    copts = TEST_COPTS + [
+        "-O3",
+    ],
+    linkstatic = 1,
+    deps = [
+        ":test_lib",
+        ":val_test_lib",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/third_party/SPIRV-Tools/BUILD.gn b/third_party/SPIRV-Tools/BUILD.gn
index 39c0fee..fb662c1 100644
--- a/third_party/SPIRV-Tools/BUILD.gn
+++ b/third_party/SPIRV-Tools/BUILD.gn
@@ -373,6 +373,9 @@
   } else if (!is_win) {
     # Work around a false-positive on a Skia GCC 10 builder.
     cflags += [ "-Wno-format-truncation" ]
+  } else {
+    # Make MSVC report the correct value for __cplusplus
+    cflags += [ "/Zc:__cplusplus" ]
   }
 }
 
diff --git a/third_party/SPIRV-Tools/CHANGES b/third_party/SPIRV-Tools/CHANGES
index 384805c..f24da41 100644
--- a/third_party/SPIRV-Tools/CHANGES
+++ b/third_party/SPIRV-Tools/CHANGES
@@ -1,7 +1,36 @@
 Revision history for SPIRV-Tools
 
-v2022.5-dev 2022-10-12
-   - Start v2022.5-dev
+v2023.2-dev 2023-01-17
+   - Start v2023.2-dev
+
+v2023.1 2023-01-17
+  - General
+    - Renamed "master" to "main" (issue#5051)
+    - Validate version 5 of clspv reflection (#5050)
+    - Remove testing support for VS2015 (#5027)
+    - Fix undef behaviour in hex float parsing (#5025)
+    - Require C++11 *or later* (#5020)
+  - Instrument
+    - Instrument: Fix bindless checking for BufferDeviceAddress (#5049)
+  - Optimizer
+    - Optimize allocation of spvtools::opt::Instruction::operands_ (#5024)
+    - spirv-opt: Fix OpCompositeInsert with Null Constant (#5008)
+    - spirv-opt: Handle null CompositeInsert (#4998)
+    - Add option to ADCE to remove output variables from interface. (#4994)
+    - Add support for tesc, tese and geom to EliminateDead*Components (#4990)
+    - Add pass to eliminate dead output components (#4982)
+    - spirv-opt: Add const folding for CompositeInsert (#4943)
+    - Add passes to eliminate dead output stores (#4970)
+    - Prevent eliminating case constructs in block merging (#4976)
+  - Validator
+    - Fix layout validation (#5015)
+    - Fix use of invalid analysis (#5013)
+    - Fix infinite loop in validator (#5006)
+    - Add validation support for SPV_NV_shader_invocation_reorder. (#4979)
+    - Only validate full layout in Vulkan environments (#4972)
+    - spirv-val: Label new Vulkan OpPtrAccessChain VUs (#4975)
+    - spirv-val: Add OpPtrAccessChain Base checks (#4965)
+
 
 v2022.4 2022-10-12
   - General
diff --git a/third_party/SPIRV-Tools/CMakeLists.txt b/third_party/SPIRV-Tools/CMakeLists.txt
index 7815a29..1c7b071 100644
--- a/third_party/SPIRV-Tools/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/CMakeLists.txt
@@ -12,26 +12,28 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-cmake_minimum_required(VERSION 2.8.12)
-if (POLICY CMP0048)
-  cmake_policy(SET CMP0048 NEW)
-endif()
-if (POLICY CMP0054)
-  # Avoid dereferencing variables or interpret keywords that have been
-  # quoted or bracketed.
-  # https://cmake.org/cmake/help/v3.1/policy/CMP0054.html
-  cmake_policy(SET CMP0054 NEW)
-endif()
-set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+cmake_minimum_required(VERSION 3.17.2)
 
 project(spirv-tools)
+
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
 enable_testing()
 set(SPIRV_TOOLS "SPIRV-Tools")
 
 include(GNUInstallDirs)
 
 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-set(CMAKE_CXX_STANDARD 11)
+
+# Require at least C++17
+if(NOT CMAKE_CXX_STANDARD)
+  set(CMAKE_CXX_STANDARD 17)
+endif()
+if(${CMAKE_CXX_STANDARD} LESS 17)
+  message(FATAL_ERROR "SPIRV-Tools requires C++17 or later, but is configured for C++${CMAKE_CXX_STANDARD})")
+endif()
+set(CMAKE_CXX_EXTENSIONS OFF)
+
 
 option(ENABLE_RTTI "Enables RTTI" OFF)
 option(SPIRV_ALLOW_TIMERS "Allow timers via clock_gettime on supported platforms" ON)
@@ -188,10 +190,9 @@
   target_compile_options(${TARGET} PRIVATE ${SPIRV_WARNINGS})
 
   if (${COMPILER_IS_LIKE_GNU})
-    target_compile_options(${TARGET} PRIVATE -std=c++11 -fno-exceptions)
     target_compile_options(${TARGET} PRIVATE
       -Wall -Wextra -Wno-long-long -Wshadow -Wundef -Wconversion
-      -Wno-sign-conversion)
+      -Wno-sign-conversion -fno-exceptions)
 
     if(NOT ENABLE_RTTI)
         add_compile_options(-fno-rtti)
diff --git a/third_party/SPIRV-Tools/DEPS b/third_party/SPIRV-Tools/DEPS
index 80b67dc..f1866ea 100644
--- a/third_party/SPIRV-Tools/DEPS
+++ b/third_party/SPIRV-Tools/DEPS
@@ -3,10 +3,17 @@
 vars = {
   'github': 'https://github.com',
 
-  'effcee_revision': '35912e1b7778ec2ddcff7e7188177761539e59e0',
-  'googletest_revision': 'd9bb8412d60b993365abb53f00b6dad9b2c01b62',
-  're2_revision': 'd2836d1b1c34c4e330a85a1006201db474bf2c8a',
-  'spirv_headers_revision': '1d31a100405cf8783ca7a31e31cdd727c9fc54c3',
+  'effcee_revision': 'c7b4db79f340f7a9981e8a484f6d5785e24242d1',
+
+  # Pin to the last version of googletest that supports C++11.
+  # Anything later requires C++14
+  'googletest_revision': 'v1.12.0',
+
+  # Use protobufs before they gained the dependency on abseil
+  'protobuf_revision': 'v3.13.0.1',
+
+  're2_revision': '8afcf7fcc481692197e33612446d69e8f5777c54',
+  'spirv_headers_revision': 'aa331ab0ffcb3a67021caa1a0c1c9017712f2f31',
 }
 
 deps = {
@@ -16,6 +23,9 @@
   'external/googletest':
       Var('github') + '/google/googletest.git@' + Var('googletest_revision'),
 
+  'external/protobuf':
+      Var('github') + '/protocolbuffers/protobuf.git@' + Var('protobuf_revision'),
+
   'external/re2':
       Var('github') + '/google/re2.git@' + Var('re2_revision'),
 
diff --git a/third_party/SPIRV-Tools/README.md b/third_party/SPIRV-Tools/README.md
index e951e37..baa44e7 100644
--- a/third_party/SPIRV-Tools/README.md
+++ b/third_party/SPIRV-Tools/README.md
@@ -1,5 +1,7 @@
 # SPIR-V Tools
 
+NEWS 2023-01-11: Development occurs on the `main` branch.
+
 ## Overview
 
 The SPIR-V Tools project provides an API and commands for processing SPIR-V
@@ -23,7 +25,7 @@
 
 <img alt="Linux" src="kokoro/img/linux.png" width="20px" height="20px" hspace="2px"/>[![Linux Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_linux_clang_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_linux_clang_release.html)
 <img alt="MacOS" src="kokoro/img/macos.png" width="20px" height="20px" hspace="2px"/>[![MacOS Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_macos_clang_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_macos_clang_release.html)
-<img alt="Windows" src="kokoro/img/windows.png" width="20px" height="20px" hspace="2px"/>[![Windows Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_windows_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_windows_vs2017_release.html)
+<img alt="Windows" src="kokoro/img/windows.png" width="20px" height="20px" hspace="2px"/>[![Windows Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_windows_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_windows_vs2019_release.html)
 
 [More downloads](docs/downloads.md)
 
@@ -96,10 +98,10 @@
 
 *Note*: The validator checks some Universal Limits, from section 2.17 of the SPIR-V spec.
 The validator will fail on a module that exceeds those minimum upper bound limits.
-It is [future work](https://github.com/KhronosGroup/SPIRV-Tools/projects/1#card-1052403)
-to parameterize the validator to allow larger
-limits accepted by a more than minimally capable SPIR-V consumer.
+The validator has been parameterized to allow larger values, for use when targeting 
+a more-than-minimally-capable SPIR-V consumer.
 
+See [`tools/val/val.cpp`](tools/val/val.cpp) or run `spirv-val --help` for the command-line help.
 
 ### Optimizer
 
@@ -271,7 +273,7 @@
   `clang-format version 5.0.0` for SPIRV-Tools. Settings are defined by
   the included [.clang-format](.clang-format) file.
 
-We intend to maintain a linear history on the GitHub `master` branch.
+We intend to maintain a linear history on the GitHub `main` branch.
 
 ### Getting the source
 
@@ -432,10 +434,13 @@
 - AppleClang 11.0
 
 On Windows
-- Visual Studio 2015
 - Visual Studio 2017
+- Visual Studio 2019
+- Visual Studio 2022
 
-Other compilers or later versions may work, but they are not tested.
+Note: Visual Studio 2017 has incomplete c++17 support. We might stop
+testing it soon. Other compilers or later versions may work, but they are not
+tested.
 
 ### CMake options
 
@@ -496,7 +501,7 @@
 
 ### Usage
 
-The internals of the library use C++11 features, and are exposed via both a C
+The internals of the library use C++17 features, and are exposed via both a C
 and C++ API.
 
 In order to use the library from an application, the include path should point
diff --git a/third_party/SPIRV-Tools/build_defs.bzl b/third_party/SPIRV-Tools/build_defs.bzl
index ed726ae..3a69de5 100644
--- a/third_party/SPIRV-Tools/build_defs.bzl
+++ b/third_party/SPIRV-Tools/build_defs.bzl
@@ -1,20 +1,24 @@
+"""Constants and macros for spirv-tools BUILD."""
+
 COMMON_COPTS = [
-        "-DSPIRV_CHECK_CONTEXT",
-        "-DSPIRV_COLOR_TERMINAL",
-    ] + select({
-    "@bazel_tools//src/conditions:windows": [""],
+    "-DSPIRV_CHECK_CONTEXT",
+    "-DSPIRV_COLOR_TERMINAL",
+] + select({
+    # On Windows, assume MSVC.
+    # C++14 is the default in VisualStudio 2017.
+    "@platforms//os:windows": [],
     "//conditions:default": [
         "-DSPIRV_LINUX",
         "-DSPIRV_TIMER_ENABLED",
+        "-std=c++11",
+        "-fvisibility=hidden",
+        "-fno-exceptions",
+        "-fno-rtti",
         "-Wall",
         "-Wextra",
         "-Wnon-virtual-dtor",
         "-Wno-missing-field-initializers",
         "-Werror",
-        "-std=c++11",
-        "-fvisibility=hidden",
-        "-fno-exceptions",
-        "-fno-rtti",
         "-Wno-long-long",
         "-Wshadow",
         "-Wundef",
@@ -23,154 +27,161 @@
     ],
 })
 
-TEST_COPTS = COMMON_COPTS + select({
-    "@bazel_tools//src/conditions:windows": [
+TEST_COPTS = COMMON_COPTS + [
+] + select({
+    "@platforms//os:windows": [
         # Disable C4503 "decorated name length exceeded" warning,
         # triggered by some heavily templated types.
         # We don't care much about that in test code.
         # Important to do since we have warnings-as-errors.
-        "/wd4503"
+        "/wd4503",
     ],
     "//conditions:default": [
         "-Wno-undef",
         "-Wno-self-assign",
         "-Wno-shadow",
-        "-Wno-unused-parameter"
+        "-Wno-unused-parameter",
     ],
 })
 
+def incompatible_with(incompatible_constraints):
+    return select(_merge_dicts([{"//conditions:default": []}, {
+        constraint: ["@platforms//:incompatible"]
+        for constraint in incompatible_constraints
+    }]))
+
 DEBUGINFO_GRAMMAR_JSON_FILE = "@spirv_headers//:spirv_ext_inst_debuginfo_grammar_unified1"
 CLDEBUGINFO100_GRAMMAR_JSON_FILE = "@spirv_headers//:spirv_ext_inst_opencl_debuginfo_100_grammar_unified1"
 SHDEBUGINFO100_GRAMMAR_JSON_FILE = "@spirv_headers//:spirv_ext_inst_nonsemantic_shader_debuginfo_100_grammar_unified1"
 
-def generate_core_tables(version = None):
+def _merge_dicts(dicts):
+    merged = {}
+    for d in dicts:
+        merged.update(d)
+    return merged
+
+def generate_core_tables(version):
     if not version:
         fail("Must specify version", "version")
-    grammars = [
-        "@spirv_headers//:spirv_core_grammar_" + version,
-        DEBUGINFO_GRAMMAR_JSON_FILE,
-        CLDEBUGINFO100_GRAMMAR_JSON_FILE,
-    ]
-    outs = [
-        "core.insts-{}.inc".format(version),
-        "operand.kinds-{}.inc".format(version),
-    ]
-    fmtargs = grammars + outs
+
+    grammars = dict(
+        core_grammar = "@spirv_headers//:spirv_core_grammar_{}".format(version),
+        debuginfo_grammar = DEBUGINFO_GRAMMAR_JSON_FILE,
+        cldebuginfo_grammar = CLDEBUGINFO100_GRAMMAR_JSON_FILE,
+    )
+
+    outs = dict(
+        core_insts_output = "core.insts-{}.inc".format(version),
+        operand_kinds_output = "operand.kinds-{}.inc".format(version),
+    )
+
+    cmd = (
+        "$(location :generate_grammar_tables)" +
+        " --spirv-core-grammar=$(location {core_grammar})" +
+        " --extinst-debuginfo-grammar=$(location {debuginfo_grammar})" +
+        " --extinst-cldebuginfo100-grammar=$(location {cldebuginfo_grammar})" +
+        " --core-insts-output=$(location {core_insts_output})" +
+        " --operand-kinds-output=$(location {operand_kinds_output})" +
+        " --output-language=c++"
+    ).format(**_merge_dicts([grammars, outs]))
+
     native.genrule(
         name = "gen_core_tables_" + version,
-        srcs = grammars,
-        outs = outs,
-        cmd = (
-            "$(location :generate_grammar_tables) " +
-            "--spirv-core-grammar=$(location {0}) " +
-            "--extinst-debuginfo-grammar=$(location {1}) " +
-            "--extinst-cldebuginfo100-grammar=$(location {2}) " +
-            "--core-insts-output=$(location {3}) " +
-            "--operand-kinds-output=$(location {4}) " +
-            "--output-language=c++"
-        ).format(*fmtargs),
-        cmd_bat = (
-            "$(location :generate_grammar_tables) " +
-            "--spirv-core-grammar=$(location {0}) " +
-            "--extinst-debuginfo-grammar=$(location {1}) " +
-            "--extinst-cldebuginfo100-grammar=$(location {2}) " +
-            "--core-insts-output=$(location {3}) " +
-            "--operand-kinds-output=$(location {4}) " +
-            "--output-language=c++"
-        ).format(*fmtargs),
+        srcs = grammars.values(),
+        outs = outs.values(),
+        cmd = cmd,
+        cmd_bat = cmd,
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
     )
 
-def generate_enum_string_mapping(version = None):
+def generate_enum_string_mapping(version):
     if not version:
         fail("Must specify version", "version")
-    grammars = [
-        "@spirv_headers//:spirv_core_grammar_" + version,
-        DEBUGINFO_GRAMMAR_JSON_FILE,
-        CLDEBUGINFO100_GRAMMAR_JSON_FILE,
-    ]
-    outs = [
-        "extension_enum.inc",
-        "enum_string_mapping.inc",
-    ]
-    fmtargs = grammars + outs
+
+    grammars = dict(
+        core_grammar = "@spirv_headers//:spirv_core_grammar_{}".format(version),
+        debuginfo_grammar = DEBUGINFO_GRAMMAR_JSON_FILE,
+        cldebuginfo_grammar = CLDEBUGINFO100_GRAMMAR_JSON_FILE,
+    )
+
+    outs = dict(
+        extension_enum_ouput = "extension_enum.inc",
+        enum_string_mapping_output = "enum_string_mapping.inc",
+    )
+
+    cmd = (
+        "$(location :generate_grammar_tables)" +
+        " --spirv-core-grammar=$(location {core_grammar})" +
+        " --extinst-debuginfo-grammar=$(location {debuginfo_grammar})" +
+        " --extinst-cldebuginfo100-grammar=$(location {cldebuginfo_grammar})" +
+        " --extension-enum-output=$(location {extension_enum_ouput})" +
+        " --enum-string-mapping-output=$(location {enum_string_mapping_output})" +
+        " --output-language=c++"
+    ).format(**_merge_dicts([grammars, outs]))
+
     native.genrule(
         name = "gen_enum_string_mapping",
-        srcs = grammars,
-        outs = outs,
-        cmd = (
-            "$(location :generate_grammar_tables) " +
-            "--spirv-core-grammar=$(location {0}) " +
-            "--extinst-debuginfo-grammar=$(location {1}) " +
-            "--extinst-cldebuginfo100-grammar=$(location {2}) " +
-            "--extension-enum-output=$(location {3}) " +
-            "--enum-string-mapping-output=$(location {4}) " +
-            "--output-language=c++"
-        ).format(*fmtargs),
-        cmd_bat = (
-            "$(location :generate_grammar_tables) " +
-            "--spirv-core-grammar=$(location {0}) " +
-            "--extinst-debuginfo-grammar=$(location {1}) " +
-            "--extinst-cldebuginfo100-grammar=$(location {2}) " +
-            "--extension-enum-output=$(location {3}) " +
-            "--enum-string-mapping-output=$(location {4}) " +
-            "--output-language=c++"
-        ).format(*fmtargs),
+        srcs = grammars.values(),
+        outs = outs.values(),
+        cmd = cmd,
+        cmd_bat = cmd,
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
     )
 
-def generate_opencl_tables(version = None):
+def generate_opencl_tables(version):
     if not version:
         fail("Must specify version", "version")
-    grammars = [
-        "@spirv_headers//:spirv_opencl_grammar_" + version,
-    ]
-    outs = ["opencl.std.insts.inc"]
-    fmtargs = grammars + outs
+
+    grammars = dict(
+        opencl_grammar = "@spirv_headers//:spirv_opencl_grammar_{}".format(version),
+    )
+
+    outs = dict(
+        opencl_insts_output = "opencl.std.insts.inc",
+    )
+
+    cmd = (
+        "$(location :generate_grammar_tables)" +
+        " --extinst-opencl-grammar=$(location {opencl_grammar})" +
+        " --opencl-insts-output=$(location {opencl_insts_output})"
+    ).format(**_merge_dicts([grammars, outs]))
+
     native.genrule(
         name = "gen_opencl_tables_" + version,
-        srcs = grammars,
-        outs = outs,
-        cmd = (
-            "$(location :generate_grammar_tables) " +
-            "--extinst-opencl-grammar=$(location {0}) " +
-            "--opencl-insts-output=$(location {1})"
-        ).format(*fmtargs),
-        cmd_bat = (
-            "$(location :generate_grammar_tables) " +
-            "--extinst-opencl-grammar=$(location {0}) " +
-            "--opencl-insts-output=$(location {1})"
-        ).format(*fmtargs),
+        srcs = grammars.values(),
+        outs = outs.values(),
+        cmd = cmd,
+        cmd_bat = cmd,
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
     )
 
-def generate_glsl_tables(version = None):
+def generate_glsl_tables(version):
     if not version:
         fail("Must specify version", "version")
-    grammars = [
-        "@spirv_headers//:spirv_glsl_grammar_" + version,
-    ]
-    outs = ["glsl.std.450.insts.inc"]
-    fmtargs = grammars + outs
+
+    grammars = dict(
+        gsls_grammar = "@spirv_headers//:spirv_glsl_grammar_{}".format(version),
+    )
+    outs = dict(
+        gsls_insts_outs = "glsl.std.450.insts.inc",
+    )
+
+    cmd = (
+        "$(location :generate_grammar_tables)" +
+        " --extinst-glsl-grammar=$(location {gsls_grammar})" +
+        " --glsl-insts-output=$(location {gsls_insts_outs})" +
+        " --output-language=c++"
+    ).format(**_merge_dicts([grammars, outs]))
+
     native.genrule(
         name = "gen_glsl_tables_" + version,
-        srcs = grammars,
-        outs = outs,
-        cmd = (
-            "$(location :generate_grammar_tables) " +
-            "--extinst-glsl-grammar=$(location {0}) " +
-            "--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}) " +
-            "--output-language=c++"
-        ).format(*fmtargs),
+        srcs = grammars.values(),
+        outs = outs.values(),
+        cmd = cmd,
+        cmd_bat = cmd,
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
     )
@@ -178,27 +189,27 @@
 def generate_vendor_tables(extension, operand_kind_prefix = ""):
     if not extension:
         fail("Must specify extension", "extension")
+
     extension_rule = extension.replace("-", "_").replace(".", "_")
-    grammars = ["@spirv_headers//:spirv_ext_inst_{}_grammar_unified1".format(extension_rule)]
-    outs = ["{}.insts.inc".format(extension)]
-    prefices = [operand_kind_prefix]
-    fmtargs = grammars + outs + prefices
+    grammars = dict(
+        vendor_grammar = "@spirv_headers//:spirv_ext_inst_{}_grammar_unified1".format(extension_rule),
+    )
+    outs = dict(
+        vendor_insts_output = "{}.insts.inc".format(extension),
+    )
+    cmd = (
+        "$(location :generate_grammar_tables)" +
+        " --extinst-vendor-grammar=$(location {vendor_grammar})" +
+        " --vendor-insts-output=$(location {vendor_insts_output})" +
+        " --vendor-operand-kind-prefix={operand_kind_prefix}"
+    ).format(operand_kind_prefix = operand_kind_prefix, **_merge_dicts([grammars, outs]))
+
     native.genrule(
         name = "gen_vendor_tables_" + extension_rule,
-        srcs = grammars,
-        outs = outs,
-        cmd = (
-            "$(location :generate_grammar_tables) " +
-            "--extinst-vendor-grammar=$(location {0}) " +
-            "--vendor-insts-output=$(location {1}) " +
-            "--vendor-operand-kind-prefix={2}"
-        ).format(*fmtargs),
-        cmd_bat = (
-            "$(location :generate_grammar_tables) " +
-            "--extinst-vendor-grammar=$(location {0}) " +
-            "--vendor-insts-output=$(location {1}) " +
-            "--vendor-operand-kind-prefix={2}"
-        ).format(*fmtargs),
+        srcs = grammars.values(),
+        outs = outs.values(),
+        cmd = cmd,
+        cmd_bat = cmd,
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
     )
@@ -206,147 +217,21 @@
 def generate_extinst_lang_headers(name, grammar = None):
     if not grammar:
         fail("Must specify grammar", "grammar")
-    outs = [name + ".h"]
-    fmtargs = outs
+    outs = dict(
+        extinst_output_path = name + ".h",
+    )
+    cmd = (
+        "$(location :generate_language_headers)" +
+        " --extinst-grammar=$<" +
+        " --extinst-output-path=$(location {extinst_output_path})"
+    ).format(**outs)
+
     native.genrule(
-        name = "gen_extinst_lang_headers_" + name,
+        name = "gen_extinst_lang_headers_{}".format(name),
         srcs = [grammar],
-        outs = outs,
-        cmd = (
-            "$(location :generate_language_headers) " +
-            "--extinst-grammar=$< " +
-            "--extinst-output-path=$(location {0})"
-        ).format(*fmtargs),
-        cmd_bat = (
-            "$(location :generate_language_headers) " +
-            "--extinst-grammar=$< " +
-            "--extinst-output-path=$(location {0})"
-        ).format(*fmtargs),
+        outs = outs.values(),
+        cmd = cmd,
+        cmd_bat = cmd,
         exec_tools = [":generate_language_headers"],
         visibility = ["//visibility:private"],
     )
-
-def base_test(name, srcs, deps = []):
-    if srcs == []:
-        return
-    if name[-5:] != "_test":
-        name = name + "_test"
-    native.cc_test(
-        name = "base_" + name,
-        srcs = srcs,
-        compatible_with = [],
-        copts = TEST_COPTS,
-        size = "large",
-        deps = [
-            ":test_common",
-            "@com_google_googletest//:gtest_main",
-            "@com_google_googletest//:gtest",
-            "@com_google_effcee//:effcee",
-        ] + deps,
-    )
-
-def lint_test(name, srcs, deps = []):
-    if name[-5:] != "_test":
-        name = name + "_test"
-    native.cc_test(
-        name = "lint_" + name,
-        srcs = srcs,
-        compatible_with = [],
-        copts = TEST_COPTS,
-        size = "large",
-        deps = [
-            ":spirv_tools_lint",
-            "@com_google_googletest//:gtest_main",
-            "@com_google_googletest//:gtest",
-            "@com_google_effcee//:effcee",
-        ] + deps,
-    )
-
-def link_test(name, srcs, deps = []):
-    if name[-5:] != "_test":
-        name = name + "_test"
-    native.cc_test(
-        name = "link_" + name,
-        srcs = srcs,
-        compatible_with = [],
-        copts = TEST_COPTS,
-        size = "large",
-        deps = [
-            ":link_test_common",
-            "@com_google_googletest//:gtest_main",
-            "@com_google_googletest//:gtest",
-            "@com_google_effcee//:effcee",
-        ] + deps,
-    )
-
-def opt_test(name, srcs, deps = []):
-    if name[-5:] != "_test":
-        name = name + "_test"
-    native.cc_test(
-        name = "opt_" + name,
-        srcs = srcs,
-        compatible_with = [],
-        copts = TEST_COPTS,
-        size = "large",
-        deps = [
-            ":opt_test_common",
-            "@com_google_googletest//:gtest_main",
-            "@com_google_googletest//:gtest",
-            "@com_google_effcee//:effcee",
-        ] + deps,
-    )
-
-def reduce_test(name, srcs, deps = []):
-    if name[-5:] != "_test":
-        name = name + "_test"
-    native.cc_test(
-        name = "reduce_" + name,
-        srcs = srcs,
-        compatible_with = [],
-        copts = TEST_COPTS,
-        size = "large",
-        deps = [
-            ":reduce_test_common",
-            ":spirv_tools_reduce",
-            "@com_google_googletest//:gtest_main",
-            "@com_google_googletest//:gtest",
-            "@com_google_effcee//:effcee",
-        ] + deps,
-    )
-
-def util_test(name, srcs, deps = []):
-    if name[-5:] != "_test":
-        name = name + "_test"
-    native.cc_test(
-        name = "util_" + name,
-        srcs = srcs,
-        compatible_with = [],
-        copts = TEST_COPTS,
-        size = "large",
-        deps = [
-            ":opt_test_common",
-            "@com_google_googletest//:gtest_main",
-            "@com_google_googletest//:gtest",
-            "@com_google_effcee//:effcee",
-        ] + deps,
-    )
-
-def val_test(name, srcs = [], copts = [], deps = [], **kwargs):
-    if name[-5:] != "_test":
-        name = name + "_test"
-    if name[:4] != "val_":
-        name = "val_" + name
-    native.cc_test(
-        name = name,
-        srcs = srcs,
-        compatible_with = [],
-        copts = TEST_COPTS + copts,
-        size = "large",
-        deps = [
-            ":val_test_common",
-            "@com_google_googletest//:gtest_main",
-            "@com_google_googletest//:gtest",
-            "@com_google_effcee//:effcee",
-        ] + deps,
-        **kwargs
-    )
diff --git a/third_party/SPIRV-Tools/external/CMakeLists.txt b/third_party/SPIRV-Tools/external/CMakeLists.txt
index 179a401..676ee97 100644
--- a/third_party/SPIRV-Tools/external/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/external/CMakeLists.txt
@@ -30,11 +30,7 @@
   # This allows flexible position of the SPIRV-Headers repo.
   set(SPIRV_HEADER_DIR ${SPIRV-Headers_SOURCE_DIR})
 else()
-  if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Headers)
-    set(SPIRV_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Headers)
-  else()
-    set(SPIRV_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/spirv-headers)
-  endif()
+  set(SPIRV_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/spirv-headers)
 endif()
 
 if (IS_DIRECTORY ${SPIRV_HEADER_DIR})
diff --git a/third_party/SPIRV-Tools/kokoro/check-format/build.sh b/third_party/SPIRV-Tools/kokoro/check-format/build.sh
index 8a5df9a..96603e4 100644
--- a/third_party/SPIRV-Tools/kokoro/check-format/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/check-format/build.sh
@@ -23,6 +23,11 @@
 BUILD_ROOT=$PWD
 SRC=$PWD/github/SPIRV-Tools
 
+# This is required to run any git command in the docker since owner will
+# have changed between the clone environment, and the docker container.
+# Marking the root of the repo as safe for ownership changes.
+git config --global --add safe.directory $SRC
+
 # Get clang-format-5.0.0.
 # Once kokoro upgrades the Ubuntu VMs, we can use 'apt-get install clang-format'
 curl -L http://releases.llvm.org/5.0.0/clang+llvm-5.0.0-linux-x86_64-ubuntu14.04.tar.xz -o clang-llvm.tar.xz
diff --git a/third_party/SPIRV-Tools/kokoro/macos-clang-debug/build.sh b/third_party/SPIRV-Tools/kokoro/macos-clang-debug/build.sh
index 8d9a062..fca76fc 100644
--- a/third_party/SPIRV-Tools/kokoro/macos-clang-debug/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/macos-clang-debug/build.sh
@@ -22,4 +22,3 @@
 
 SCRIPT_DIR=`dirname "$BASH_SOURCE"`
 source $SCRIPT_DIR/../scripts/macos/build.sh Debug
-
diff --git a/third_party/SPIRV-Tools/kokoro/macos-clang-release-bazel/build.sh b/third_party/SPIRV-Tools/kokoro/macos-clang-release-bazel/build.sh
index c62611a..50ad42b 100644
--- a/third_party/SPIRV-Tools/kokoro/macos-clang-release-bazel/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/macos-clang-release-bazel/build.sh
@@ -24,6 +24,11 @@
 CXX=clang++
 SRC=$PWD/github/SPIRV-Tools
 
+# This is required to run any git command in the docker since owner will
+# have changed between the clone environment, and the docker container.
+# Marking the root of the repo as safe for ownership changes.
+git config --global --add safe.directory $SRC
+
 cd $SRC
 git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
 git clone https://github.com/google/googletest          external/googletest
diff --git a/third_party/SPIRV-Tools/kokoro/macos-clang-release/build.sh b/third_party/SPIRV-Tools/kokoro/macos-clang-release/build.sh
index ccc8b16..b1460a9 100644
--- a/third_party/SPIRV-Tools/kokoro/macos-clang-release/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/macos-clang-release/build.sh
@@ -22,4 +22,3 @@
 
 SCRIPT_DIR=`dirname "$BASH_SOURCE"`
 source $SCRIPT_DIR/../scripts/macos/build.sh RelWithDebInfo
-
diff --git a/third_party/SPIRV-Tools/kokoro/scripts/linux/build-docker.sh b/third_party/SPIRV-Tools/kokoro/scripts/linux/build-docker.sh
index 80043b8..52fbb9e 100755
--- a/third_party/SPIRV-Tools/kokoro/scripts/linux/build-docker.sh
+++ b/third_party/SPIRV-Tools/kokoro/scripts/linux/build-docker.sh
@@ -20,6 +20,11 @@
 # Display commands being run.
 set -x
 
+# This is required to run any git command in the docker since owner will
+# have changed between the clone environment, and the docker container.
+# Marking the root of the repo as safe for ownership changes.
+git config --global --add safe.directory $ROOT_DIR
+
 . /bin/using.sh # Declare the bash `using` function for configuring toolchains.
 
 if [ $COMPILER = "clang" ]; then
@@ -30,14 +35,6 @@
 
 cd $ROOT_DIR
 
-function clone_if_missing() {
-  url=$1
-  dir=$2
-  if [[ ! -d "$dir" ]]; then
-    git clone ${@:3} "$url" "$dir"
-  fi
-}
-
 function clean_dir() {
   dir=$1
   if [[ -d "$dir" ]]; then
@@ -46,12 +43,8 @@
   mkdir "$dir"
 }
 
-clone_if_missing https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers --depth=1
-clone_if_missing https://github.com/google/googletest          external/googletest
-pushd external/googletest; git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7; popd
-clone_if_missing https://github.com/google/effcee              external/effcee        --depth=1
-clone_if_missing https://github.com/google/re2                 external/re2           --depth=1
-clone_if_missing https://github.com/protocolbuffers/protobuf   external/protobuf      --branch v3.13.0.1
+# Get source for dependencies, as specified in the DEPS file
+/usr/bin/python3 utils/git-sync-deps --treeless
 
 if [ $TOOL = "cmake" ]; then
   using cmake-3.17.2
diff --git a/third_party/SPIRV-Tools/kokoro/scripts/macos/build.sh b/third_party/SPIRV-Tools/kokoro/scripts/macos/build.sh
index 3618e69..8381f87 100644
--- a/third_party/SPIRV-Tools/kokoro/scripts/macos/build.sh
+++ b/third_party/SPIRV-Tools/kokoro/scripts/macos/build.sh
@@ -24,6 +24,11 @@
 SRC=$PWD/github/SPIRV-Tools
 BUILD_TYPE=$1
 
+# This is required to run any git command in the docker since owner will
+# have changed between the clone environment, and the docker container.
+# Marking the root of the repo as safe for ownership changes.
+git config --global --add safe.directory $SRC
+
 # Get NINJA.
 wget -q https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-mac.zip
 unzip -q ninja-mac.zip
@@ -31,12 +36,7 @@
 export PATH="$PWD:$PATH"
 
 cd $SRC
-git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
-git clone https://github.com/google/googletest          external/googletest
-cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
-git clone --depth=1 https://github.com/google/effcee              external/effcee
-git clone --depth=1 https://github.com/google/re2                 external/re2
-git clone --depth=1 --branch v3.13.0.1 https://github.com/protocolbuffers/protobuf external/protobuf
+python3 utils/git-sync-deps --treeless
 
 mkdir build && cd $SRC/build
 
diff --git a/third_party/SPIRV-Tools/kokoro/scripts/windows/build.bat b/third_party/SPIRV-Tools/kokoro/scripts/windows/build.bat
index 8c9d689..bb14da3 100644
--- a/third_party/SPIRV-Tools/kokoro/scripts/windows/build.bat
+++ b/third_party/SPIRV-Tools/kokoro/scripts/windows/build.bat
@@ -24,26 +24,20 @@
 :: Force usage of python 3.6
 set PATH=C:\python36;"C:\Program Files\cmake-3.23.1-windows-x86_64\bin";%PATH%
 
-cd %SRC%
-git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
-git clone https://github.com/google/googletest          external/googletest
-cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
-git clone --depth=1 https://github.com/google/effcee              external/effcee
-git clone --depth=1 https://github.com/google/re2                 external/re2
-git clone --depth=1 --branch v3.13.0.1 https://github.com/protocolbuffers/protobuf external/protobuf
-
 :: #########################################
 :: set up msvc build env
 :: #########################################
 if %VS_VERSION% == 2017 (
   call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
   echo "Using VS 2017..."
-) else if %VS_VERSION% == 2015 (
-  call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
-  echo "Using VS 2015..."
+) else if %VS_VERSION% == 2019 (
+  call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
+  echo "Using VS 2019..."
 )
 
 cd %SRC%
+python utils/git-sync-deps --treeless
+
 mkdir build
 cd build
 
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2013-release/build.bat b/third_party/SPIRV-Tools/kokoro/windows-msvc-2013-release/build.bat
deleted file mode 100644
index e77172a..0000000
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2013-release/build.bat
+++ /dev/null
@@ -1,24 +0,0 @@
-:: Copyright (c) 2018 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.
-::
-:: Windows Build Script.
-
-@echo on
-
-:: Find out the directory of the common build script.
-set SCRIPT_DIR=%~dp0
-
-:: Call with correct parameter
-call %SCRIPT_DIR%\..\scripts\windows\build.bat RelWithDebInfo 2013
-
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2013-release/presubmit.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2013-release/presubmit.cfg
deleted file mode 100644
index 7d3b238..0000000
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2013-release/presubmit.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2018 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.
-
-# Presubmit build configuration.
-build_file: "SPIRV-Tools/kokoro/windows-msvc-2013-release/build.bat"
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/build.bat b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat
similarity index 87%
rename from third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/build.bat
rename to third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat
index de20b0a..c1945e2 100644
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/build.bat
+++ b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat
@@ -34,10 +34,8 @@
 unzip -q bazel-5.0.0-windows-x86_64.zip
 
 :: Set up MSVC
-call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
-set BAZEL_VS=C:\Program Files (x86)\Microsoft Visual Studio 14.0
-set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
-set BAZEL_PYTHON=c:\tools\python2\python.exe
+call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
+set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC
 
 :: #########################################
 :: Start building.
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/continuous.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/continuous.cfg
similarity index 90%
rename from third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/continuous.cfg
rename to third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/continuous.cfg
index f72cf05..f2387a6 100644
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/continuous.cfg
+++ b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/continuous.cfg
@@ -13,4 +13,4 @@
 # limitations under the License.
 
 # Continuous build configuration.
-build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/build.bat"
+build_file: "SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat"
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/presubmit.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/presubmit.cfg
similarity index 90%
rename from third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/presubmit.cfg
rename to third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/presubmit.cfg
index 148972c..13394b4 100644
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/presubmit.cfg
+++ b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/presubmit.cfg
@@ -13,4 +13,4 @@
 # limitations under the License.
 
 # Presubmit build configuration.
-build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/build.bat"
+build_file: "SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat"
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-debug/build.bat
similarity index 87%
copy from third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat
copy to third_party/SPIRV-Tools/kokoro/windows-msvc-2019-debug/build.bat
index c0e4bd3..7ad94c1 100644
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat
+++ b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-debug/build.bat
@@ -1,4 +1,4 @@
-:: Copyright (c) 2018 Google LLC.
+:: Copyright (c) 2023 Google LLC
 ::
 :: Licensed under the Apache License, Version 2.0 (the "License");
 :: you may not use this file except in compliance with the License.
@@ -20,5 +20,4 @@
 set SCRIPT_DIR=%~dp0
 
 :: Call with correct parameter
-call %SCRIPT_DIR%\..\scripts\windows\build.bat RelWithDebInfo 2015
-
+call %SCRIPT_DIR%\..\scripts\windows\build.bat Debug 2019
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/continuous.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-debug/continuous.cfg
similarity index 78%
copy from third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/continuous.cfg
copy to third_party/SPIRV-Tools/kokoro/windows-msvc-2019-debug/continuous.cfg
index 3e47e52..e3a7863 100644
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/continuous.cfg
+++ b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-debug/continuous.cfg
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Google LLC.
+# Copyright (c) 2023 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,4 +13,10 @@
 # limitations under the License.
 
 # Continuous build configuration.
-build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat"
+build_file: "SPIRV-Tools/kokoro/windows-msvc-2019-debug/build.bat"
+
+action {
+  define_artifacts {
+    regex: "install.zip"
+  }
+}
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/presubmit.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-debug/presubmit.cfg
similarity index 84%
copy from third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/presubmit.cfg
copy to third_party/SPIRV-Tools/kokoro/windows-msvc-2019-debug/presubmit.cfg
index 148972c..0ed3594 100644
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/presubmit.cfg
+++ b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-debug/presubmit.cfg
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Google LLC.
+# Copyright (c) 2023 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,4 +13,4 @@
 # limitations under the License.
 
 # Presubmit build configuration.
-build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/build.bat"
+build_file: "SPIRV-Tools/kokoro/windows-msvc-2019-debug/build.bat"
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-release/build.bat
similarity index 95%
rename from third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat
rename to third_party/SPIRV-Tools/kokoro/windows-msvc-2019-release/build.bat
index c0e4bd3..8212924 100644
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat
+++ b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-release/build.bat
@@ -1,4 +1,4 @@
-:: Copyright (c) 2018 Google LLC.
+:: Copyright (c) 2023 Google LLC
 ::
 :: Licensed under the Apache License, Version 2.0 (the "License");
 :: you may not use this file except in compliance with the License.
@@ -20,5 +20,5 @@
 set SCRIPT_DIR=%~dp0
 
 :: Call with correct parameter
-call %SCRIPT_DIR%\..\scripts\windows\build.bat RelWithDebInfo 2015
+call %SCRIPT_DIR%\..\scripts\windows\build.bat RelWithDebInfo 2019
 
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/continuous.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-release/continuous.cfg
similarity index 78%
rename from third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/continuous.cfg
rename to third_party/SPIRV-Tools/kokoro/windows-msvc-2019-release/continuous.cfg
index 3e47e52..624ccbd 100644
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/continuous.cfg
+++ b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-release/continuous.cfg
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Google LLC.
+# Copyright (c) 2023 Google LLC.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,4 +13,10 @@
 # limitations under the License.
 
 # Continuous build configuration.
-build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat"
+build_file: "SPIRV-Tools/kokoro/windows-msvc-2019-release/build.bat"
+
+action {
+  define_artifacts {
+    regex: "install.zip"
+  }
+}
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/presubmit.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-release/presubmit.cfg
similarity index 85%
rename from third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/presubmit.cfg
rename to third_party/SPIRV-Tools/kokoro/windows-msvc-2019-release/presubmit.cfg
index 85a1625..4c578e0 100644
--- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2015-release/presubmit.cfg
+++ b/third_party/SPIRV-Tools/kokoro/windows-msvc-2019-release/presubmit.cfg
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Google LLC.
+# Copyright (c) 2023 Google LLC.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,4 +13,4 @@
 # limitations under the License.
 
 # Presubmit build configuration.
-build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat"
+build_file: "SPIRV-Tools/kokoro/windows-msvc-2019-release/build.bat"
diff --git a/third_party/SPIRV-Tools/source/CMakeLists.txt b/third_party/SPIRV-Tools/source/CMakeLists.txt
index e85ec9d..acfa0c1 100644
--- a/third_party/SPIRV-Tools/source/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/CMakeLists.txt
@@ -425,10 +425,7 @@
 endif()
 
 if(ENABLE_SPIRV_TOOLS_INSTALL)
-  install(TARGETS ${SPIRV_TOOLS_TARGETS} EXPORT ${SPIRV_TOOLS}Targets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+  install(TARGETS ${SPIRV_TOOLS_TARGETS} EXPORT ${SPIRV_TOOLS}Targets)
   export(EXPORT ${SPIRV_TOOLS}Targets FILE ${SPIRV_TOOLS}Target.cmake)
 
   spvtools_config_package_dir(${SPIRV_TOOLS} PACKAGE_DIR)
diff --git a/third_party/SPIRV-Tools/source/diff/CMakeLists.txt b/third_party/SPIRV-Tools/source/diff/CMakeLists.txt
index 1328699..52f18f2 100644
--- a/third_party/SPIRV-Tools/source/diff/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/diff/CMakeLists.txt
@@ -39,10 +39,7 @@
 spvtools_check_symbol_exports(SPIRV-Tools-diff)
 
 if(ENABLE_SPIRV_TOOLS_INSTALL)
-  install(TARGETS SPIRV-Tools-diff EXPORT SPIRV-Tools-diffTargets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+  install(TARGETS SPIRV-Tools-diff EXPORT SPIRV-Tools-diffTargets)
   export(EXPORT SPIRV-Tools-diffTargets FILE SPIRV-Tools-diffTargets.cmake)
 
   spvtools_config_package_dir(SPIRV-Tools-diff PACKAGE_DIR)
diff --git a/third_party/SPIRV-Tools/source/fuzz/CMakeLists.txt b/third_party/SPIRV-Tools/source/fuzz/CMakeLists.txt
index dd674dd..86ee657 100644
--- a/third_party/SPIRV-Tools/source/fuzz/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/fuzz/CMakeLists.txt
@@ -470,10 +470,7 @@
   spvtools_check_symbol_exports(SPIRV-Tools-fuzz)
 
   if(ENABLE_SPIRV_TOOLS_INSTALL)
-      install(TARGETS SPIRV-Tools-fuzz EXPORT SPIRV-Tools-fuzzTargets
-            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+      install(TARGETS SPIRV-Tools-fuzz EXPORT SPIRV-Tools-fuzzTargets)
       export(EXPORT SPIRV-Tools-fuzzTargets FILE SPIRV-Tools-fuzzTarget.cmake)
 
       spvtools_config_package_dir(SPIRV-Tools-fuzz PACKAGE_DIR)
diff --git a/third_party/SPIRV-Tools/source/link/CMakeLists.txt b/third_party/SPIRV-Tools/source/link/CMakeLists.txt
index a452a10..a35b9a5 100644
--- a/third_party/SPIRV-Tools/source/link/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/link/CMakeLists.txt
@@ -31,10 +31,7 @@
 spvtools_check_symbol_exports(SPIRV-Tools-link)
 
 if(ENABLE_SPIRV_TOOLS_INSTALL)
-  install(TARGETS SPIRV-Tools-link EXPORT SPIRV-Tools-linkTargets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+  install(TARGETS SPIRV-Tools-link EXPORT SPIRV-Tools-linkTargets)
   export(EXPORT SPIRV-Tools-linkTargets FILE SPIRV-Tools-linkTargets.cmake)
 
   spvtools_config_package_dir(SPIRV-Tools-link PACKAGE_DIR)
diff --git a/third_party/SPIRV-Tools/source/lint/CMakeLists.txt b/third_party/SPIRV-Tools/source/lint/CMakeLists.txt
index 1feae3f..4704beb 100644
--- a/third_party/SPIRV-Tools/source/lint/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/lint/CMakeLists.txt
@@ -46,10 +46,7 @@
 spvtools_check_symbol_exports(SPIRV-Tools-lint)
 
 if(ENABLE_SPIRV_TOOLS_INSTALL)
-  install(TARGETS SPIRV-Tools-lint EXPORT SPIRV-Tools-lintTargets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+  install(TARGETS SPIRV-Tools-lint EXPORT SPIRV-Tools-lintTargets)
   export(EXPORT SPIRV-Tools-lintTargets FILE SPIRV-Tools-lintTargets.cmake)
 
   spvtools_config_package_dir(SPIRV-Tools-lint PACKAGE_DIR)
diff --git a/third_party/SPIRV-Tools/source/opt/CMakeLists.txt b/third_party/SPIRV-Tools/source/opt/CMakeLists.txt
index c34c38d..eea3c47 100644
--- a/third_party/SPIRV-Tools/source/opt/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/opt/CMakeLists.txt
@@ -271,10 +271,7 @@
 spvtools_check_symbol_exports(SPIRV-Tools-opt)
 
 if(ENABLE_SPIRV_TOOLS_INSTALL)
-  install(TARGETS SPIRV-Tools-opt EXPORT SPIRV-Tools-optTargets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+  install(TARGETS SPIRV-Tools-opt EXPORT SPIRV-Tools-optTargets)
   export(EXPORT SPIRV-Tools-optTargets FILE SPIRV-Tools-optTargets.cmake)
 
   spvtools_config_package_dir(SPIRV-Tools-opt PACKAGE_DIR)
diff --git a/third_party/SPIRV-Tools/source/opt/eliminate_dead_io_components_pass.cpp b/third_party/SPIRV-Tools/source/opt/eliminate_dead_io_components_pass.cpp
index e430c6d..916fc27 100644
--- a/third_party/SPIRV-Tools/source/opt/eliminate_dead_io_components_pass.cpp
+++ b/third_party/SPIRV-Tools/source/opt/eliminate_dead_io_components_pass.cpp
@@ -236,7 +236,12 @@
     }
     type_mgr->AttachDecoration(*dec, &new_struct_ty);
   }
-  analysis::Type* reg_new_var_ty = type_mgr->GetRegisteredType(&new_struct_ty);
+  // Clone name instructions for new struct type
+  analysis::Type* reg_new_str_ty = type_mgr->GetRegisteredType(&new_struct_ty);
+  uint32_t new_struct_ty_id = type_mgr->GetTypeInstruction(reg_new_str_ty);
+  context()->CloneNames(old_struct_ty_id, new_struct_ty_id, length);
+  // Attach new type to var
+  analysis::Type* reg_new_var_ty = reg_new_str_ty;
   if (arr_type) {
     analysis::Array new_arr_ty(reg_new_var_ty, arr_type->length_info());
     reg_new_var_ty = type_mgr->GetRegisteredType(&new_arr_ty);
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 ca36dd6..ad581e1 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
@@ -536,6 +536,8 @@
       new BasicBlock(std::move(valid_label)));
   builder.SetInsertPoint(&*new_blk_ptr);
   uint32_t new_ref_id = CloneOriginalReference(ref, &builder);
+  uint32_t null_id = 0;
+  uint32_t ref_type_id = ref->ref_inst->type_id();
   (void)builder.AddBranch(merge_blk_id);
   new_blocks->push_back(std::move(new_blk_ptr));
   // Gen invalid block
@@ -563,10 +565,23 @@
     GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
                         {error_id, u_index_id, u_length_id}, &builder);
   }
+  // Generate a ConstantNull, converting to uint64 if the type cannot be a null.
+  if (new_ref_id != 0) {
+    analysis::TypeManager* type_mgr = context()->get_type_mgr();
+    analysis::Type* ref_type = type_mgr->GetType(ref_type_id);
+    if (ref_type->AsPointer() != nullptr) {
+      context()->AddCapability(spv::Capability::Int64);
+      uint32_t null_u64_id = GetNullId(GetUint64Id());
+      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);
+    }
+  }
   // Remember last invalid block id
   uint32_t last_invalid_blk_id = new_blk_ptr->GetLabelInst()->result_id();
   // Gen zero for invalid  reference
-  uint32_t ref_type_id = ref->ref_inst->type_id();
   (void)builder.AddBranch(merge_blk_id);
   new_blocks->push_back(std::move(new_blk_ptr));
   // Gen merge block
@@ -577,8 +592,7 @@
   // reference.
   if (new_ref_id != 0) {
     Instruction* phi_inst = builder.AddPhi(
-        ref_type_id, {new_ref_id, valid_blk_id, GetNullId(ref_type_id),
-                      last_invalid_blk_id});
+        ref_type_id, {new_ref_id, valid_blk_id, null_id, last_invalid_blk_id});
     context()->ReplaceAllUsesWith(ref->ref_inst->result_id(),
                                   phi_inst->result_id());
   }
@@ -734,15 +748,7 @@
   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(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));
-  }
+  context()->AddCapability(spv::Capability::ImageQuery);
   // Move original block's preceding instructions into first new block
   std::unique_ptr<BasicBlock> new_blk_ptr;
   MovePreludeCode(ref_inst_itr, ref_block_itr, &new_blk_ptr);
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 be361e6..97d25f3 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
@@ -408,14 +408,7 @@
                                                  InstructionBuilder* builder,
                                                  uint32_t* ref_uptr_id) {
   // Enable Int64 if necessary
-  if (!get_feature_mgr()->HasCapability(spv::Capability::Int64)) {
-    std::unique_ptr<Instruction> cap_int64_inst(new Instruction(
-        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));
-  }
+  context()->AddCapability(spv::Capability::Int64);
   // Convert reference pointer to uint64
   uint32_t ref_ptr_id = ref_inst->GetSingleWordInOperand(0);
   Instruction* ref_uptr_inst =
diff --git a/third_party/SPIRV-Tools/source/opt/instruction.cpp b/third_party/SPIRV-Tools/source/opt/instruction.cpp
index ab3ca0f..ece6baf 100644
--- a/third_party/SPIRV-Tools/source/opt/instruction.cpp
+++ b/third_party/SPIRV-Tools/source/opt/instruction.cpp
@@ -73,6 +73,7 @@
       unique_id_(c->TakeNextUniqueId()),
       dbg_line_insts_(std::move(dbg_line)),
       dbg_scope_(kNoDebugScope, kNoInlinedAt) {
+  operands_.reserve(inst.num_operands);
   for (uint32_t i = 0; i < inst.num_operands; ++i) {
     const auto& current_payload = inst.operands[i];
     operands_.emplace_back(
@@ -92,6 +93,7 @@
       has_result_id_(inst.result_id != 0),
       unique_id_(c->TakeNextUniqueId()),
       dbg_scope_(dbg_scope) {
+  operands_.reserve(inst.num_operands);
   for (uint32_t i = 0; i < inst.num_operands; ++i) {
     const auto& current_payload = inst.operands[i];
     operands_.emplace_back(
@@ -110,6 +112,14 @@
       unique_id_(c->TakeNextUniqueId()),
       operands_(),
       dbg_scope_(kNoDebugScope, kNoInlinedAt) {
+  size_t operands_size = in_operands.size();
+  if (has_type_id_) {
+    operands_size++;
+  }
+  if (has_result_id_) {
+    operands_size++;
+  }
+  operands_.reserve(operands_size);
   if (has_type_id_) {
     operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID,
                            std::initializer_list<uint32_t>{ty_id});
diff --git a/third_party/SPIRV-Tools/source/opt/ir_context.h b/third_party/SPIRV-Tools/source/opt/ir_context.h
index d4dbbaa..35075de 100644
--- a/third_party/SPIRV-Tools/source/opt/ir_context.h
+++ b/third_party/SPIRV-Tools/source/opt/ir_context.h
@@ -378,6 +378,11 @@
   // having more than one name. This method returns the first one it finds.
   inline Instruction* GetMemberName(uint32_t struct_type_id, uint32_t index);
 
+  // Copy names from |old_id| to |new_id|. Only copy member name if index is
+  // less than |max_member_index|.
+  inline void CloneNames(const uint32_t old_id, const uint32_t new_id,
+                         const uint32_t max_member_index = UINT32_MAX);
+
   // Sets the message consumer to the given |consumer|. |consumer| which will be
   // invoked every time there is a message to be communicated to the outside.
   void SetMessageConsumer(MessageConsumer c) { consumer_ = std::move(c); }
@@ -1208,6 +1213,25 @@
   return nullptr;
 }
 
+void IRContext::CloneNames(const uint32_t old_id, const uint32_t new_id,
+                           const uint32_t max_member_index) {
+  std::vector<std::unique_ptr<Instruction>> names_to_add;
+  auto names = GetNames(old_id);
+  for (auto n : names) {
+    Instruction* old_name_inst = n.second;
+    if (old_name_inst->opcode() == spv::Op::OpMemberName) {
+      auto midx = old_name_inst->GetSingleWordInOperand(1);
+      if (midx >= max_member_index) continue;
+    }
+    std::unique_ptr<Instruction> new_name_inst(old_name_inst->Clone(this));
+    new_name_inst->SetInOperand(0, {new_id});
+    names_to_add.push_back(std::move(new_name_inst));
+  }
+  // We can't add the new names when we are iterating over name range above.
+  // We can add all the new names now.
+  for (auto& new_name : names_to_add) AddDebug2Inst(std::move(new_name));
+}
+
 }  // namespace opt
 }  // namespace spvtools
 
diff --git a/third_party/SPIRV-Tools/source/reduce/CMakeLists.txt b/third_party/SPIRV-Tools/source/reduce/CMakeLists.txt
index 6fd8409..9ebe418 100644
--- a/third_party/SPIRV-Tools/source/reduce/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/source/reduce/CMakeLists.txt
@@ -101,10 +101,7 @@
 spvtools_check_symbol_exports(SPIRV-Tools-reduce)
 
 if(ENABLE_SPIRV_TOOLS_INSTALL)
-  install(TARGETS SPIRV-Tools-reduce EXPORT SPIRV-Tools-reduceTargets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+  install(TARGETS SPIRV-Tools-reduce EXPORT SPIRV-Tools-reduceTargets)
   export(EXPORT SPIRV-Tools-reduceTargets FILE SPIRV-Tools-reduceTarget.cmake)
 
   spvtools_config_package_dir(SPIRV-Tools-reduce PACKAGE_DIR)
diff --git a/third_party/SPIRV-Tools/source/util/hex_float.h b/third_party/SPIRV-Tools/source/util/hex_float.h
index 06e3c57..98353a4 100644
--- a/third_party/SPIRV-Tools/source/util/hex_float.h
+++ b/third_party/SPIRV-Tools/source/util/hex_float.h
@@ -896,6 +896,47 @@
   return is;
 }
 
+namespace detail {
+
+// Returns a new value formed from 'value' by setting 'bit' that is the
+// 'n'th most significant bit (where 0 is the most significant bit).
+// If 'bit' is zero or 'n' is more than the number of bits in the integer
+// type, then return the original value.
+template <typename UINT_TYPE>
+UINT_TYPE set_nth_most_significant_bit(UINT_TYPE value, UINT_TYPE bit,
+                                       UINT_TYPE n) {
+  constexpr UINT_TYPE max_position = std::numeric_limits<UINT_TYPE>::digits - 1;
+  if ((bit != 0) && (n <= max_position)) {
+    return static_cast<UINT_TYPE>(value | (bit << (max_position - n)));
+  }
+  return value;
+}
+
+// Attempts to increment the argument.
+// If it does not overflow, then increments the argument and returns true.
+// If it would overflow, returns false.
+template <typename INT_TYPE>
+bool saturated_inc(INT_TYPE& value) {
+  if (value == std::numeric_limits<INT_TYPE>::max()) {
+    return false;
+  }
+  value++;
+  return true;
+}
+
+// Attempts to decrement the argument.
+// If it does not underflow, then decrements the argument and returns true.
+// If it would overflow, returns false.
+template <typename INT_TYPE>
+bool saturated_dec(INT_TYPE& value) {
+  if (value == std::numeric_limits<INT_TYPE>::min()) {
+    return false;
+  }
+  value--;
+  return true;
+}
+}  // namespace detail
+
 // Reads a HexFloat from the given stream.
 // If the float is not encoded as a hex-float then it will be parsed
 // as a regular float.
@@ -997,13 +1038,16 @@
         if (bits_written) {
           // If we are here the bits represented belong in the fractional
           // part of the float, and we have to adjust the exponent accordingly.
-          fraction = static_cast<uint_type>(
-              fraction |
-              static_cast<uint_type>(
-                  write_bit << (HF::top_bit_left_shift - fraction_index++)));
-          // TODO(dneto): Avoid overflow. Testing would require
-          // parameterization.
-          exponent = static_cast<int_type>(exponent + 1);
+          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
+                                                          fraction_index);
+          // Increment the fraction index. If the input has bizarrely many
+          // significant digits, then silently drop them.
+          detail::saturated_inc(fraction_index);
+          if (!detail::saturated_inc(exponent)) {
+            // Overflow failure
+            is.setstate(std::ios::failbit);
+            return is;
+          }
         }
         // Since this updated after setting fraction bits, this effectively
         // drops the leading 1 bit.
@@ -1034,14 +1078,17 @@
           // Handle modifying the exponent here this way we can handle
           // an arbitrary number of hex values without overflowing our
           // integer.
-          // TODO(dneto): Handle underflow. Testing would require extra
-          // parameterization.
-          exponent = static_cast<int_type>(exponent - 1);
+          if (!detail::saturated_dec(exponent)) {
+            // Overflow failure
+            is.setstate(std::ios::failbit);
+            return is;
+          }
         } else {
-          fraction = static_cast<uint_type>(
-              fraction |
-              static_cast<uint_type>(
-                  write_bit << (HF::top_bit_left_shift - fraction_index++)));
+          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
+                                                          fraction_index);
+          // Increment the fraction index. If the input has bizarrely many
+          // significant digits, then silently drop them.
+          detail::saturated_inc(fraction_index);
         }
       }
     } else {
diff --git a/third_party/SPIRV-Tools/source/val/validate_cfg.cpp b/third_party/SPIRV-Tools/source/val/validate_cfg.cpp
index 24d2416..9ba66f4 100644
--- a/third_party/SPIRV-Tools/source/val/validate_cfg.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_cfg.cpp
@@ -560,7 +560,7 @@
           target_block->structurally_reachable() &&
           !header->structurally_dominates(*target_block)) {
         return _.diag(SPV_ERROR_INVALID_CFG, header->label())
-               << "Selection header " << _.getIdName(header->id())
+               << "Switch header " << _.getIdName(header->id())
                << " does not structurally dominate its case construct "
                << _.getIdName(target);
       }
diff --git a/third_party/SPIRV-Tools/source/val/validate_decorations.cpp b/third_party/SPIRV-Tools/source/val/validate_decorations.cpp
index ef9753d..f9c8435 100644
--- a/third_party/SPIRV-Tools/source/val/validate_decorations.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_decorations.cpp
@@ -633,10 +633,10 @@
       }
     }
     nextValidOffset = offset + size;
-    if (!scalar_block_layout && blockRules &&
+    if (!scalar_block_layout &&
         (spv::Op::OpTypeArray == opcode || spv::Op::OpTypeStruct == opcode)) {
-      // Uniform block rules don't permit anything in the padding of a struct
-      // or array.
+      // Non-scalar block layout rules don't permit anything in the padding of
+      // a struct or array.
       nextValidOffset = align(nextValidOffset, alignment);
     }
   }
diff --git a/third_party/SPIRV-Tools/source/val/validate_extensions.cpp b/third_party/SPIRV-Tools/source/val/validate_extensions.cpp
index ebb13cf..fa58e0f 100644
--- a/third_party/SPIRV-Tools/source/val/validate_extensions.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_extensions.cpp
@@ -39,6 +39,20 @@
 namespace val {
 namespace {
 
+std::string ReflectionInstructionName(ValidationState_t& _,
+                                      const Instruction* inst) {
+  spv_ext_inst_desc desc = nullptr;
+  if (_.grammar().lookupExtInst(SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION,
+                                inst->word(4), &desc) != SPV_SUCCESS ||
+      !desc) {
+    return std::string("Unknown ExtInst");
+  }
+  std::ostringstream ss;
+  ss << desc->name;
+
+  return ss.str();
+}
+
 uint32_t GetSizeTBitWidth(const ValidationState_t& _) {
   if (_.addressing_model() == spv::AddressingModel::Physical32) return 32;
 
@@ -273,12 +287,14 @@
 }
 
 spv_result_t ValidateClspvReflectionKernel(ValidationState_t& _,
-                                           const Instruction* inst) {
+                                           const Instruction* inst,
+                                           uint32_t version) {
+  const auto inst_name = ReflectionInstructionName(_, inst);
   const auto kernel_id = inst->GetOperandAs<uint32_t>(4);
   const auto kernel = _.FindDef(kernel_id);
   if (kernel->opcode() != spv::Op::OpFunction) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Kernel does not reference a function";
+           << inst_name << " does not reference a function";
   }
 
   bool found_kernel = false;
@@ -290,18 +306,18 @@
   }
   if (!found_kernel) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Kernel does not reference an entry-point";
+           << inst_name << " does not reference an entry-point";
   }
 
   const auto* exec_models = _.GetExecutionModels(kernel_id);
   if (!exec_models || exec_models->empty()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "Kernel does not reference an entry-point";
+           << inst_name << " does not reference an entry-point";
   }
   for (auto exec_model : *exec_models) {
     if (exec_model != spv::ExecutionModel::GLCompute) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "Kernel must refer only to GLCompute entry-points";
+             << inst_name << " must refer only to GLCompute entry-points";
     }
   }
 
@@ -323,6 +339,37 @@
            << "Name must match an entry-point for Kernel";
   }
 
+  const auto num_operands = inst->operands().size();
+  if (version < 5 && num_operands > 6) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Version " << version << " of the " << inst_name
+           << " instruction can only have 2 additional operands";
+  }
+
+  if (num_operands > 6) {
+    const auto num_args_id = inst->GetOperandAs<uint32_t>(6);
+    if (!IsUint32Constant(_, num_args_id)) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "NumArguments must be a 32-bit unsigned integer OpConstant";
+    }
+  }
+
+  if (num_operands > 7) {
+    const auto flags_id = inst->GetOperandAs<uint32_t>(7);
+    if (!IsUint32Constant(_, flags_id)) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "Flags must be a 32-bit unsigned integer OpConstant";
+    }
+  }
+
+  if (num_operands > 8) {
+    const auto atts_id = inst->GetOperandAs<uint32_t>(8);
+    if (_.GetIdOpcode(atts_id) != spv::Op::OpString) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "Attributes must be an OpString";
+    }
+  }
+
   return SPV_SUCCESS;
 }
 
@@ -439,8 +486,8 @@
   return SPV_SUCCESS;
 }
 
-spv_result_t ValidateClspvReflectionArgumentPodBuffer(ValidationState_t& _,
-                                                      const Instruction* inst) {
+spv_result_t ValidateClspvReflectionArgumentOffsetBuffer(ValidationState_t& _,
+                                                         const Instruction* inst) {
   const auto num_operands = inst->operands().size();
   if (auto error = ValidateKernelDecl(_, inst)) {
     return error;
@@ -480,7 +527,7 @@
   return SPV_SUCCESS;
 }
 
-spv_result_t ValidateClspvReflectionArgumentPodPushConstant(
+spv_result_t ValidateClspvReflectionArgumentPushConstant(
     ValidationState_t& _, const Instruction* inst) {
   const auto num_operands = inst->operands().size();
   if (auto error = ValidateKernelDecl(_, inst)) {
@@ -587,8 +634,8 @@
   return SPV_SUCCESS;
 }
 
-spv_result_t ValidateClspvReflectionConstantData(ValidationState_t& _,
-                                                 const Instruction* inst) {
+spv_result_t ValidateClspvReflectionInitializedData(ValidationState_t& _,
+                                                    const Instruction* inst) {
   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
@@ -650,18 +697,250 @@
   return SPV_SUCCESS;
 }
 
+spv_result_t ValidateClspvReflectionSubgroupMaxSize(ValidationState_t& _,
+                                                    const Instruction* inst) {
+  const auto size_id = inst->GetOperandAs<uint32_t>(4);
+  if (!IsUint32Constant(_, size_id)) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Size must be a 32-bit unsigned integer OpConstant";
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateClspvReflectionPointerRelocation(ValidationState_t& _,
+                                                      const Instruction* inst) {
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "ObjectOffset must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "PointerOffset must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "PointerSize must be a 32-bit unsigned integer OpConstant";
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateClspvReflectionImageMetadataPushConstant(
+    ValidationState_t& _, const Instruction* inst) {
+  if (auto error = ValidateKernelDecl(_, inst)) {
+    return error;
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Ordinal must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Offset must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Size must be a 32-bit unsigned integer OpConstant";
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateClspvReflectionImageMetadataUniform(
+    ValidationState_t& _, const Instruction* inst) {
+  if (auto error = ValidateKernelDecl(_, inst)) {
+    return error;
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Ordinal must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Binding must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(8))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Offset must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(9))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Size must be a 32-bit unsigned integer OpConstant";
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateClspvReflectionPushConstantData(ValidationState_t& _,
+                                                     const Instruction* inst) {
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Offset must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Size must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != spv::Op::OpString) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst) << "Data must be an OpString";
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateClspvReflectionPrintfInfo(ValidationState_t& _,
+                                              const Instruction* inst) {
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "PrintfID must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(5)) != spv::Op::OpString) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "FormatString must be an OpString";
+  }
+
+  for (size_t i = 6; i < inst->operands().size(); ++i) {
+    if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(i))) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "ArgumentSizes must be a 32-bit unsigned integer OpConstant";
+    }
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateClspvReflectionPrintfStorageBuffer(ValidationState_t& _,
+                                                        const Instruction* inst) {
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Binding must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Size must be a 32-bit unsigned integer OpConstant";
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateClspvReflectionPrintfPushConstant(ValidationState_t& _,
+                                                       const Instruction* inst) {
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Offset must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "Size must be a 32-bit unsigned integer OpConstant";
+  }
+
+  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "BufferSize must be a 32-bit unsigned integer OpConstant";
+  }
+
+  return SPV_SUCCESS;
+}
+
 spv_result_t ValidateClspvReflectionInstruction(ValidationState_t& _,
                                                 const Instruction* inst,
-                                                uint32_t /*version*/) {
+                                                uint32_t version) {
   if (!_.IsVoidType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Return Type must be OpTypeVoid";
   }
 
-  auto ext_inst = inst->GetOperandAs<NonSemanticClspvReflectionInstructions>(3);
+  uint32_t required_version = 0;
+  const auto ext_inst =
+      inst->GetOperandAs<NonSemanticClspvReflectionInstructions>(3);
   switch (ext_inst) {
     case NonSemanticClspvReflectionKernel:
-      return ValidateClspvReflectionKernel(_, inst);
+    case NonSemanticClspvReflectionArgumentInfo:
+    case NonSemanticClspvReflectionArgumentStorageBuffer:
+    case NonSemanticClspvReflectionArgumentUniform:
+    case NonSemanticClspvReflectionArgumentPodStorageBuffer:
+    case NonSemanticClspvReflectionArgumentPodUniform:
+    case NonSemanticClspvReflectionArgumentPodPushConstant:
+    case NonSemanticClspvReflectionArgumentSampledImage:
+    case NonSemanticClspvReflectionArgumentStorageImage:
+    case NonSemanticClspvReflectionArgumentSampler:
+    case NonSemanticClspvReflectionArgumentWorkgroup:
+    case NonSemanticClspvReflectionSpecConstantWorkgroupSize:
+    case NonSemanticClspvReflectionSpecConstantGlobalOffset:
+    case NonSemanticClspvReflectionSpecConstantWorkDim:
+    case NonSemanticClspvReflectionPushConstantGlobalOffset:
+    case NonSemanticClspvReflectionPushConstantEnqueuedLocalSize:
+    case NonSemanticClspvReflectionPushConstantGlobalSize:
+    case NonSemanticClspvReflectionPushConstantRegionOffset:
+    case NonSemanticClspvReflectionPushConstantNumWorkgroups:
+    case NonSemanticClspvReflectionPushConstantRegionGroupOffset:
+    case NonSemanticClspvReflectionConstantDataStorageBuffer:
+    case NonSemanticClspvReflectionConstantDataUniform:
+    case NonSemanticClspvReflectionLiteralSampler:
+    case NonSemanticClspvReflectionPropertyRequiredWorkgroupSize:
+      required_version = 1;
+      break;
+    case NonSemanticClspvReflectionSpecConstantSubgroupMaxSize:
+      required_version = 2;
+      break;
+    case NonSemanticClspvReflectionArgumentPointerPushConstant:
+    case NonSemanticClspvReflectionArgumentPointerUniform:
+    case NonSemanticClspvReflectionProgramScopeVariablesStorageBuffer:
+    case NonSemanticClspvReflectionProgramScopeVariablePointerRelocation:
+    case NonSemanticClspvReflectionImageArgumentInfoChannelOrderPushConstant:
+    case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypePushConstant:
+    case NonSemanticClspvReflectionImageArgumentInfoChannelOrderUniform:
+    case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypeUniform:
+      required_version = 3;
+      break;
+    case NonSemanticClspvReflectionArgumentStorageTexelBuffer:
+    case NonSemanticClspvReflectionArgumentUniformTexelBuffer:
+      required_version = 4;
+      break;
+    case NonSemanticClspvReflectionConstantDataPointerPushConstant:
+    case NonSemanticClspvReflectionProgramScopeVariablePointerPushConstant:
+    case NonSemanticClspvReflectionPrintfInfo:
+    case NonSemanticClspvReflectionPrintfBufferStorageBuffer:
+    case NonSemanticClspvReflectionPrintfBufferPointerPushConstant:
+      required_version = 5;
+      break;
+    default:
+      break;
+  }
+  if (version < required_version) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << ReflectionInstructionName(_, inst) << " requires version "
+           << required_version << ", but parsed version is " << version;
+  }
+
+  switch (ext_inst) {
+    case NonSemanticClspvReflectionKernel:
+      return ValidateClspvReflectionKernel(_, inst, version);
     case NonSemanticClspvReflectionArgumentInfo:
       return ValidateClspvReflectionArgumentInfo(_, inst);
     case NonSemanticClspvReflectionArgumentStorageBuffer:
@@ -669,12 +948,16 @@
     case NonSemanticClspvReflectionArgumentSampledImage:
     case NonSemanticClspvReflectionArgumentStorageImage:
     case NonSemanticClspvReflectionArgumentSampler:
+    case NonSemanticClspvReflectionArgumentStorageTexelBuffer:
+    case NonSemanticClspvReflectionArgumentUniformTexelBuffer:
       return ValidateClspvReflectionArgumentBuffer(_, inst);
     case NonSemanticClspvReflectionArgumentPodStorageBuffer:
     case NonSemanticClspvReflectionArgumentPodUniform:
-      return ValidateClspvReflectionArgumentPodBuffer(_, inst);
+    case NonSemanticClspvReflectionArgumentPointerUniform:
+      return ValidateClspvReflectionArgumentOffsetBuffer(_, inst);
     case NonSemanticClspvReflectionArgumentPodPushConstant:
-      return ValidateClspvReflectionArgumentPodPushConstant(_, inst);
+    case NonSemanticClspvReflectionArgumentPointerPushConstant:
+      return ValidateClspvReflectionArgumentPushConstant(_, inst);
     case NonSemanticClspvReflectionArgumentWorkgroup:
       return ValidateClspvReflectionArgumentWorkgroup(_, inst);
     case NonSemanticClspvReflectionSpecConstantWorkgroupSize:
@@ -691,11 +974,31 @@
       return ValidateClspvReflectionPushConstant(_, inst);
     case NonSemanticClspvReflectionConstantDataStorageBuffer:
     case NonSemanticClspvReflectionConstantDataUniform:
-      return ValidateClspvReflectionConstantData(_, inst);
+    case NonSemanticClspvReflectionProgramScopeVariablesStorageBuffer:
+      return ValidateClspvReflectionInitializedData(_, inst);
     case NonSemanticClspvReflectionLiteralSampler:
       return ValidateClspvReflectionSampler(_, inst);
     case NonSemanticClspvReflectionPropertyRequiredWorkgroupSize:
       return ValidateClspvReflectionPropertyRequiredWorkgroupSize(_, inst);
+    case NonSemanticClspvReflectionSpecConstantSubgroupMaxSize:
+      return ValidateClspvReflectionSubgroupMaxSize(_, inst);
+    case NonSemanticClspvReflectionProgramScopeVariablePointerRelocation:
+      return ValidateClspvReflectionPointerRelocation(_, inst);
+    case NonSemanticClspvReflectionImageArgumentInfoChannelOrderPushConstant:
+    case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypePushConstant:
+      return ValidateClspvReflectionImageMetadataPushConstant(_, inst);
+    case NonSemanticClspvReflectionImageArgumentInfoChannelOrderUniform:
+    case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypeUniform:
+      return ValidateClspvReflectionImageMetadataUniform(_, inst);
+    case NonSemanticClspvReflectionConstantDataPointerPushConstant:
+    case NonSemanticClspvReflectionProgramScopeVariablePointerPushConstant:
+      return ValidateClspvReflectionPushConstantData(_, inst);
+    case NonSemanticClspvReflectionPrintfInfo:
+      return ValidateClspvReflectionPrintfInfo(_, inst);
+    case NonSemanticClspvReflectionPrintfBufferStorageBuffer:
+      return ValidateClspvReflectionPrintfStorageBuffer(_, inst);
+    case NonSemanticClspvReflectionPrintfBufferPointerPushConstant:
+      return ValidateClspvReflectionPrintfPushConstant(_, inst);
     default:
       break;
   }
diff --git a/third_party/SPIRV-Tools/source/val/validate_memory.cpp b/third_party/SPIRV-Tools/source/val/validate_memory.cpp
index 57fd23d..5f7358c 100644
--- a/third_party/SPIRV-Tools/source/val/validate_memory.cpp
+++ b/third_party/SPIRV-Tools/source/val/validate_memory.cpp
@@ -1398,7 +1398,7 @@
       }
       default: {
         // Give an error. reached non-composite type while indexes still remain.
-        return _.diag(SPV_ERROR_INVALID_ID, cur_word_instr)
+        return _.diag(SPV_ERROR_INVALID_ID, inst)
                << instr_name
                << " reached non-composite type while indexes "
                   "still remain to be traversed.";
diff --git a/third_party/SPIRV-Tools/source/wasm/build.sh b/third_party/SPIRV-Tools/source/wasm/build.sh
index f02ae52..4f7b701 100755
--- a/third_party/SPIRV-Tools/source/wasm/build.sh
+++ b/third_party/SPIRV-Tools/source/wasm/build.sh
@@ -16,6 +16,11 @@
 
 set -e
 
+# This is required to run any git command in the docker since owner will
+# have changed between the clone environment, and the docker container.
+# Marking the root of the repo as safe for ownership changes.
+git config --global --add safe.directory /app
+
 NUM_CORES=$(nproc)
 echo "Detected $NUM_CORES cores for building"
 
diff --git a/third_party/SPIRV-Tools/docker-compose.yml b/third_party/SPIRV-Tools/source/wasm/docker-compose.yml
similarity index 83%
rename from third_party/SPIRV-Tools/docker-compose.yml
rename to third_party/SPIRV-Tools/source/wasm/docker-compose.yml
index fb6d114..2340fdb 100644
--- a/third_party/SPIRV-Tools/docker-compose.yml
+++ b/third_party/SPIRV-Tools/source/wasm/docker-compose.yml
@@ -1,7 +1,7 @@
 version: "3"
 services:
   build:
-    image: emscripten/emsdk:2.0.2
+    image: emscripten/emsdk:3.1.28
     environment:
       GITHUB_RUN_NUMBER: ${GITHUB_RUN_NUMBER:-}
     working_dir: /app
diff --git a/third_party/SPIRV-Tools/test/cpp_interface_test.cpp b/third_party/SPIRV-Tools/test/cpp_interface_test.cpp
index 5d11698..222f44f 100644
--- a/third_party/SPIRV-Tools/test/cpp_interface_test.cpp
+++ b/third_party/SPIRV-Tools/test/cpp_interface_test.cpp
@@ -322,6 +322,36 @@
   EXPECT_EQ(Header(), optimized_text);
 }
 
+TEST(SpirvHeadersCpp, BitwiseOrMemoryAccessMask) {
+  EXPECT_EQ(spv::MemoryAccessMask(6), spv::MemoryAccessMask::Aligned |
+                                          spv::MemoryAccessMask::Nontemporal);
+}
+
+TEST(SpirvHeadersCpp, BitwiseAndMemoryAccessMask) {
+  EXPECT_EQ(spv::MemoryAccessMask::Aligned,
+            spv::MemoryAccessMask::Aligned & spv::MemoryAccessMask(6));
+  EXPECT_EQ(spv::MemoryAccessMask::Nontemporal,
+            spv::MemoryAccessMask::Nontemporal & spv::MemoryAccessMask(6));
+  EXPECT_EQ(spv::MemoryAccessMask(0), spv::MemoryAccessMask::Nontemporal &
+                                          spv::MemoryAccessMask::Aligned);
+}
+
+TEST(SpirvHeadersCpp, BitwiseXorMemoryAccessMask) {
+  EXPECT_EQ(spv::MemoryAccessMask::Nontemporal,
+            spv::MemoryAccessMask::Aligned ^ spv::MemoryAccessMask(6));
+  EXPECT_EQ(spv::MemoryAccessMask::Aligned,
+            spv::MemoryAccessMask::Nontemporal ^ spv::MemoryAccessMask(6));
+  EXPECT_EQ(spv::MemoryAccessMask(6), spv::MemoryAccessMask::Nontemporal ^
+                                          spv::MemoryAccessMask::Aligned);
+  EXPECT_EQ(spv::MemoryAccessMask(0), spv::MemoryAccessMask::Nontemporal ^
+                                          spv::MemoryAccessMask::Nontemporal);
+}
+
+TEST(SpirvHeadersCpp, BitwiseNegateMemoryAccessMask) {
+  EXPECT_EQ(spv::MemoryAccessMask(~(uint32_t(4))),
+            ~spv::MemoryAccessMask::Nontemporal);
+}
+
 // TODO(antiagainst): tests for SetMessageConsumer().
 
 }  // namespace
diff --git a/third_party/SPIRV-Tools/test/hex_float_test.cpp b/third_party/SPIRV-Tools/test/hex_float_test.cpp
index 25d3c70..a44d9ec 100644
--- a/third_party/SPIRV-Tools/test/hex_float_test.cpp
+++ b/third_party/SPIRV-Tools/test/hex_float_test.cpp
@@ -1348,9 +1348,11 @@
   return os;
 }
 
-using FloatStreamParseTest = ::testing::TestWithParam<StreamParseCase<float>>;
+using Float32StreamParseTest = ::testing::TestWithParam<StreamParseCase<float>>;
+using Float16StreamParseTest =
+    ::testing::TestWithParam<StreamParseCase<Float16>>;
 
-TEST_P(FloatStreamParseTest, Samples) {
+TEST_P(Float32StreamParseTest, Samples) {
   std::stringstream input(GetParam().literal);
   HexFloat<FloatProxy<float>> parsed_value(0.0f);
   // Hex floats must be read with the stream input operator.
@@ -1367,8 +1369,87 @@
   }
 }
 
+// Returns a Float16 constructed from its sign bit, unbiased exponent, and
+// mantissa.
+Float16 makeF16(int sign_bit, int unbiased_exp, int mantissa) {
+  EXPECT_LE(0, sign_bit);
+  EXPECT_LE(sign_bit, 1);
+  // Exponent is 5 bits, with bias of 15.
+  EXPECT_LE(-15, unbiased_exp);  // -15 means zero or subnormal
+  EXPECT_LE(unbiased_exp, 16);   // 16 means infinity or NaN
+  EXPECT_LE(0, mantissa);
+  EXPECT_LE(mantissa, 0x3ff);
+  const unsigned biased_exp = 15 + unbiased_exp;
+  const uint32_t as_bits = sign_bit << 15 | (biased_exp << 10) | mantissa;
+  EXPECT_LE(as_bits, 0xffffu);
+  return Float16(static_cast<uint16_t>(as_bits));
+}
+
+TEST_P(Float16StreamParseTest, Samples) {
+  std::stringstream input(GetParam().literal);
+  HexFloat<FloatProxy<Float16>> parsed_value(makeF16(0, 0, 0));
+  // Hex floats must be read with the stream input operator.
+  input >> parsed_value;
+  if (GetParam().expect_success) {
+    EXPECT_FALSE(input.fail());
+    std::string suffix;
+    input >> suffix;
+    const auto got = parsed_value.value();
+    const auto expected = GetParam().expected_value.value();
+    EXPECT_EQ(got.data(), expected.data())
+        << "got: " << got << " expected: " << expected;
+  } else {
+    EXPECT_TRUE(input.fail());
+  }
+}
+
 INSTANTIATE_TEST_SUITE_P(
-    HexFloatExponentMissingDigits, FloatStreamParseTest,
+    HexFloat32FillSignificantDigits, Float32StreamParseTest,
+    ::testing::ValuesIn(std::vector<StreamParseCase<float>>{
+        {"0x123456p0", true, "", ldexpf(0x123456, 0)},
+        // Patterns that fill all mantissa bits
+        {"0x1.fffffep+23", true, "", ldexpf(0x1fffffe, -1)},
+        {"0x1f.ffffep+19", true, "", ldexpf(0x1fffffe, -1)},
+        {"0x1ff.fffep+15", true, "", ldexpf(0x1fffffe, -1)},
+        {"0x1fff.ffep+11", true, "", ldexpf(0x1fffffe, -1)},
+        {"0x1ffff.fep+7", true, "", ldexpf(0x1fffffe, -1)},
+        {"0x1fffff.ep+3", true, "", ldexpf(0x1fffffe, -1)},
+        {"0x1fffffe.p-1", true, "", ldexpf(0x1fffffe, -1)},
+        {"0xffffff.p+0", true, "", ldexpf(0x1fffffe, -1)},
+        {"0xffffff.p+0", true, "", ldexpf(0xffffff, 0)},
+        // Now drop some bits in the middle
+        {"0xa5a5a5.p+0", true, "", ldexpf(0xa5a5a5, 0)},
+        {"0x5a5a5a.p+0", true, "", ldexpf(0x5a5a5a, 0)}}));
+
+INSTANTIATE_TEST_SUITE_P(
+    HexFloat32ExcessSignificantDigits, Float32StreamParseTest,
+    ::testing::ValuesIn(std::vector<StreamParseCase<float>>{
+        // Base cases
+        {"0x1.fffffep0", true, "", ldexpf(0xffffff, -23)},
+        {"0xa5a5a5p0", true, "", ldexpf(0xa5a5a5, 0)},
+        {"0xa.5a5a5p+9", true, "", ldexpf(0xa5a5a5, -11)},
+        {"0x5a5a5ap0", true, "", ldexpf(0x5a5a5a, 0)},
+        {"0x5.a5a5ap+9", true, "", ldexpf(0x5a5a5a, -11)},
+        // Truncate extra bits: zeroes
+        {"0x1.fffffe0p0", true, "", ldexpf(0xffffff, -23)},
+        {"0xa5a5a5000p0", true, "", ldexpf(0xa5a5a5, 12)},
+        {"0xa.5a5a5000p+9", true, "", ldexpf(0xa5a5a5, -11)},
+        {"0x5a5a5a000p0", true, "", ldexpf(0x5a5a5a, 12)},
+        {"0x5.a5a5a000p+9", true, "", ldexpf(0x5a5a5a, -11)},
+        // Truncate extra bits: ones
+        {"0x1.ffffffp0",  // Extra bits in the last nibble
+         true, "", ldexpf(0xffffff, -23)},
+        {"0x1.fffffffp0", true, "", ldexpf(0xffffff, -23)},
+        {"0xa5a5a5fffp0", true, "", ldexpf(0xa5a5a5, 12)},
+        {"0xa.5a5a5fffp+9", true, "", ldexpf(0xa5a5a5, -11)},
+        {"0x5a5a5afffp0",
+         // The 5 nibble (0101), leads with 0, so the result can fit a leading
+         // 1 bit , yielding 8 (1000).
+         true, "", ldexpf(0x5a5a5a8, 8)},
+        {"0x5.a5a5afffp+9", true, "", ldexpf(0x5a5a5a8, 8 - 32 + 9)}}));
+
+INSTANTIATE_TEST_SUITE_P(
+    HexFloat32ExponentMissingDigits, Float32StreamParseTest,
     ::testing::ValuesIn(std::vector<StreamParseCase<float>>{
         {"0x1.0p1", true, "", 2.0f},
         {"0x1.0p1a", true, "a", 2.0f},
@@ -1388,7 +1469,7 @@
         {"0x1.0p--", false, "", 0.0f}}));
 
 INSTANTIATE_TEST_SUITE_P(
-    HexFloatExponentTrailingSign, FloatStreamParseTest,
+    HexFloat32ExponentTrailingSign, Float32StreamParseTest,
     ::testing::ValuesIn(std::vector<StreamParseCase<float>>{
         // Don't consume a sign after the binary exponent digits.
         {"0x1.0p1", true, "", 2.0f},
@@ -1396,7 +1477,7 @@
         {"0x1.0p1-", true, "-", 2.0f}}));
 
 INSTANTIATE_TEST_SUITE_P(
-    HexFloatPositiveExponentOverflow, FloatStreamParseTest,
+    HexFloat32PositiveExponentOverflow, Float32StreamParseTest,
     ::testing::ValuesIn(std::vector<StreamParseCase<float>>{
         // Positive exponents
         {"0x1.0p1", true, "", 2.0f},       // fine, a normal number
@@ -1412,7 +1493,7 @@
     }));
 
 INSTANTIATE_TEST_SUITE_P(
-    HexFloatNegativeExponentOverflow, FloatStreamParseTest,
+    HexFloat32NegativeExponentOverflow, Float32StreamParseTest,
     ::testing::ValuesIn(std::vector<StreamParseCase<float>>{
         // Positive results, digits before '.'
         {"0x1.0p-126", true, "",
@@ -1436,7 +1517,109 @@
         {"0x0.0p-5000000000", true, "", 0.0f},  // zero mantissa, zero result
     }));
 
-// TODO(awoloszyn): Add fp16 tests and HexFloatTraits.
+INSTANTIATE_TEST_SUITE_P(
+    HexFloat16ExcessSignificantDigits, Float16StreamParseTest,
+    ::testing::ValuesIn(std::vector<StreamParseCase<Float16>>{
+        // Zero
+        {"0x1.c00p0", true, "", makeF16(0, 0, 0x300)},
+        {"0x0p0", true, "", makeF16(0, -15, 0x0)},
+        {"0x000.0000p0", true, "", makeF16(0, -15, 0x0)},
+        // All leading 1s
+        {"0x1p0", true, "", makeF16(0, 0, 0x0)},
+        {"0x1.8p0", true, "", makeF16(0, 0, 0x200)},
+        {"0x1.cp0", true, "", makeF16(0, 0, 0x300)},
+        {"0x1.ep0", true, "", makeF16(0, 0, 0x380)},
+        {"0x1.fp0", true, "", makeF16(0, 0, 0x3c0)},
+        {"0x1.f8p0", true, "", makeF16(0, 0, 0x3e0)},
+        {"0x1.fcp0", true, "", makeF16(0, 0, 0x3f0)},
+        {"0x1.fep0", true, "", makeF16(0, 0, 0x3f8)},
+        {"0x1.ffp0", true, "", makeF16(0, 0, 0x3fc)},
+        // Fill trailing zeros to all significant places
+        // that might be used for significant digits.
+        {"0x1.ff8p0", true, "", makeF16(0, 0, 0x3fe)},
+        {"0x1.ffcp0", true, "", makeF16(0, 0, 0x3ff)},
+        {"0x1.800p0", true, "", makeF16(0, 0, 0x200)},
+        {"0x1.c00p0", true, "", makeF16(0, 0, 0x300)},
+        {"0x1.e00p0", true, "", makeF16(0, 0, 0x380)},
+        {"0x1.f00p0", true, "", makeF16(0, 0, 0x3c0)},
+        {"0x1.f80p0", true, "", makeF16(0, 0, 0x3e0)},
+        {"0x1.fc0p0", true, "", makeF16(0, 0, 0x3f0)},
+        {"0x1.fe0p0", true, "", makeF16(0, 0, 0x3f8)},
+        {"0x1.ff0p0", true, "", makeF16(0, 0, 0x3fc)},
+        {"0x1.ff8p0", true, "", makeF16(0, 0, 0x3fe)},
+        {"0x1.ffcp0", true, "", makeF16(0, 0, 0x3ff)},
+        // Add several trailing zeros
+        {"0x1.c00000p0", true, "", makeF16(0, 0, 0x300)},
+        {"0x1.e00000p0", true, "", makeF16(0, 0, 0x380)},
+        {"0x1.f00000p0", true, "", makeF16(0, 0, 0x3c0)},
+        {"0x1.f80000p0", true, "", makeF16(0, 0, 0x3e0)},
+        {"0x1.fc0000p0", true, "", makeF16(0, 0, 0x3f0)},
+        {"0x1.fe0000p0", true, "", makeF16(0, 0, 0x3f8)},
+        {"0x1.ff0000p0", true, "", makeF16(0, 0, 0x3fc)},
+        {"0x1.ff8000p0", true, "", makeF16(0, 0, 0x3fe)},
+        {"0x1.ffcp0000", true, "", makeF16(0, 0, 0x3ff)},
+        // Samples that drop out bits in the middle.
+        //   5 = 0101    4 = 0100
+        //   a = 1010    8 = 1000
+        {"0x1.5a4p0", true, "", makeF16(0, 0, 0x169)},
+        {"0x1.a58p0", true, "", makeF16(0, 0, 0x296)},
+        // Samples that drop out bits *and* truncate significant bits
+        // that can't be represented.
+        {"0x1.5a40000p0", true, "", makeF16(0, 0, 0x169)},
+        {"0x1.5a7ffffp0", true, "", makeF16(0, 0, 0x169)},
+        {"0x1.a580000p0", true, "", makeF16(0, 0, 0x296)},
+        {"0x1.a5bffffp0", true, "", makeF16(0, 0, 0x296)},
+        // Try some negations.
+        {"-0x0p0", true, "", makeF16(1, -15, 0x0)},
+        {"-0x000.0000p0", true, "", makeF16(1, -15, 0x0)},
+        {"-0x1.5a40000p0", true, "", makeF16(1, 0, 0x169)},
+        {"-0x1.5a7ffffp0", true, "", makeF16(1, 0, 0x169)},
+        {"-0x1.a580000p0", true, "", makeF16(1, 0, 0x296)},
+        {"-0x1.a5bffffp0", true, "", makeF16(1, 0, 0x296)}}));
+
+INSTANTIATE_TEST_SUITE_P(
+    HexFloat16IncreasingExponentsAndMantissa, Float16StreamParseTest,
+    ::testing::ValuesIn(std::vector<StreamParseCase<Float16>>{
+        // Zero
+        {"0x0p0", true, "", makeF16(0, -15, 0x0)},
+        {"0x0p5000000000000", true, "", makeF16(0, -15, 0x0)},
+        {"-0x0p5000000000000", true, "", makeF16(1, -15, 0x0)},
+        // Leading 1
+        {"0x1p0", true, "", makeF16(0, 0, 0x0)},
+        {"0x1p1", true, "", makeF16(0, 1, 0x0)},
+        {"0x1p16", true, "", makeF16(0, 16, 0x0)},
+        {"0x1p-1", true, "", makeF16(0, -1, 0x0)},
+        {"0x1p-14", true, "", makeF16(0, -14, 0x0)},
+        // Leading 2
+        {"0x2p0", true, "", makeF16(0, 1, 0x0)},
+        {"0x2p1", true, "", makeF16(0, 2, 0x0)},
+        {"0x2p15", true, "", makeF16(0, 16, 0x0)},
+        {"0x2p-1", true, "", makeF16(0, 0, 0x0)},
+        {"0x2p-15", true, "", makeF16(0, -14, 0x0)},
+        // Leading 8
+        {"0x8p0", true, "", makeF16(0, 3, 0x0)},
+        {"0x8p1", true, "", makeF16(0, 4, 0x0)},
+        {"0x8p13", true, "", makeF16(0, 16, 0x0)},
+        {"0x8p-3", true, "", makeF16(0, 0, 0x0)},
+        {"0x8p-17", true, "", makeF16(0, -14, 0x0)},
+        // Leading 10
+        {"0x10.0p0", true, "", makeF16(0, 4, 0x0)},
+        {"0x10.0p1", true, "", makeF16(0, 5, 0x0)},
+        {"0x10.0p12", true, "", makeF16(0, 16, 0x0)},
+        {"0x10.0p-5", true, "", makeF16(0, -1, 0x0)},
+        {"0x10.0p-18", true, "", makeF16(0, -14, 0x0)},
+        // Samples that drop out bits *and* truncate significant bits
+        // that can't be represented.
+        // Progressively increase the leading digit.
+        {"0x1.5a40000p0", true, "", makeF16(0, 0, 0x169)},
+        {"0x1.5a7ffffp0", true, "", makeF16(0, 0, 0x169)},
+        {"0x2.5a40000p0", true, "", makeF16(0, 1, 0x0b4)},
+        {"0x2.5a7ffffp0", true, "", makeF16(0, 1, 0x0b4)},
+        {"0x4.5a40000p0", true, "", makeF16(0, 2, 0x05a)},
+        {"0x4.5a7ffffp0", true, "", makeF16(0, 2, 0x05a)},
+        {"0x8.5a40000p0", true, "", makeF16(0, 3, 0x02d)},
+        {"0x8.5a7ffffp0", true, "", makeF16(0, 3, 0x02d)}}));
+
 }  // namespace
 }  // namespace utils
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/eliminate_dead_io_components_test.cpp b/third_party/SPIRV-Tools/test/opt/eliminate_dead_io_components_test.cpp
index f175e49..da26cef 100644
--- a/third_party/SPIRV-Tools/test/opt/eliminate_dead_io_components_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/eliminate_dead_io_components_test.cpp
@@ -445,9 +445,9 @@
     %v2float = OpTypeVector %float 2
      %Vertex = OpTypeStruct %v4float %v2float
 ; CHECK: %Vertex = OpTypeStruct %v4float %v2float
-; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
+; CHECK: %Vertex_0 = OpTypeStruct %v4float
 %_ptr_Input_Vertex = OpTypePointer Input %Vertex
-; CHECK: [[pty:%\w+]] = OpTypePointer Input [[sty]]
+; CHECK: [[pty:%\w+]] = OpTypePointer Input %Vertex_0
       %iVert = OpVariable %_ptr_Input_Vertex Input
 ; CHECK: %iVert = OpVariable [[pty]] Input
         %int = OpTypeInt 32 1
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 4f4b668..3600d0d 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
@@ -159,9 +159,9 @@
 ; 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+}} = 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+}}
@@ -567,14 +567,12 @@
 %_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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )";
   // clang-format on
 
@@ -601,10 +599,10 @@
 ; 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: {{%\w+}} = 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: %104 = OpPhi %v4float %46 %42 [[null_v4float]] %43
 ; CHECK: OpStore %_entryPointOutput_vColor %104
 OpReturn
 OpFunctionEnd
@@ -706,14 +704,14 @@
 %_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: {{%\w+}} = 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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )";
   // clang-format on
 
@@ -738,10 +736,10 @@
 ; 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: {{%\w+}} = 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
+; CHECK: %112 = OpPhi %v4float %54 %50 [[null_v4float]] %51
 %39 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1
 %40 = OpLoad %uint %39
 %41 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %40
@@ -763,7 +761,7 @@
 ; 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: %122 = OpPhi %v4float %119 %115 [[null_v4float]] %116
 ; CHECK: %45 = OpFAdd %v4float %112 %122
 OpStore %_entryPointOutput_vColor %45
 OpReturn
@@ -835,14 +833,13 @@
 %_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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )";
   // clang-format on
 
@@ -868,10 +865,10 @@
 ; 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: {{%\w+}} = 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: %142 = OpPhi %v4float %84 %80 [[null_v4float]] %81
 ; CHECK: OpStore %_entryPointOutput_vColor %142
 OpReturn
 OpFunctionEnd
@@ -940,14 +937,13 @@
 %_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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )";
   // clang-format on
 
@@ -971,10 +967,10 @@
 ; 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: {{%\w+}} = 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: %137 = OpPhi %v4float %79 %76 [[null_v4float]] %77
 ; CHECK: OpStore %_entryPointOutput_vColor %137
 OpReturn
 OpFunctionEnd
@@ -1167,14 +1163,13 @@
 %_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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )";
   // clang-format on
 
@@ -1205,11 +1200,11 @@
 ; 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: [[bitcast_result:%\w+]] = OpBitcast %uint %37
+; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_74 %uint_0 [[bitcast_result]] %uint_128
 ; CHECK: OpBranch %47
 ; CHECK: %47 = OpLabel
-; CHECK: %107 = OpPhi %v4float %51 %48 %106 %49
+; CHECK: %107 = OpPhi %v4float %51 %48 [[null_v4float]] %49
 ; CHECK: %43 = OpAccessChain %_ptr_Output_v4float %_ %int_0
 ; CHECK: OpStore %43 %107
 OpReturn
@@ -1309,7 +1304,6 @@
 %_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
@@ -1319,7 +1313,7 @@
 ; CHECK: %_ptr_Input_v3float = OpTypePointer Input %v3float
 ; CHECK: %gl_TessCoord = OpVariable %_ptr_Input_v3float Input
 ; CHECK: %v3uint = OpTypeVector %uint 3
-; CHECK: %101 = OpConstantNull %v4float
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )";
   // clang-format on
 
@@ -1338,10 +1332,10 @@
 ; 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: {{%\w+}} = 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
+; CHECK: %102 = OpPhi %v4float %38 %36 [[null_v4float]] %37
 %31 = OpAccessChain %_ptr_Output_v4float %_ %int_0
 OpStore %31 %29
 ; CHECK-NOT: OpStore %31 %29
@@ -1435,14 +1429,13 @@
 %_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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )";
   // clang-format on
 
@@ -1492,13 +1485,16 @@
 ; 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: {{%\w+}} = 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: [[phi_result:%\w+]] = OpPhi %v4float %68 %64 [[null_v4float]] %65
 ; CHECK: OpLine %5 24 0
 %47 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0
 OpStore %47 %45
+; CHECK-NOT: OpStore %47 %45
+; CHECK: [[store_loc:%\w+]] = OpAccessChain %_ptr_Function_v4float %ps_output %int_0
+; CHECK: OpStore [[store_loc]] [[phi_result]]
 OpLine %1 25 0
 %48 = OpLoad %PS_OUTPUT %ps_output
 OpReturnValue %48
@@ -1580,13 +1576,11 @@
 )" + 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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )";
   // clang-format on
 
@@ -1624,14 +1618,14 @@
 ; 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: [[phi_result_1:%\w+]] = OpPhi %v4float %143 %139 [[null_v4float]] %140
 ; CHECK: OpBranch %58
 ; CHECK: %60 = OpLabel
-; CHECK: %115 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_59 %uint_0 %32 %55
+; CHECK: {{%\w+}} = 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
+; CHECK: [[phi_result_2:%\w+]] = OpPhi %v4float [[phi_result_1]] %138 [[null_v4float]] %60
+; CHECK: OpStore %_entryPointOutput_vColor [[phi_result_2]]
 OpReturn
 OpFunctionEnd
 )";
@@ -1698,12 +1692,11 @@
 )" + 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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )";
   // clang-format on
 
@@ -1728,11 +1721,11 @@
 ; 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: {{%\w+}} = 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
+; CHECK: [[phi_result:%\w+]] = OpPhi %v4float %59 %55 [[null_v4float]] %56
+; CHECK: OpStore %_entryPointOutput_vColor [[phi_result]]
 OpReturn
 OpFunctionEnd
 )";
@@ -1932,14 +1925,12 @@
 )" + 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
+; CHECK: [[null_float:%\w+]] = OpConstantNull %float
 )";
   // clang-format on
 
@@ -1970,15 +1961,15 @@
 ; 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: [[phi_result_1:%\w+]] = OpPhi %float %127 %125 [[null_float]] %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: [[bitcast_result:%\w+]] = OpBitcast %uint %7
+; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 [[bitcast_result]] %40
 ; CHECK: OpBranch %43
 ; CHECK: %43 = OpLabel
-; CHECK: %102 = OpPhi %float %130 %124 %101 %45
-; CHECK: OpStore %b %102
+; CHECK: [[phi_result_2:%\w+]] = OpPhi %float [[phi_result_1]] %124 [[null_float]] %45
+; CHECK: OpStore %b [[phi_result_2]]
 OpReturn
 OpFunctionEnd
 )";
@@ -2062,14 +2053,12 @@
 )" + 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
+; CHECK: [[null_float:%\w+]] = OpConstantNull %float
 )";
   // clang-format on
 
@@ -2087,8 +2076,8 @@
 ; 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: [[bitcast_result_1:%\w+]] = OpBitcast %uint %7
+; CHECK: %122 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_3 [[bitcast_result_1]]
 ; CHECK: %123 = OpULessThan %bool %uint_0 %122
 ; CHECK: OpSelectionMerge %124 None
 ; CHECK: OpBranchConditional %123 %125 %126
@@ -2100,15 +2089,15 @@
 ; 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: [[phi_result_1:%\w+]] = OpPhi %float %127 %125 [[null_float]] %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: [[bitcast_result_2:%\w+]] = OpBitcast %uint %7
+; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 [[bitcast_result_2]] %40
 ; CHECK: OpBranch %43
 ; CHECK: %43 = OpLabel
-; CHECK: %102 = OpPhi %float %130 %124 %101 %45
-; CHECK: OpStore %b %102
+; CHECK: [[phi_result_2:%\w+]] = OpPhi %float [[phi_result_1]] %124 [[null_float]] %45
+; CHECK: OpStore %b [[phi_result_2]]
 OpReturn
 OpFunctionEnd
 )";
@@ -2181,14 +2170,12 @@
 )" + 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
+; CHECK: [[null_float:%\w+]] = OpConstantNull %float
 )";
   // clang-format on
 
@@ -2219,15 +2206,15 @@
 ; 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: [[phi_result_1:%\w+]] = OpPhi %float %127 %125 [[null_float]] %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: [[bitcast_result:%\w+]] = OpBitcast %uint %7
+; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_45 %uint_0 [[bitcast_result]] %40
 ; CHECK: OpBranch %43
 ; CHECK: %43 = OpLabel
-; CHECK: %102 = OpPhi %float %130 %124 %101 %45
-; CHECK: OpStore %b %102
+; CHECK: [[phi_result_2:%\w+]] = OpPhi %float [[phi_result_1]] %124 [[null_float]] %45
+; CHECK: OpStore %b [[phi_result_2]]
 OpReturn
 OpFunctionEnd
 )";
@@ -2296,13 +2283,12 @@
 )" + 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
+; CHECK: [[null_float:%\w+]] = OpConstantNull %float
 )";
   // clang-format on
 
@@ -2322,11 +2308,11 @@
 ; 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: {{%\w+}} = 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
+; CHECK: [[phi_result:%\w+]] = OpPhi %float %50 %48 [[null_float]] %49
+; CHECK: OpStore %b [[phi_result]]
 OpReturn
 OpFunctionEnd
 )";
@@ -2523,7 +2509,6 @@
 %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
@@ -2531,8 +2516,7 @@
 ; 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
+; CHECK: [[null_float:%\w+]] = OpConstantNull %float
 )" + kInputGlobals;
   // clang-format on
 
@@ -2562,15 +2546,15 @@
 ; 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: [[phi_result_1:%\w+]] = OpPhi %float %117 %115 [[null_float]] %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: [[bitcast_result:%\w+]] = OpBitcast %uint %7
+; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_46 %uint_0 [[bitcast_result]] %uint_128
 ; CHECK: OpBranch %26
 ; CHECK: %26 = OpLabel
-; CHECK: %89 = OpPhi %float %120 %114 %88 %28
-; CHECK: OpStore %b %89
+; CHECK: [[phi_result_2:%\w+]] = OpPhi %float [[phi_result_1]] %114 [[null_float]] %28
+; CHECK: OpStore %b [[phi_result_2]]
 OpReturn
 OpFunctionEnd
 )";
@@ -2653,19 +2637,16 @@
 %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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
+; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint
 )";
   // clang-format on
 
@@ -2689,10 +2670,10 @@
 ; 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: {{%\w+}} = 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: [[phi_result_1:%\w+]] = OpPhi %uint %137 %135 [[null_uint]] %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
@@ -2701,7 +2682,7 @@
 ; 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: {{%\w+}} = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_1 [[phi_result_1]]
 ; CHECK: %143 = OpULessThan %bool %uint_0 %142
 ; CHECK: OpSelectionMerge %144 None
 ; CHECK: OpBranchConditional %143 %145 %146
@@ -2713,13 +2694,13 @@
 ; 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: [[phi_result_2:%\w+]] = OpPhi %v4float %148 %145 [[null_v4float]] %146
 ; CHECK: OpBranch %51
 ; CHECK: %53 = OpLabel
-; CHECK: %111 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_50 %uint_0 %141 %48
+; CHECK: {{%\w+}} = 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: %113 = OpPhi %v4float [[phi_result_2]] %144 [[null_v4float]] %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
@@ -2774,7 +2755,7 @@
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint RayGenerationNV %main "main"
-; CHECK: OpEntryPoint RayGenerationNV %main "main" %89
+; CHECK: OpEntryPoint RayGenerationNV %main "main" [[launch_id:%\w+]]
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -2794,7 +2775,7 @@
 OpDecorate %images NonWritable
 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
 )" + kInputDecorations + kOutputDecorations + R"(
-; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
+; CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
@@ -2821,14 +2802,9 @@
 )" + 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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
+; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint
 )";
   // clang-format on
 
@@ -2852,10 +2828,10 @@
 ; 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: {{%\w+}} = 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: %142 = OpPhi %uint %138 %136 [[null_uint]] %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
@@ -2876,13 +2852,13 @@
 ; 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: %151 = OpPhi %v4float %149 %146 [[null_v4float]] %147
 ; CHECK: OpBranch %51
 ; CHECK: %53 = OpLabel
-; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: {{%\w+}} = 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: %114 = OpPhi %v4float %151 %145 [[null_v4float]] %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
@@ -2936,7 +2912,7 @@
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint IntersectionNV %main "main"
-; CHECK: OpEntryPoint IntersectionNV %main "main" %89
+; CHECK: OpEntryPoint IntersectionNV %main "main" [[launch_id:%\w+]]
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -2956,7 +2932,7 @@
 OpDecorate %images NonWritable
 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
 )" + kInputDecorations + kOutputDecorations + R"(
-; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
+; CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
@@ -2984,12 +2960,9 @@
 ; 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
+; CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
+; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint
 )";
   // clang-format on
 
@@ -3013,10 +2986,10 @@
 ; 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: {{%\w+}} = 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: %142 = OpPhi %uint %138 %136 [[null_uint]] %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
@@ -3037,13 +3010,13 @@
 ; 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: %151 = OpPhi %v4float %149 %146 [[null_v4float]] %147
 ; CHECK: OpBranch %51
 ; CHECK: %53 = OpLabel
-; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: {{%\w+}} = 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: %114 = OpPhi %v4float %151 %145 [[null_v4float]] %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
@@ -3097,7 +3070,7 @@
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint AnyHitNV %main "main"
-; CHECK: OpEntryPoint AnyHitNV %main "main" %89
+; CHECK: OpEntryPoint AnyHitNV %main "main" [[launch_id:%\w+]]
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -3117,7 +3090,7 @@
 OpDecorate %images NonWritable
 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
 )" + kInputDecorations + kOutputDecorations + R"(
-; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
+; CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
@@ -3144,14 +3117,10 @@
 )" + 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
+; CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
+; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint
 )";
   // clang-format on
 
@@ -3175,10 +3144,10 @@
 ; 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: {{%\w+}} = 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: %142 = OpPhi %uint %138 %136 [[null_uint]] %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
@@ -3199,13 +3168,13 @@
 ; 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: %151 = OpPhi %v4float %149 %146 [[null_v4float]] %147
 ; CHECK: OpBranch %51
 ; CHECK: %53 = OpLabel
-; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: {{%\w+}} = 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: %114 = OpPhi %v4float %151 %145 [[null_v4float]] %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
@@ -3259,7 +3228,7 @@
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint ClosestHitNV %main "main"
-; CHECK: OpEntryPoint ClosestHitNV %main "main" %89
+; CHECK: OpEntryPoint ClosestHitNV %main "main" [[launch_id:%\w+]]
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -3279,7 +3248,7 @@
 OpDecorate %images NonWritable
 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
 )" + kInputDecorations + kOutputDecorations + R"(
-; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
+; CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
@@ -3306,14 +3275,10 @@
 )" + 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
+; CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
+; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint
 )";
   // clang-format on
 
@@ -3337,10 +3302,10 @@
 ; 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: {{%\w+}} = 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: %142 = OpPhi %uint %138 %136 [[null_uint]] %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
@@ -3361,13 +3326,13 @@
 ; 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: %151 = OpPhi %v4float %149 %146 [[null_v4float]] %147
 ; CHECK: OpBranch %51
 ; CHECK: %53 = OpLabel
-; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: {{%\w+}} = 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: %114 = OpPhi %v4float %151 %145 [[null_v4float]] %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
@@ -3421,7 +3386,7 @@
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint MissNV %main "main"
-; CHECK: OpEntryPoint MissNV %main "main" %89
+; CHECK: OpEntryPoint MissNV %main "main" [[launch_id:%\w+]]
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -3441,7 +3406,7 @@
 OpDecorate %images NonWritable
 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
 )" + kInputDecorations + kOutputDecorations + R"(
-; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
+; CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
@@ -3468,14 +3433,10 @@
 )" + 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
+; CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
+; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint
 )";
   // clang-format on
 
@@ -3499,10 +3460,10 @@
 ; 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: {{%\w+}} = 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: %142 = OpPhi %uint %138 %136 [[null_uint]] %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
@@ -3523,13 +3484,13 @@
 ; 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: %151 = OpPhi %v4float %149 %146 [[null_v4float]] %147
 ; CHECK: OpBranch %51
 ; CHECK: %53 = OpLabel
-; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: {{%\w+}} = 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: %114 = OpPhi %v4float %151 %145 [[null_v4float]] %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
@@ -3583,7 +3544,7 @@
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint CallableNV %main "main"
-; CHECK: OpEntryPoint CallableNV %main "main" %89
+; CHECK: OpEntryPoint CallableNV %main "main" [[launch_id:%\w+]]
 OpSource GLSL 460
 OpSourceExtension "GL_EXT_nonuniform_qualifier"
 OpSourceExtension "GL_NV_ray_tracing"
@@ -3603,7 +3564,7 @@
 OpDecorate %images NonWritable
 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
 )" + kInputDecorations + kOutputDecorations + R"(
-; CHECK: OpDecorate %89 BuiltIn LaunchIdNV
+; CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV
 %void = OpTypeVoid
 %3 = OpTypeFunction %void
 %uint = OpTypeInt 32 0
@@ -3630,14 +3591,9 @@
 )" + 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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
+; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint
 )";
   // clang-format on
 
@@ -3661,10 +3617,10 @@
 ; 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: {{%\w+}} = 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: %142 = OpPhi %uint %138 %136 [[null_uint]] %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
@@ -3685,13 +3641,13 @@
 ; 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: %151 = OpPhi %v4float %149 %146 [[null_v4float]] %147
 ; CHECK: OpBranch %51
 ; CHECK: %53 = OpLabel
-; CHECK: %112 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_51 %uint_0 %142 %48
+; CHECK: {{%\w+}} = 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: %114 = OpPhi %v4float %151 %145 [[null_v4float]] %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
@@ -3822,17 +3778,11 @@
 %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
+; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
 )" + kInputGlobals + R"(
-; CHECK: %165 = OpConstantNull %v2float
+; CHECK: [[null_v2float:%\w+]] = OpConstantNull %v2float
 )";
   // clang-format on
 
@@ -3870,10 +3820,10 @@
 ; 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: {{%\w+}} = 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: %166 = OpPhi %v2float %162 %160 [[null_v2float]] %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
@@ -3889,7 +3839,7 @@
 ; 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: %178 = OpPhi %v4float %175 %171 [[null_v4float]] %172
 ; CHECK: %51 = OpCompositeExtract %float %178 0
 OpStore %y %51
 %54 = OpLoad %float %x
@@ -4017,12 +3967,11 @@
  ;CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
  )" + kInputGlobals + R"(
  ;CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
- ;CHECK:         %148 = OpTypeFunction %void %uint %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:        %202 = OpConstantNull %v2float
+ ;CHECK:        [[null_v2float:%\w+]] = OpConstantNull %v2float
      %MainPs = OpFunction %void None %3
           %5 = OpLabel
  ;CHECK: %140 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_1 %uint_0
@@ -4048,10 +3997,10 @@
  ;CHECK:        %146 = OpLoad %v2float %86
  ;CHECK:               OpBranch %143
  ;CHECK:        %145 = OpLabel
- ;CHECK:        %201 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_71 %uint_4 %uint_0 %119 %140
+ ;CHECK:        {{%\w+}} = 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
+ ;CHECK:        %203 = OpPhi %v2float %146 %144 [[null_v2float]] %145
                OpBranch %91
          %88 = OpLabel
          %89 = OpAccessChain %_ptr_Uniform_v2float %__0 %int_1
@@ -4068,7 +4017,7 @@
  ;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
+ ;CHECK:        %212 = OpPhi %v2float %209 %207 [[null_v2float]] %208
                OpBranch %91
          %91 = OpLabel
         %115 = OpPhi %v2float %87 %85 %90 %88
@@ -4210,12 +4159,11 @@
 )" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
-;CHECK:        %132 = OpTypeFunction %void %uint %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:        %185 = OpConstantNull %v2float
+;CHECK:        [[null_v2float:%\w+]] = OpConstantNull %v2float
      %MainPs = OpFunction %void None %3
           %5 = OpLabel
 ;CHECK:        %123 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_2 %uint_0
@@ -4240,10 +4188,10 @@
 ;CHECK:        %130 = OpLoad %v2float %81
 ;CHECK:               OpBranch %127
 ;CHECK:        %129 = OpLabel
-;CHECK:        %184 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_78 %uint_4 %uint_0 %101 %123
+;CHECK:        {{%\w+}} = 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
+;CHECK:        %186 = OpPhi %v2float %130 %128 [[null_v2float]] %129
          %86 = OpFAdd %v2float %66 %82
 ;CHECK-NOT:         %86 = OpFAdd %v2float %66 %82
 ;CHECK:             %86 = OpFAdd %v2float %66 %186
@@ -4353,13 +4301,12 @@
 )" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
-;CHECK:        %135 = OpTypeFunction %void %uint %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:        %189 = OpConstantNull %v2float
-;CHECK:        %201 = OpConstantNull %v4float
+;CHECK:        [[null_v2float:%\w+]] = OpConstantNull %v2float
+;CHECK:        [[null_v4float:%\w+]] = OpConstantNull %v4float
      %MainPs = OpFunction %void None %3
           %5 = OpLabel
 ;CHECK:        %126 = OpFunctionCall %uint %inst_bindless_direct_read_4 %uint_0 %uint_0 %uint_2 %uint_0
@@ -4387,10 +4334,10 @@
 ;CHECK:        %133 = OpLoad %v2float %81
 ;CHECK:               OpBranch %130
 ;CHECK:        %132 = OpLabel
-;CHECK:        %188 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_78 %uint_4 %uint_0 %101 %126
+;CHECK:        {{%\w+}} = 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
+;CHECK:        %190 = OpPhi %v2float %133 %131 [[null_v2float]] %132
 ;CHECK:         %86 = OpFAdd %v2float %66 %190
          %87 = OpLoad %46 %g_tColor
          %88 = OpLoad %50 %g_sAniso
@@ -4408,10 +4355,10 @@
 ;CHECK:        %198 = OpImageSampleImplicitLod %v4float %197 %86
 ;CHECK:               OpBranch %193
 ;CHECK:        %195 = OpLabel
-;CHECK:        %200 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_83 %uint_1 %uint_0 %uint_0 %uint_0
+;CHECK:        {{%\w+}} = 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:        %202 = OpPhi %v4float %198 %194 [[null_v4float]] %195
 ;CHECK:               OpStore %_entryPointOutput_vColor %202
                OpReturn
                OpFunctionEnd
@@ -4490,15 +4437,12 @@
 %_ptr_Output_v4float = OpTypePointer Output %v4float
 %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
 ;CHECK:       %bool = OpTypeBool
-;CHECK:         %51 = 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:        %106 = OpConstantNull %v4float
-;CHECK:        %111 = OpTypeFunction %uint %uint %uint %uint %uint
+;CHECK:        [[null_v4float:%\w+]] = OpConstantNull %v4float
 )" + kInputGlobals + R"(
      %MainPs = OpFunction %void None %10
          %30 = OpLabel
@@ -4539,14 +4483,14 @@
 ;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:        [[phi_result_1:%\w+]] = OpPhi %v4float %138 %134 [[null_v4float]] %135
 ;CHECK:               OpBranch %44
 ;CHECK:         %46 = OpLabel
-;CHECK:        %105 = OpFunctionCall %void %inst_bindless_stream_write_4 %uint_60 %uint_0 %41 %uint_128
+;CHECK:        {{%\w+}} = 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
+;CHECK:        [[phi_result_2:%\w+]] = OpPhi %v4float [[phi_result_1]] %133 [[null_v4float]] %46
+;CHECK:               OpStore %_entryPointOutput_vColor [[phi_result_2]]
                OpReturn
                OpFunctionEnd
 )" + kStreamWrite4Frag + kDirectRead4;
@@ -4681,12 +4625,10 @@
 )" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
-;CHECK:         %88 = OpTypeFunction %void %uint %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:        %142 = OpConstantNull %v2float
+;CHECK:        [[null_v2float:%\w+]] = OpConstantNull %v2float
      %MainPs = OpFunction %void None %14
          %37 = OpLabel
 ;CHECK:         %79 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
@@ -4714,10 +4656,10 @@
 ;CHECK:         %86 = OpLoad %v2float %41
 ;CHECK:               OpBranch %83
 ;CHECK:         %85 = OpLabel
-;CHECK:        %141 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_81 %uint_4 %uint_0 %58 %79
+;CHECK:        {{%\w+}} = 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
+;CHECK:        %143 = OpPhi %v2float %86 %84 [[null_v2float]] %85
 ;CHECK:         %43 = OpFAdd %v2float %38 %143
          %44 = OpLoad %30 %g_tColor
          %45 = OpLoad %32 %g_sAniso
@@ -4808,23 +4750,16 @@
     %v4float = OpTypeVector %float 4
 %_ptr_Input_v4float = OpTypePointer Input %v4float
  %a_position = OpVariable %_ptr_Input_v4float Input
-;CHECK;         %37 = OpTypeFunction %uint %uint %uint %uint
-;CHECK;%_runtimearr_uint = OpTypeRuntimeArray %uint
+;CHECK:         %37 = OpTypeFunction %uint %uint %uint %uint
+;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
 )" + kInputGlobals + R"(
-;CHECK;%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
-;CHECK;       %bool = OpTypeBool
-;CHECK;         %63 = OpTypeFunction %void %uint %uint %uint %uint %uint
+;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+;CHECK:       %bool = OpTypeBool
 )" + 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_45 = OpConstant %uint 45
-;CHECK;        %115 = OpConstantNull %float
+;CHECK:%_ptr_Input_uint = OpTypePointer Input %uint
+;CHECK:%gl_VertexIndex = OpVariable %_ptr_Input_uint Input
+;CHECK:%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input
+;CHECK: [[null_float:%\w+]] = OpConstantNull %float
        %main = OpFunction %void None %3
           %5 = OpLabel
 ;CHECK:         %55 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
@@ -4847,10 +4782,10 @@
 ;CHECK:         %61 = OpLoad %float %20
 ;CHECK:               OpBranch %58
 ;CHECK:         %60 = OpLabel
-;CHECK:        %114 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_45 %uint_4 %uint_0 %35 %55
+;CHECK:        {{\w+}} = 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
+;CHECK:        %116 = OpPhi %float %61 %59 [[null_float]] %60
                OpStore %v_vtxResult %21
 ;CHECK-NOT:           OpStore %v_vtxResult %21
 ;CHECK:               OpStore %v_vtxResult %116
@@ -4943,12 +4878,11 @@
 )" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
-;CHECK:         %63 = OpTypeFunction %void %uint %uint %uint %uint %uint
 )" + 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:        %114 = OpConstantNull %float
+;CHECK: [[null_float:%\w+]] = OpConstantNull %float
 %main = OpFunction %void None %3
           %5 = OpLabel
 ;CHECK:         %55 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
@@ -4971,10 +4905,10 @@
 ;CHECK:         %61 = OpLoad %float %20
 ;CHECK:               OpBranch %58
 ;CHECK:         %60 = OpLabel
-;CHECK:        %113 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_45 %uint_4 %uint_0 %35 %55
+;CHECK:    {{%\w+}} = 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
+;CHECK:        %115 = OpPhi %float %61 %59 [[null_float]] %60
                OpStore %v_vtxResult %21
 ;CHECK-NOT:           OpStore %v_vtxResult %21
 ;CHECK:               OpStore %v_vtxResult %115
@@ -5074,12 +5008,11 @@
 )" + kInputGlobals + R"(
 ;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
 ;CHECK:       %bool = OpTypeBool
-;CHECK:         %72 = OpTypeFunction %void %uint %uint %uint %uint %uint
 )" + 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:        %124 = OpConstantNull %v2float
+;CHECK: [[null_v2float:%\w+]] = OpConstantNull %v2float
        %main = OpFunction %void None %3
           %5 = OpLabel
 ;CHECK:         %64 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
@@ -5106,10 +5039,10 @@
 ;CHECK:         %70 = OpLoad %v2float %25
 ;CHECK:               OpBranch %67
 ;CHECK:         %69 = OpLabel
-;CHECK:        %123 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_51 %uint_4 %uint_0 %43 %64
+;CHECK:        {{%\w+}} = 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:        %125 = OpPhi %v2float %70 %68 [[null_v2float]] %69
 ;CHECK:               OpStore %v_vtxResult %125
                OpReturn
                OpFunctionEnd
@@ -5172,14 +5105,12 @@
                     %ii = OpVariable %_ptr_Input_int Input
 ;CHECK:           %uint = OpTypeInt 32 0
 ;CHECK:           %bool = OpTypeBool
-;CHECK:             %35 = OpTypeFunction %void %uint %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:             %93 = OpConstantNull %v4float
+;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
                   %main = OpFunction %void None %3
                      %5 = OpLabel
 ;CHECK:                   OpBranch %21
@@ -5204,10 +5135,10 @@
 ;CHECK:             %33 = OpImageRead %v4float %32 %17
 ;CHECK:                   OpBranch %29
 ;CHECK:             %31 = OpLabel
-;CHECK:             %92 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_33 %uint_7 %uint_0 %23 %25
+;CHECK:             {{%\w+}} = 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:             %94 = OpPhi %v4float %33 %30 [[null_v4float]] %31
 ;CHECK:                   OpStore %x %94
                           OpReturn
                           OpFunctionEnd
@@ -5365,14 +5296,12 @@
                     %ii = OpVariable %_ptr_Input_int Input
 ;CHECK:           %uint = OpTypeInt 32 0
 ;CHECK:           %bool = OpTypeBool
-;CHECK:             %35 = OpTypeFunction %void %uint %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:             %94 = OpConstantNull %v4float
+;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
                   %main = OpFunction %void None %3
                      %5 = OpLabel
 ;CHECK:                   OpBranch %21
@@ -5397,10 +5326,10 @@
 ;CHECK:             %33 = OpImageFetch %v4float %32 %17
 ;CHECK:                   OpBranch %29
 ;CHECK:             %31 = OpLabel
-;CHECK:             %93 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_32 %uint_6 %uint_0 %23 %25
+;CHECK:             {{%\w+}} = 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:             %95 = OpPhi %v4float %33 %30 [[null_v4float]] %31
 ;CHECK:                   OpStore %x %95
                           OpReturn
                           OpFunctionEnd
@@ -5464,14 +5393,12 @@
                     %ii = OpVariable %_ptr_Input_int Input
 ;CHECK:           %uint = OpTypeInt 32 0
 ;CHECK:           %bool = OpTypeBool
-;CHECK:             %38 = OpTypeFunction %void %uint %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:             %97 = OpConstantNull %v4float
+;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float
                   %main = OpFunction %void None %3
                      %5 = OpLabel
 ;CHECK:                   OpBranch %23
@@ -5498,10 +5425,10 @@
 ;CHECK:             %36 = OpImageFetch %v4float %35 %18
 ;CHECK:                   OpBranch %31
 ;CHECK:             %33 = OpLabel
-;CHECK:             %96 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_34 %uint_6 %uint_0 %25 %27
+;CHECK:             {{%\w+}} = 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:             %98 = OpPhi %v4float %36 %32 [[null_v4float]] %33
 ;CHECK:                   OpStore %x %98
                           OpReturn
                           OpFunctionEnd
@@ -5572,14 +5499,12 @@
                     %ii = OpVariable %_ptr_Input_int Input
 ;CHECK:           %uint = OpTypeInt 32 0
 ;CHECK:           %bool = OpTypeBool
-;CHECK:             %44 = OpTypeFunction %void %uint %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
+;CHECK:            [[null_v4float:%\w+]] = OpConstantNull %v4float
                   %main = OpFunction %void None %3
                      %5 = OpLabel
 ;CHECK:                   OpBranch %28
@@ -5609,10 +5534,10 @@
 ;CHECK:             %42 = OpImageFetch %v4float %41 %23
 ;CHECK:                   OpBranch %36
 ;CHECK:             %38 = OpLabel
-;CHECK:            %102 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_42 %uint_6 %uint_0 %30 %32
+;CHECK:            {{%\w+}} = 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:            %104 = OpPhi %v4float %42 %37 [[null_v4float]] %38
 ;CHECK:                   OpStore %x %104
                           OpReturn
                           OpFunctionEnd
@@ -5625,6 +5550,148 @@
                                                false, true, true, true);
 }
 
+TEST_F(InstBindlessTest, DeviceBufferAddressOOB) {
+  // #version 450
+  // #extension GL_EXT_buffer_reference : enable
+  //  layout(buffer_reference, buffer_reference_align = 16) buffer bufStruct;
+  // layout(set = 0, binding = 0) uniform ufoo {
+  //     bufStruct data;
+  //     int nWrites;
+  // } u_info;
+  // layout(buffer_reference, std140) buffer bufStruct {
+  //     int a[4];
+  // };
+  // void main() {
+  //     for (int i=0; i < u_info.nWrites; ++i) {
+  //         u_info.data.a[i] = 0xdeadca71;
+  //     }
+  // }
+
+  // clang-format off
+  const std::string text = R"(
+OpCapability Shader
+OpCapability PhysicalStorageBufferAddresses
+;CHECK: OpCapability Int64
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel PhysicalStorageBuffer64 GLSL450
+OpEntryPoint Vertex %main "main" %u_info
+;CHECK: OpEntryPoint Vertex %main "main" %u_info %inst_bindless_input_buffer %inst_bindless_output_buffer %gl_VertexIndex %gl_InstanceIndex
+OpSource GLSL 450
+OpSourceExtension "GL_EXT_buffer_reference"
+OpName %main "main"
+OpName %i "i"
+OpName %ufoo "ufoo"
+OpMemberName %ufoo 0 "data"
+OpMemberName %ufoo 1 "nWrites"
+OpName %bufStruct "bufStruct"
+OpMemberName %bufStruct 0 "a"
+OpName %u_info "u_info"
+OpMemberDecorate %ufoo 0 Offset 0
+OpMemberDecorate %ufoo 1 Offset 8
+OpDecorate %ufoo Block
+OpDecorate %_arr_int_uint_4 ArrayStride 16
+OpMemberDecorate %bufStruct 0 Offset 0
+OpDecorate %bufStruct Block
+OpDecorate %u_info DescriptorSet 0
+OpDecorate %u_info Binding 0)"
+    + kInputDecorations + kOutputDecorations +
+R"(%void = OpTypeVoid
+%3 = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+%int_0 = OpConstant %int 0
+OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_bufStruct PhysicalStorageBuffer
+%ufoo = OpTypeStruct %_ptr_PhysicalStorageBuffer_bufStruct %int
+%uint = OpTypeInt 32 0
+%uint_4 = OpConstant %uint 4
+%_arr_int_uint_4 = OpTypeArray %int %uint_4
+%bufStruct = OpTypeStruct %_arr_int_uint_4
+%_ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer PhysicalStorageBuffer %bufStruct
+%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo
+%u_info = OpVariable %_ptr_Uniform_ufoo Uniform
+%int_1 = OpConstant %int 1
+%_ptr_Uniform_int = OpTypePointer Uniform %int
+%bool = OpTypeBool
+%_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer Uniform %_ptr_PhysicalStorageBuffer_bufStruct
+%int_n559035791 = OpConstant %int -559035791
+%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int)"
+    + kInputGlobals + kOutputGlobals +
+R"(%main = OpFunction %void None %3
+%5 = OpLabel
+%i = OpVariable %_ptr_Function_int Function
+;CHECK: OpBranch %137
+;CHECK: %137 = OpLabel
+;CHECK: 65 = OpFunctionCall %uint %inst_bindless_direct_read_3 %uint_1 %uint_0 %uint_0
+;CHECK: OpBranch %40
+;CHECK: 40 = OpLabel
+;CHECK: OpBranch %39
+;CHECK: 39 = OpLabel
+OpStore %i %int_0
+OpBranch %10
+%10 = OpLabel
+OpLoopMerge %12 %13 None
+OpBranch %14
+%14 = OpLabel
+%15 = OpLoad %int %i
+%26 = OpAccessChain %_ptr_Uniform_int %u_info %int_1
+%27 = OpLoad %int %26
+%29 = OpSLessThan %bool %15 %27
+;CHECK-NOT: %27 = OpLoad %int %26
+;CHECK-NOT: %29 = OpSLessThan %bool %15 %27
+;CHECK: 43 = OpIAdd %uint %uint_8 %uint_3
+;CHECK: 66 = OpULessThan %bool %43 %65
+;CHECK: OpSelectionMerge %67 None
+;CHECK: OpBranchConditional %66 %68 %69
+;CHECK: 68 = OpLabel
+;CHECK: 70 = OpLoad %int %26
+;CHECK: OpBranch %67
+;CHECK: 69 = OpLabel
+;CHECK: 122 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_54 %uint_4 %uint_0 %43 %65
+;CHECK: OpBranch %67
+;CHECK: 67 = OpLabel
+;CHECK: 124 = OpPhi %int %70 %68 %123 %69
+;CHECK: 29 = OpSLessThan %bool %15 %124
+OpBranchConditional %29 %11 %12
+%11 = OpLabel
+%31 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0
+%32 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %31
+;CHECK-NOT: %32 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %31
+;CHECK: 125 = OpIAdd %uint %uint_0 %uint_7
+;CHECK: 126 = OpULessThan %bool %125 %65
+;CHECK: OpSelectionMerge %127 None
+;CHECK: OpBranchConditional %126 %128 %129
+;CHECK: 128 = OpLabel
+;CHECK: 130 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %31
+;CHECK: OpBranch %127
+;CHECK: 129 = OpLabel
+;CHECK: 132 = OpFunctionCall %void %inst_bindless_stream_write_5 %uint_59 %uint_4 %uint_0 %125 %65
+;CHECK: 135 = OpConvertUToPtr %_ptr_PhysicalStorageBuffer_bufStruct %134
+;CHECK: OpBranch %127
+;CHECK: 127 = OpLabel
+;CHECK: 136 = OpPhi %_ptr_PhysicalStorageBuffer_bufStruct %130 %128 %135 %129
+%33 = OpLoad %int %i
+%36 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %32 %int_0 %33
+;CHECK-NOT: %36 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %32 %int_0 %33
+;CHECK: %36 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %136 %int_0 %33
+OpStore %36 %int_n559035791 Aligned 16
+OpBranch %13
+%13 = OpLabel
+%37 = OpLoad %int %i
+%38 = OpIAdd %int %37 %int_1
+OpStore %i %38
+OpBranch %10
+%12 = OpLabel
+OpReturn
+OpFunctionEnd)"
+    + kDirectRead3 + kStreamWrite5Vert;
+  // clang-format on
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false, true,
+                                               true, true, true);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //   Compute shader
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 7886ba7..b08f7b0 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
@@ -120,6 +120,22 @@
 )" + kStreamWrite4End;
 // clang-format on
 
+// clang-format off
+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;
+// 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
@@ -552,6 +568,118 @@
       defs + decorates + globals + main_func + output_funcs, true);
 }
 
+TEST_F(InstBuffAddrTest, DeviceBufferAddressOOB) {
+  // #version 450
+  // #extension GL_EXT_buffer_reference : enable
+  //  layout(buffer_reference, buffer_reference_align = 16) buffer bufStruct;
+  // layout(set = 0, binding = 0) uniform ufoo {
+  //     bufStruct data;
+  //     int nWrites;
+  // } u_info;
+  // layout(buffer_reference, std140) buffer bufStruct {
+  //     int a[4];
+  // };
+  // void main() {
+  //     for (int i=0; i < u_info.nWrites; ++i) {
+  //         u_info.data.a[i] = 0xdeadca71;
+  //     }
+  // }
+
+  // clang-format off
+  const std::string text = R"(
+OpCapability Shader
+OpCapability PhysicalStorageBufferAddresses
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel PhysicalStorageBuffer64 GLSL450
+OpEntryPoint Vertex %main "main" %u_info
+;CHECK: OpEntryPoint Vertex %main "main" %u_info %inst_buff_addr_input_buffer %inst_buff_addr_output_buffer %gl_VertexIndex %gl_InstanceIndex
+OpSource GLSL 450
+OpSourceExtension "GL_EXT_buffer_reference"
+OpName %main "main"
+OpName %i "i"
+OpName %ufoo "ufoo"
+OpMemberName %ufoo 0 "data"
+OpMemberName %ufoo 1 "nWrites"
+OpName %bufStruct "bufStruct"
+OpMemberName %bufStruct 0 "a"
+OpName %u_info "u_info"
+OpMemberDecorate %ufoo 0 Offset 0
+OpMemberDecorate %ufoo 1 Offset 8
+OpDecorate %ufoo Block
+OpDecorate %_arr_int_uint_4 ArrayStride 16
+OpMemberDecorate %bufStruct 0 Offset 0
+OpDecorate %bufStruct Block
+OpDecorate %u_info DescriptorSet 0
+OpDecorate %u_info Binding 0)" + kInputDecorations + kOutputDecorations + R"(
+%void = OpTypeVoid
+%3 = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+%int_0 = OpConstant %int 0
+OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_bufStruct PhysicalStorageBuffer
+%ufoo = OpTypeStruct %_ptr_PhysicalStorageBuffer_bufStruct %int
+%uint = OpTypeInt 32 0
+%uint_4 = OpConstant %uint 4
+%_arr_int_uint_4 = OpTypeArray %int %uint_4
+%bufStruct = OpTypeStruct %_arr_int_uint_4
+%_ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer PhysicalStorageBuffer %bufStruct
+%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo
+%u_info = OpVariable %_ptr_Uniform_ufoo Uniform
+%int_1 = OpConstant %int 1
+%_ptr_Uniform_int = OpTypePointer Uniform %int
+%bool = OpTypeBool
+%_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer Uniform %_ptr_PhysicalStorageBuffer_bufStruct
+%int_n559035791 = OpConstant %int -559035791
+%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int)" + kInputGlobals + kOutputGlobals + R"(
+%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
+%26 = OpAccessChain %_ptr_Uniform_int %u_info %int_1
+%27 = OpLoad %int %26
+%29 = OpSLessThan %bool %15 %27
+OpBranchConditional %29 %11 %12
+%11 = OpLabel
+%31 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0
+%32 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %31
+%33 = OpLoad %int %i
+%36 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %32 %int_0 %33
+;CHECK: %41 = OpConvertPtrToU %ulong %36
+;CHECK: %76 = OpFunctionCall %bool %inst_buff_addr_search_and_test %41 %uint_4
+;CHECK: OpSelectionMerge %77 None
+;CHECK: OpBranchConditional %76 %78 %79
+;CHECK: %78 = OpLabel
+OpStore %36 %int_n559035791 Aligned 16
+;CHECK: OpBranch %77
+;CHECK: 79 = OpLabel
+;CHECK: 80 = OpUConvert %uint %41
+;CHECK: 82 = OpShiftRightLogical %ulong %41 %uint_32
+;CHECK: 83 = OpUConvert %uint %82
+;CHECK: 134 = OpFunctionCall %void %inst_buff_addr_stream_write_4 %uint_62 %uint_2 %80 %83
+;CHECK: OpBranch %77
+;CHECK: 77 = OpLabel
+OpBranch %13
+%13 = OpLabel
+%37 = OpLoad %int %i
+%38 = OpIAdd %int %37 %int_1
+OpStore %i %38
+OpBranch %10
+%12 = OpLabel
+OpReturn
+OpFunctionEnd)" + kSearchAndTest + kStreamWrite4Vert;
+  // clang-format on
+
+  SetTargetEnv(SPV_ENV_VULKAN_1_2);
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<InstBuffAddrCheckPass>(text, true, 7, 23);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/module_utils.h b/third_party/SPIRV-Tools/test/opt/module_utils.h
index 007f132..6859188 100644
--- a/third_party/SPIRV-Tools/test/opt/module_utils.h
+++ b/third_party/SPIRV-Tools/test/opt/module_utils.h
@@ -17,6 +17,7 @@
 
 #include <vector>
 #include "source/opt/module.h"
+#include "gtest/gtest.h"
 
 namespace spvtest {
 
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 561e817..d876c48 100644
--- a/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_cfg_test.cpp
@@ -2064,6 +2064,106 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
+TEST_F(ValidateCFG, OpSwitchTargetCannotBeOuterLoopMergeBlock) {
+  std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1
+%3 = OpTypeBool
+%4 = OpUndef %3
+%5 = OpTypeInt 32 0
+%6 = OpConstant %5 0
+
+%7 = OpFunction %1 None %2
+
+%8 = OpLabel
+OpBranch %9
+
+%9 = OpLabel
+OpLoopMerge %10 %11 None
+OpBranch %12
+
+%12 = OpLabel
+OpSelectionMerge %13 None
+OpSwitch %6 %13 0 %10 1 %14
+
+%14 = OpLabel
+OpBranch %13
+
+%13 = OpLabel
+OpBranch %11
+
+%11 = OpLabel
+OpBranch %9
+
+%10 = OpLabel
+OpReturn
+
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "Switch header '12[%12]' does not structurally dominate its case construct '10[%10]'\n"
+          "  %12 = OpLabel"));
+}
+
+TEST_F(ValidateCFG, OpSwitchTargetCannotBeOuterLoopContinueBlock) {
+  std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1
+%3 = OpTypeBool
+%4 = OpUndef %3
+%5 = OpTypeInt 32 0
+%6 = OpConstant %5 0
+
+%7 = OpFunction %1 None %2
+
+%8 = OpLabel
+OpBranch %9
+
+%9 = OpLabel
+OpLoopMerge %10 %11 None
+OpBranch %12
+
+%12 = OpLabel
+OpSelectionMerge %13 None
+OpSwitch %6 %13 0 %11 1 %14
+
+%14 = OpLabel
+OpBranch %13
+
+%13 = OpLabel
+OpBranch %11
+
+%11 = OpLabel
+OpBranch %9
+
+%10 = OpLabel
+OpReturn
+
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "Switch header '12[%12]' does not structurally dominate its case construct '11[%11]'\n"
+          "  %12 = OpLabel"));
+}
+
 TEST_F(ValidateCFG, WrongOperandList) {
   std::string text = R"(
 OpCapability Shader
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 ff62f4b..04d373a 100644
--- a/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp
@@ -4523,6 +4523,48 @@
   // #version 450
   // layout (set=0,binding=0) buffer S {
   //   uvec3 arr[2][2]; // first 3 elements are 16 bytes, last is 12
+  //   uint i;  // Can't have offset 60 = 3x16 + 12
+  // } B;
+  // void main() {}
+
+  std::string spirv = R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %1 "main"
+               OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
+               OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
+               OpMemberDecorate %_struct_4 0 Offset 0
+               OpMemberDecorate %_struct_4 1 Offset 64
+               OpDecorate %_struct_4 BufferBlock
+               OpDecorate %5 DescriptorSet 0
+               OpDecorate %5 Binding 0
+       %void = OpTypeVoid
+          %7 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+     %uint_2 = OpConstant %uint 2
+%_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
+%_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
+  %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
+%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
+          %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
+          %1 = OpFunction %void None %7
+         %12 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  CompileSuccessfully(spirv);
+  EXPECT_EQ(SPV_SUCCESS,
+            ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGoodScalar) {
+  // Original GLSL
+
+  // #version 450
+  // layout (set=0,binding=0) buffer S {
+  //   uvec3 arr[2][2]; // first 3 elements are 16 bytes, last is 12
   //   uint i;  // Can have offset 60 = 3x16 + 12
   // } B;
   // void main() {}
@@ -4554,6 +4596,7 @@
                OpFunctionEnd
   )";
 
+  options_->scalar_block_layout = true;
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_SUCCESS,
             ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
@@ -4569,7 +4612,7 @@
                OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
                OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
                OpMemberDecorate %_struct_4 0 Offset 0
-               OpMemberDecorate %_struct_4 1 Offset 56
+               OpMemberDecorate %_struct_4 1 Offset 60
                OpDecorate %_struct_4 BufferBlock
                OpDecorate %5 DescriptorSet 0
                OpDecorate %5 Binding 0
@@ -4595,8 +4638,8 @@
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Structure id 4 decorated as BufferBlock for variable "
                         "in Uniform storage class must follow standard storage "
-                        "buffer layout rules: member 1 at offset 56 overlaps "
-                        "previous member ending at offset 59"));
+                        "buffer layout rules: member 1 at offset 60 overlaps "
+                        "previous member ending at offset 63"));
 }
 
 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackGood) {
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 e685acd..8f0bcce 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
@@ -6239,6 +6239,197 @@
               HasSubstr("Name must match an entry-point for Kernel"));
 }
 
+TEST_F(ValidateClspvReflection, KernelArgumentsVersionGood) {
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%int = OpTypeInt 32 0
+%int_1 = OpConstant %int 1
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name %int_1
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateClspvReflection, KernelArgumentsVersionBad) {
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.4"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%int = OpTypeInt 32 0
+%int_1 = OpConstant %int 1
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name %int_1
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Version 4 of the Kernel instruction can only have 2 "
+                        "additional operands"));
+}
+
+TEST_F(ValidateClspvReflection, KernelNumArgumentsNotInt) {
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%float = OpTypeFloat 32
+%float_0 = OpConstant %float 0
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name %float_0
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("NumArguments must be a 32-bit unsigned integer OpConstant"));
+}
+
+TEST_F(ValidateClspvReflection, KernelNumArgumentsNotConstant) {
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%null = OpConstantNull %int
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name %null
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("NumArguments must be a 32-bit unsigned integer OpConstant"));
+}
+
+TEST_F(ValidateClspvReflection, KernelFlagsNotInt) {
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%float = OpTypeFloat 32
+%float_0 = OpConstant %float 0
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name %int_0 %float_0
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Flags must be a 32-bit unsigned integer OpConstant"));
+}
+
+TEST_F(ValidateClspvReflection, KernelFlagsNotConstant) {
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%null = OpConstantNull %int
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name %int_0 %null
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Flags must be a 32-bit unsigned integer OpConstant"));
+}
+
+TEST_F(ValidateClspvReflection, KernelAttributesNotString) {
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%float = OpTypeFloat 32
+%float_0 = OpConstant %float 0
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name %int_0 %int_0 %int_0
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Attributes must be an OpString"));
+}
+
 using ArgumentBasics =
     spvtest::ValidateBase<std::pair<std::string, std::string>>;
 
@@ -6254,7 +6445,11 @@
         std::make_pair("ArgumentSampledImage", "%int_0 %int_0"),
         std::make_pair("ArgumentStorageImage", "%int_0 %int_0"),
         std::make_pair("ArgumentSampler", "%int_0 %int_0"),
-        std::make_pair("ArgumentWorkgroup", "%int_0 %int_0")}));
+        std::make_pair("ArgumentWorkgroup", "%int_0 %int_0"),
+        std::make_pair("ArgumentPointerPushConstant", "%int_0 %int_4"),
+        std::make_pair("ArgumentPointerUniform", "%int_0 %int_0 %int_0 %int_4"),
+        std::make_pair("ArgumentStorageTexelBuffer", "%int_0 %int_0"),
+        std::make_pair("ArgumentUniformTexelBuffer", "%int_0 %int_0")}));
 
 TEST_P(ArgumentBasics, KernelNotAnExtendedInstruction) {
   const std::string ext_inst = std::get<0>(GetParam());
@@ -6262,7 +6457,7 @@
   const std::string text = R"(
 OpCapability Shader
 OpExtension "SPV_KHR_non_semantic_info"
-%ext = OpExtInstImport "NonSemantic.ClspvReflection.1"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %foo "foo"
 OpExecutionMode %foo LocalSize 1 1 1
@@ -6291,8 +6486,8 @@
   const std::string text = R"(
 OpCapability Shader
 OpExtension "SPV_KHR_non_semantic_info"
-%ext = OpExtInstImport "NonSemantic.ClspvReflection.1"
-%ext2 = OpExtInstImport "NonSemantic.ClspvReflection.1"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+%ext2 = OpExtInstImport "NonSemantic.ClspvReflection.5"
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %foo "foo"
 OpExecutionMode %foo LocalSize 1 1 1
@@ -6323,7 +6518,7 @@
   const std::string text = R"(
 OpCapability Shader
 OpExtension "SPV_KHR_non_semantic_info"
-%ext = OpExtInstImport "NonSemantic.ClspvReflection.1"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %foo "foo"
 OpExecutionMode %foo LocalSize 1 1 1
@@ -6353,7 +6548,7 @@
   const std::string text = R"(
 OpCapability Shader
 OpExtension "SPV_KHR_non_semantic_info"
-%ext = OpExtInstImport "NonSemantic.ClspvReflection.1"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %foo "foo"
 OpExecutionMode %foo LocalSize 1 1 1
@@ -6383,7 +6578,7 @@
   const std::string text = R"(
 OpCapability Shader
 OpExtension "SPV_KHR_non_semantic_info"
-%ext = OpExtInstImport "NonSemantic.ClspvReflection.1"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %foo "foo"
 OpExecutionMode %foo LocalSize 1 1 1
@@ -6414,8 +6609,8 @@
   const std::string text = R"(
 OpCapability Shader
 OpExtension "SPV_KHR_non_semantic_info"
-%ext = OpExtInstImport "NonSemantic.ClspvReflection.1"
-%ext2 = OpExtInstImport "NonSemantic.ClspvReflection.1"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+%ext2 = OpExtInstImport "NonSemantic.ClspvReflection.5"
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %foo "foo"
 OpExecutionMode %foo LocalSize 1 1 1
@@ -6659,7 +6854,269 @@
         std::make_pair(
             "PropertyRequiredWorkgroupSize %decl %int_1 %int_1 %float_0", "Z"),
         std::make_pair(
-            "PropertyRequiredWorkgroupSize %decl %int_1 %int_1 %null", "Z")}));
+            "PropertyRequiredWorkgroupSize %decl %int_1 %int_1 %null", "Z"),
+        std::make_pair("SpecConstantSubgroupMaxSize %float_0", "Size"),
+        std::make_pair("SpecConstantSubgroupMaxSize %null", "Size"),
+        std::make_pair(
+            "ArgumentPointerPushConstant %decl %float_0 %int_0 %int_0",
+            "Ordinal"),
+        std::make_pair("ArgumentPointerPushConstant %decl %null %int_0 %int_0",
+                       "Ordinal"),
+        std::make_pair(
+            "ArgumentPointerPushConstant %decl %int_0 %float_0 %int_0",
+            "Offset"),
+        std::make_pair("ArgumentPointerPushConstant %decl %int_0 %null %int_0",
+                       "Offset"),
+        std::make_pair(
+            "ArgumentPointerPushConstant %decl %int_0 %int_0 %float_0", "Size"),
+        std::make_pair("ArgumentPointerPushConstant %decl %int_0 %int_0 %null",
+                       "Size"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %float_0 %int_0 %int_0 %int_0 %int_4",
+            "Ordinal"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %null %int_0 %int_0 %int_0 %int_4",
+            "Ordinal"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %int_0 %float_0 %int_0 %int_0 %int_4",
+            "DescriptorSet"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %int_0 %null %int_0 %int_0 %int_4",
+            "DescriptorSet"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %int_0 %int_0 %float_0 %int_0 %int_4",
+            "Binding"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %int_0 %int_0 %null %int_0 %int_4",
+            "Binding"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %int_0 %int_0 %int_0 %float_0 %int_4",
+            "Offset"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %int_0 %int_0 %int_0 %null %int_4",
+            "Offset"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %int_0 %int_0 %int_0 %int_0 %float_0",
+            "Size"),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %int_0 %int_0 %int_0 %int_0 %null",
+            "Size"),
+        std::make_pair(
+            "ProgramScopeVariablesStorageBuffer %float_0 %int_0 %data",
+            "DescriptorSet"),
+        std::make_pair("ProgramScopeVariablesStorageBuffer %null %int_0 %data",
+                       "DescriptorSet"),
+        std::make_pair(
+            "ProgramScopeVariablesStorageBuffer %int_0 %float_0 %data",
+            "Binding"),
+        std::make_pair("ProgramScopeVariablesStorageBuffer %int_0 %null %data",
+                       "Binding"),
+        std::make_pair(
+            "ProgramScopeVariablePointerRelocation %float_0 %int_0 %int_4",
+            "ObjectOffset"),
+        std::make_pair(
+            "ProgramScopeVariablePointerRelocation %null %int_0 %int_4",
+            "ObjectOffset"),
+        std::make_pair(
+            "ProgramScopeVariablePointerRelocation %int_0 %float_0 %int_4",
+            "PointerOffset"),
+        std::make_pair(
+            "ProgramScopeVariablePointerRelocation %int_0 %null %int_4",
+            "PointerOffset"),
+        std::make_pair(
+            "ProgramScopeVariablePointerRelocation %int_0 %int_0 %float_0",
+            "PointerSize"),
+        std::make_pair(
+            "ProgramScopeVariablePointerRelocation %int_0 %int_0 %null",
+            "PointerSize"),
+        std::make_pair("ImageArgumentInfoChannelOrderPushConstant %decl "
+                       "%float_0 %int_0 %int_4",
+                       "Ordinal"),
+        std::make_pair("ImageArgumentInfoChannelOrderPushConstant %decl %null "
+                       "%int_0 %int_4",
+                       "Ordinal"),
+        std::make_pair("ImageArgumentInfoChannelOrderPushConstant %decl %int_0 "
+                       "%float_0 %int_4",
+                       "Offset"),
+        std::make_pair("ImageArgumentInfoChannelOrderPushConstant %decl %int_0 "
+                       "%null %int_4",
+                       "Offset"),
+        std::make_pair("ImageArgumentInfoChannelOrderPushConstant %decl %int_0 "
+                       "%int_0 %float_0",
+                       "Size"),
+        std::make_pair("ImageArgumentInfoChannelOrderPushConstant %decl %int_0 "
+                       "%int_0 %null",
+                       "Size"),
+        std::make_pair("ImageArgumentInfoChannelDataTypePushConstant %decl "
+                       "%float_0 %int_0 %int_4",
+                       "Ordinal"),
+        std::make_pair("ImageArgumentInfoChannelDataTypePushConstant %decl "
+                       "%null %int_0 %int_4",
+                       "Ordinal"),
+        std::make_pair("ImageArgumentInfoChannelDataTypePushConstant %decl "
+                       "%int_0 %float_0 %int_4",
+                       "Offset"),
+        std::make_pair("ImageArgumentInfoChannelDataTypePushConstant %decl "
+                       "%int_0 %null %int_4",
+                       "Offset"),
+        std::make_pair("ImageArgumentInfoChannelDataTypePushConstant %decl "
+                       "%int_0 %int_0 %float_0",
+                       "Size"),
+        std::make_pair("ImageArgumentInfoChannelDataTypePushConstant %decl "
+                       "%int_0 %int_0 %null",
+                       "Size"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %float_0 "
+                       "%int_0 %int_0 %int_0 %int_4",
+                       "Ordinal"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %null "
+                       "%int_0 %int_0 %int_0 %int_4",
+                       "Ordinal"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %int_0 "
+                       "%float_0 %int_0 %int_0 %int_4",
+                       "DescriptorSet"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %int_0 "
+                       "%null %int_0 %int_0 %int_4",
+                       "DescriptorSet"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %int_0 "
+                       "%int_0 %float_0 %int_0 %int_4",
+                       "Binding"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %int_0 "
+                       "%int_0 %null %int_0 %int_4",
+                       "Binding"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %int_0 "
+                       "%int_0 %int_0 %float_0 %int_4",
+                       "Offset"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %int_0 "
+                       "%int_0 %int_0 %null %int_4",
+                       "Offset"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %int_0 "
+                       "%int_0 %int_0 %int_0 %float_0",
+                       "Size"),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %int_0 "
+                       "%int_0 %int_0 %int_0 %null",
+                       "Size"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %float_0 "
+                       "%int_0 %int_0 %int_0 %int_4",
+                       "Ordinal"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %null "
+                       "%int_0 %int_0 %int_0 %int_4",
+                       "Ordinal"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %int_0 "
+                       "%float_0 %int_0 %int_0 %int_4",
+                       "DescriptorSet"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %int_0 "
+                       "%null %int_0 %int_0 %int_4",
+                       "DescriptorSet"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %int_0 "
+                       "%int_0 %float_0 %int_0 %int_4",
+                       "Binding"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %int_0 "
+                       "%int_0 %null %int_0 %int_4",
+                       "Binding"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %int_0 "
+                       "%int_0 %int_0 %float_0 %int_4",
+                       "Offset"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %int_0 "
+                       "%int_0 %int_0 %null %int_4",
+                       "Offset"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %int_0 "
+                       "%int_0 %int_0 %int_0 %float_0",
+                       "Size"),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %int_0 "
+                       "%int_0 %int_0 %int_0 %null",
+                       "Size"),
+        std::make_pair(
+            "ArgumentStorageTexelBuffer %decl %float_0 %int_0 %int_0",
+            "Ordinal"),
+        std::make_pair("ArgumentStorageTexelBuffer %decl %null %int_0 %int_0",
+                       "Ordinal"),
+        std::make_pair(
+            "ArgumentStorageTexelBuffer %decl %int_0 %float_0 %int_0",
+            "DescriptorSet"),
+        std::make_pair("ArgumentStorageTexelBuffer %decl %int_0 %null %int_0",
+                       "DescriptorSet"),
+        std::make_pair(
+            "ArgumentStorageTexelBuffer %decl %int_0 %int_0 %float_0",
+            "Binding"),
+        std::make_pair("ArgumentStorageTexelBuffer %decl %int_0 %int_0 %null",
+                       "Binding"),
+        std::make_pair(
+            "ArgumentUniformTexelBuffer %decl %float_0 %int_0 %int_0",
+            "Ordinal"),
+        std::make_pair("ArgumentUniformTexelBuffer %decl %null %int_0 %int_0",
+                       "Ordinal"),
+        std::make_pair(
+            "ArgumentUniformTexelBuffer %decl %int_0 %float_0 %int_0",
+            "DescriptorSet"),
+        std::make_pair("ArgumentUniformTexelBuffer %decl %int_0 %null %int_0",
+                       "DescriptorSet"),
+        std::make_pair(
+            "ArgumentUniformTexelBuffer %decl %int_0 %int_0 %float_0",
+            "Binding"),
+        std::make_pair("ArgumentUniformTexelBuffer %decl %int_0 %int_0 %null",
+                       "Binding"),
+        std::make_pair("ConstantDataPointerPushConstant %float_0 %int_4 %data",
+                       "Offset"),
+        std::make_pair("ConstantDataPointerPushConstant %null %int_4 %data",
+                       "Offset"),
+        std::make_pair("ConstantDataPointerPushConstant %int_0 %float_0 %data",
+                       "Size"),
+        std::make_pair("ConstantDataPointerPushConstant %int_0 %null %data",
+                       "Size"),
+        std::make_pair(
+            "ProgramScopeVariablePointerPushConstant %float_0 %int_4 %data",
+            "Offset"),
+        std::make_pair(
+            "ProgramScopeVariablePointerPushConstant %null %int_4 %data",
+            "Offset"),
+        std::make_pair(
+            "ProgramScopeVariablePointerPushConstant %int_0 %float_0 %data",
+            "Size"),
+        std::make_pair(
+            "ProgramScopeVariablePointerPushConstant %int_0 %null %data",
+            "Size"),
+        std::make_pair("PrintfInfo %float_0 %data %int_0 %int_0 %int_0",
+                       "PrintfID"),
+        std::make_pair("PrintfInfo %null %data %int_0 %int_0 %int_0",
+                       "PrintfID"),
+        std::make_pair("PrintfInfo %int_0 %data %float_0 %int_0 %int_0",
+                       "ArgumentSizes"),
+        std::make_pair("PrintfInfo %int_0 %data %null %int_0 %int_0",
+                       "ArgumentSizes"),
+        std::make_pair("PrintfInfo %int_0 %data %int_0 %float_0 %int_0",
+                       "ArgumentSizes"),
+        std::make_pair("PrintfInfo %int_0 %data %int_0 %null %int_0",
+                       "ArgumentSizes"),
+        std::make_pair("PrintfInfo %int_0 %data %int_0 %int_0 %null",
+                       "ArgumentSizes"),
+        std::make_pair("PrintfInfo %int_0 %data %int_0 %int_0 %float_0",
+                       "ArgumentSizes"),
+        std::make_pair("PrintfInfo %int_0 %data %int_0 %float_0",
+                       "ArgumentSizes"),
+        std::make_pair("PrintfInfo %int_0 %data %int_0 %null", "ArgumentSizes"),
+        std::make_pair("PrintfBufferStorageBuffer %float_0 %int_0 %int_4",
+                       "DescriptorSet"),
+        std::make_pair("PrintfBufferStorageBuffer %null %int_0 %int_4",
+                       "DescriptorSet"),
+        std::make_pair("PrintfBufferStorageBuffer %int_0 %float_0 %int_4",
+                       "Binding"),
+        std::make_pair("PrintfBufferStorageBuffer %int_0 %null %int_4",
+                       "Binding"),
+        std::make_pair("PrintfBufferStorageBuffer %int_0 %int_0 %float_0",
+                       "Size"),
+        std::make_pair("PrintfBufferStorageBuffer %int_0 %int_0 %null", "Size"),
+        std::make_pair("PrintfBufferPointerPushConstant %float_0 %int_0 %int_4",
+                       "Offset"),
+        std::make_pair("PrintfBufferPointerPushConstant %null %int_0 %int_4",
+                       "Offset"),
+        std::make_pair("PrintfBufferPointerPushConstant %int_0 %float_0 %int_4",
+                       "Size"),
+        std::make_pair("PrintfBufferPointerPushConstant %int_0 %null %int_4",
+                       "Size"),
+        std::make_pair("PrintfBufferPointerPushConstant %int_0 %int_0 %float_0",
+                       "BufferSize"),
+        std::make_pair("PrintfBufferPointerPushConstant %int_0 %int_0 %null",
+                       "BufferSize")}));
 
 TEST_P(Uint32Constant, Invalid) {
   const std::string ext_inst = std::get<0>(GetParam());
@@ -6667,7 +7124,7 @@
   const std::string text = R"(
 OpCapability Shader
 OpExtension "SPV_KHR_non_semantic_info"
-%ext = OpExtInstImport "NonSemantic.ClspvReflection.1"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %foo "foo"
 OpExecutionMode %foo LocalSize 1 1 1
@@ -6705,7 +7162,15 @@
     ::testing::ValuesIn(std::vector<std::pair<std::string, std::string>>{
         std::make_pair("ConstantDataStorageBuffer %int_0 %int_0 %int_0",
                        "Data"),
-        std::make_pair("ConstantDataUniform %int_0 %int_0 %int_0", "Data")}));
+        std::make_pair("ConstantDataUniform %int_0 %int_0 %int_0", "Data"),
+        std::make_pair(
+            "ProgramScopeVariablesStorageBuffer %int_0 %int_0 %int_0", "Data"),
+        std::make_pair("ConstantDataPointerPushConstant %int_0 %int_0 %int_0",
+                       "Data"),
+        std::make_pair(
+            "ProgramScopeVariablePointerPushConstant %int_0 %int_0 %int_0",
+            "Data"),
+        std::make_pair("PrintfInfo %int_0 %int_0", "FormatString")}));
 
 TEST_P(StringOperand, Invalid) {
   const std::string ext_inst = std::get<0>(GetParam());
@@ -6713,6 +7178,106 @@
   const std::string text = R"(
 OpCapability Shader
 OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%data = OpString "1234"
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%null = OpConstantNull %int
+%float = OpTypeFloat 32
+%float_0 = OpConstant %float 0
+%void_fn = OpTypeFunction %void
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name
+%inst = OpExtInst %void %ext )" +
+                           ext_inst;
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(), HasSubstr(name + " must be an OpString"));
+}
+
+using VersionCheck = spvtest::ValidateBase<std::pair<std::string, uint32_t>>;
+
+INSTANTIATE_TEST_SUITE_P(
+    ValidateClspvReflectionVersionCheck, VersionCheck,
+    ::testing::ValuesIn(std::vector<std::pair<std::string, uint32_t>>{
+        std::make_pair("ArgumentStorageBuffer %decl %int_0 %int_0 %int_0", 1),
+        std::make_pair("ArgumentUniform %decl %int_0 %int_0 %int_0", 1),
+        std::make_pair(
+            "ArgumentPodStorageBuffer %decl %int_0 %int_0 %int_0 %int_0 %int_0",
+            1),
+        std::make_pair(
+            "ArgumentPodUniform %decl %int_0 %int_0 %int_0 %int_0 %int_0", 1),
+        std::make_pair("ArgumentPodPushConstant %decl %int_0 %int_0 %int_0", 1),
+        std::make_pair("ArgumentSampledImage %decl %int_0 %int_0 %int_0", 1),
+        std::make_pair("ArgumentStorageImage %decl %int_0 %int_0 %int_0", 1),
+        std::make_pair("ArgumentSampler %decl %int_0 %int_0 %int_0", 1),
+        std::make_pair("ArgumentWorkgroup %decl %int_0 %int_0 %int_0", 1),
+        std::make_pair("SpecConstantWorkgroupSize %int_0 %int_0 %int_0", 1),
+        std::make_pair("SpecConstantGlobalOffset %int_0 %int_0 %int_0", 1),
+        std::make_pair("SpecConstantWorkDim %int_0", 1),
+        std::make_pair("PushConstantGlobalOffset %int_0 %int_0", 1),
+        std::make_pair("PushConstantEnqueuedLocalSize %int_0 %int_0", 1),
+        std::make_pair("PushConstantGlobalSize %int_0 %int_0", 1),
+        std::make_pair("PushConstantRegionOffset %int_0 %int_0", 1),
+        std::make_pair("PushConstantNumWorkgroups %int_0 %int_0", 1),
+        std::make_pair("PushConstantRegionGroupOffset %int_0 %int_0", 1),
+        std::make_pair("ConstantDataStorageBuffer %int_0 %int_0 %data", 1),
+        std::make_pair("ConstantDataUniform %int_0 %int_0 %data", 1),
+        std::make_pair("LiteralSampler %int_0 %int_0 %int_0", 1),
+        std::make_pair(
+            "PropertyRequiredWorkgroupSize %decl %int_0 %int_0 %int_0", 1),
+        std::make_pair("SpecConstantSubgroupMaxSize %int_0", 2),
+        std::make_pair("ArgumentPointerPushConstant %decl %int_0 %int_0 %int_0",
+                       3),
+        std::make_pair(
+            "ArgumentPointerUniform %decl %int_0 %int_0 %int_0 %int_0 %int_0",
+            3),
+        std::make_pair("ProgramScopeVariablesStorageBuffer %int_0 %int_0 %data",
+                       3),
+        std::make_pair(
+            "ProgramScopeVariablePointerRelocation %int_0 %int_0 %int_0", 3),
+        std::make_pair("ImageArgumentInfoChannelOrderPushConstant %decl %int_0 "
+                       "%int_0 %int_0",
+                       3),
+        std::make_pair("ImageArgumentInfoChannelDataTypePushConstant %decl "
+                       "%int_0 %int_0 %int_0",
+                       3),
+        std::make_pair("ImageArgumentInfoChannelOrderUniform %decl %int_0 "
+                       "%int_0 %int_0 %int_0 %int_0",
+                       3),
+        std::make_pair("ImageArgumentInfoChannelDataTypeUniform %decl %int_0 "
+                       "%int_0 %int_0 %int_0 %int_0",
+                       3),
+        std::make_pair("ArgumentStorageTexelBuffer %decl %int_0 %int_0 %int_0",
+                       4),
+        std::make_pair("ArgumentUniformTexelBuffer %decl %int_0 %int_0 %int_0",
+                       4),
+        std::make_pair("ConstantDataPointerPushConstant %int_0 %int_0 %data",
+                       5),
+        std::make_pair(
+            "ProgramScopeVariablePointerPushConstant %int_0 %int_0 %data", 5),
+        std::make_pair("PrintfInfo %int_0 %data", 5),
+        std::make_pair("PrintfBufferStorageBuffer %int_0 %int_0 %int_0", 5),
+        std::make_pair("PrintfBufferPointerPushConstant %int_0 %int_0 %int_0",
+                       5)}));
+
+TEST_P(VersionCheck, V1) {
+  const std::string ext_inst = std::get<0>(GetParam());
+  const uint32_t version = std::get<1>(GetParam());
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
 %ext = OpExtInstImport "NonSemantic.ClspvReflection.1"
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %foo "foo"
@@ -6737,8 +7302,174 @@
                            ext_inst;
 
   CompileSuccessfully(text);
-  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr(name + " must be an OpString"));
+  if (version <= 1) {
+    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+  } else {
+    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+    EXPECT_THAT(getDiagnosticString(),
+                HasSubstr("requires version " + std::to_string(version) +
+                          ", but parsed version is 1"));
+  }
+}
+
+TEST_P(VersionCheck, V2) {
+  const std::string ext_inst = std::get<0>(GetParam());
+  const uint32_t version = std::get<1>(GetParam());
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.2"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%data = OpString "1234"
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%null = OpConstantNull %int
+%float = OpTypeFloat 32
+%float_0 = OpConstant %float 0
+%void_fn = OpTypeFunction %void
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name
+%inst = OpExtInst %void %ext )" +
+                           ext_inst;
+
+  CompileSuccessfully(text);
+  if (version <= 2) {
+    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+  } else {
+    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+    EXPECT_THAT(getDiagnosticString(),
+                HasSubstr("requires version " + std::to_string(version) +
+                          ", but parsed version is 2"));
+  }
+}
+
+TEST_P(VersionCheck, V3) {
+  const std::string ext_inst = std::get<0>(GetParam());
+  const uint32_t version = std::get<1>(GetParam());
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.3"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%data = OpString "1234"
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%null = OpConstantNull %int
+%float = OpTypeFloat 32
+%float_0 = OpConstant %float 0
+%void_fn = OpTypeFunction %void
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name
+%inst = OpExtInst %void %ext )" +
+                           ext_inst;
+
+  CompileSuccessfully(text);
+  if (version <= 3) {
+    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+  } else {
+    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+    EXPECT_THAT(getDiagnosticString(),
+                HasSubstr("requires version " + std::to_string(version) +
+                          ", but parsed version is 3"));
+  }
+}
+
+TEST_P(VersionCheck, V4) {
+  const std::string ext_inst = std::get<0>(GetParam());
+  const uint32_t version = std::get<1>(GetParam());
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.4"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%data = OpString "1234"
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%null = OpConstantNull %int
+%float = OpTypeFloat 32
+%float_0 = OpConstant %float 0
+%void_fn = OpTypeFunction %void
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name
+%inst = OpExtInst %void %ext )" +
+                           ext_inst;
+
+  CompileSuccessfully(text);
+  if (version <= 4) {
+    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+  } else {
+    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+    EXPECT_THAT(getDiagnosticString(),
+                HasSubstr("requires version " + std::to_string(version) +
+                          ", but parsed version is 4"));
+  }
+}
+
+TEST_P(VersionCheck, V5) {
+  const std::string ext_inst = std::get<0>(GetParam());
+  const uint32_t version = std::get<1>(GetParam());
+  const std::string text = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_non_semantic_info"
+%ext = OpExtInstImport "NonSemantic.ClspvReflection.5"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %foo "foo"
+OpExecutionMode %foo LocalSize 1 1 1
+%foo_name = OpString "foo"
+%data = OpString "1234"
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%int_4 = OpConstant %int 4
+%null = OpConstantNull %int
+%float = OpTypeFloat 32
+%float_0 = OpConstant %float 0
+%void_fn = OpTypeFunction %void
+%foo = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+%decl = OpExtInst %void %ext Kernel %foo %foo_name
+%inst = OpExtInst %void %ext )" +
+                           ext_inst;
+
+  CompileSuccessfully(text);
+  if (version <= 5) {
+    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+  } else {
+    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+    EXPECT_THAT(getDiagnosticString(),
+                HasSubstr("requires version " + std::to_string(version) +
+                          ", but parsed version is 1"));
+  }
 }
 
 }  // namespace
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 a457980..3666f38 100644
--- a/third_party/SPIRV-Tools/test/val/val_id_test.cpp
+++ b/third_party/SPIRV-Tools/test/val/val_id_test.cpp
@@ -203,11 +203,12 @@
     // 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;
     }
+
+    // Copy up to the first quote
+    result.write(msg + next, open_quote - next);
     // Handle apostrophes
     if (!isdigit(message[open_quote + 1])) {
       result << '\'';
diff --git a/third_party/SPIRV-Tools/tools/CMakeLists.txt b/third_party/SPIRV-Tools/tools/CMakeLists.txt
index 86d0bc4..d272b08 100644
--- a/third_party/SPIRV-Tools/tools/CMakeLists.txt
+++ b/third_party/SPIRV-Tools/tools/CMakeLists.txt
@@ -69,6 +69,19 @@
   endif(SPIRV_BUILD_FUZZER)
 
   if(ENABLE_SPIRV_TOOLS_INSTALL)
-    install(TARGETS ${SPIRV_INSTALL_TARGETS} DESTINATION ${CMAKE_INSTALL_BINDIR})
+    install(TARGETS ${SPIRV_INSTALL_TARGETS} EXPORT SPIRV-Tools-toolsTargets)
+    export(EXPORT SPIRV-Tools-toolsTargets FILE SPIRV-Tools-toolsTargets.cmake)
+
+    spvtools_config_package_dir(SPIRV-Tools-tools PACKAGE_DIR)
+    install(EXPORT SPIRV-Tools-toolsTargets FILE SPIRV-Tools-toolsTargets.cmake
+            DESTINATION ${PACKAGE_DIR})
+
+    file(WRITE ${CMAKE_BINARY_DIR}/SPIRV-Tools-toolsConfig.cmake
+      "include(CMakeFindDependencyMacro)\n"
+      "find_dependency(${SPIRV_TOOLS})\n"
+      "include(\${CMAKE_CURRENT_LIST_DIR}/SPIRV-Tools-toolsTargets.cmake)\n"
+      )
+
+    install(FILES ${CMAKE_BINARY_DIR}/SPIRV-Tools-toolsConfig.cmake DESTINATION ${PACKAGE_DIR})
   endif(ENABLE_SPIRV_TOOLS_INSTALL)
 endif()
diff --git a/third_party/SPIRV-Tools/utils/check_code_format.sh b/third_party/SPIRV-Tools/utils/check_code_format.sh
index 7994740..da5e019 100755
--- a/third_party/SPIRV-Tools/utils/check_code_format.sh
+++ b/third_party/SPIRV-Tools/utils/check_code_format.sh
@@ -18,7 +18,7 @@
 #
 # This script assumes to be invoked at the project root directory.
 
-BASE_BRANCH=${1:-master}
+BASE_BRANCH=${1:-main}
 
 FILES_TO_CHECK=$(git diff --name-only ${BASE_BRANCH} | grep -E ".*\.(cpp|cc|c\+\+|cxx|c|h|hpp)$")
 
diff --git a/third_party/SPIRV-Tools/utils/git-sync-deps b/third_party/SPIRV-Tools/utils/git-sync-deps
index 7a7e606..6549afb 100755
--- a/third_party/SPIRV-Tools/utils/git-sync-deps
+++ b/third_party/SPIRV-Tools/utils/git-sync-deps
@@ -28,10 +28,9 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 """Parse a DEPS file and git checkout all of the dependencies.
+"""
 
-Args:
-  An optional list of deps_os values.
-
+EXTRA_HELP = """
 Environment Variables:
   GIT_EXECUTABLE: path to "git" binary; if unset, will look for one of
   ['git', 'git.exe', 'git.bat'] in your default path.
@@ -52,6 +51,7 @@
 """
 
 
+import argparse
 import os
 import re
 import subprocess
@@ -59,12 +59,14 @@
 import threading
 from builtins import bytes
 
-
 def git_executable():
   """Find the git executable.
 
   Returns:
-      A string suitable for passing to subprocess functions, or None.
+      A triple:
+        A string suitable for passing to subprocess functions, or None.
+        The major version number
+        The minor version number
   """
   envgit = os.environ.get('GIT_EXECUTABLE')
   searchlist = ['git', 'git.exe', 'git.bat']
@@ -72,30 +74,36 @@
     searchlist.insert(0, envgit)
   with open(os.devnull, 'w') as devnull:
     for git in searchlist:
+      major=None
+      minor=None
       try:
-        subprocess.call([git, '--version'], stdout=devnull)
+        version_info = subprocess.check_output([git, '--version']).decode('utf-8')
+        match = re.search("^git version (\d+)\.(\d+)",version_info)
+        print("Using {}".format(version_info))
+        if match:
+          major = int(match.group(1))
+          minor = int(match.group(2))
+        else:
+          continue
       except (OSError,):
         continue
-      return git
-  return None
+      return (git,major,minor)
+  return (None,0,0)
 
 
 DEFAULT_DEPS_PATH = os.path.normpath(
   os.path.join(os.path.dirname(__file__), os.pardir, 'DEPS'))
 
+def get_deps_os_str(deps_file):
+  parsed_deps = parse_file_to_dict(deps_file)
+  parts = []
+  if 'deps_os' in parsed_deps:
+    for deps_os in parsed_deps['deps_os']:
+      parts.append(' [{}]]'.format(deps_os))
+  return "\n".join(parts)
 
-def usage(deps_file_path = None):
-  sys.stderr.write(
-    'Usage: run to grab dependencies, with optional platform support:\n')
-  sys.stderr.write('  %s %s' % (sys.executable, __file__))
-  if deps_file_path:
-    parsed_deps = parse_file_to_dict(deps_file_path)
-    if 'deps_os' in parsed_deps:
-      for deps_os in parsed_deps['deps_os']:
-        sys.stderr.write(' [%s]' % deps_os)
-  sys.stderr.write('\n\n')
-  sys.stderr.write(__doc__)
-
+def looks_like_raw_commit(commit):
+  return re.match('^[a-f0-9]{40}$', commit) is not None
 
 def git_repository_sync_is_disabled(git, directory):
   try:
@@ -125,14 +133,14 @@
 
 def status(directory, checkoutable):
   def truncate(s, length):
-    return s if len(s) <= length else s[:(length - 3)] + '...'
+    return s if len(s) <= length else '...' + s[-(length - 3):]
   dlen = 36
   directory = truncate(directory, dlen)
   checkoutable = truncate(checkoutable, 40)
   sys.stdout.write('%-*s @ %s\n' % (dlen, directory, checkoutable))
 
 
-def git_checkout_to_directory(git, repo, checkoutable, directory, verbose):
+def git_checkout_to_directory(git, repo, checkoutable, directory, verbose, treeless):
   """Checkout (and clone if needed) a Git repository.
 
   Args:
@@ -147,13 +155,22 @@
     directory (string) the path into which the repository
               should be checked out.
 
-    verbose (boolean)
+    verbose (boolean): emit status info to stdout
+
+    treeless (boolean): when true, clone without any trees.
 
   Raises an exception if any calls to git fail.
   """
   if not os.path.isdir(directory):
+    # Use blobless or treeless checkouts for faster downloads.
+    # This defers some work to checkout time.
+    # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
+    filter = ['--filter=tree:0'] if treeless else ['--filter=blob:none']
+    # If the thing to check out looks like a tag (and not like a commit),
+    # then limit the checkout to that branch.
+    branch = [] if looks_like_raw_commit(checkoutable) else ['--branch={}'.format(checkoutable)]
     subprocess.check_call(
-      [git, 'clone', '--quiet', repo, directory])
+        [git, 'clone', '--quiet', '--single-branch'] + filter + branch + [repo, directory])
 
   if not is_git_toplevel(git, directory):
     # if the directory exists, but isn't a git repo, you will modify
@@ -200,7 +217,7 @@
   return dictionary
 
 
-def git_sync_deps(deps_file_path, command_line_os_requests, verbose):
+def git_sync_deps(deps_file_path, command_line_os_requests, verbose, treeless):
   """Grab dependencies, with optional platform support.
 
   Args:
@@ -210,11 +227,20 @@
         List of strings that should each be a key in the deps_os
         dictionary in the DEPS file.
 
+    verbose (boolean): emit status info to stdout
+
+    treeless (boolean): when true, clone as treeless instead of blobless
+
   Raises git Exceptions.
   """
-  git = git_executable()
+  (git,git_major,git_minor) = git_executable()
   assert git
 
+  # --filter=tree:0 is available in git 2.20 and later
+  if (git_major,git_minor) < (2,20):
+    print("disabling --treeless: git is older than v2.20")
+    treeless = False
+
   deps_file_directory = os.path.dirname(deps_file_path)
   deps_file = parse_file_to_dict(deps_file_path)
   dependencies = deps_file['deps'].copy()
@@ -241,7 +267,7 @@
     relative_directory = os.path.join(deps_file_directory, directory)
 
     list_of_arg_lists.append(
-      (git, repo, checkoutable, relative_directory, verbose))
+      (git, repo, checkoutable, relative_directory, verbose, treeless))
 
   multithread(git_checkout_to_directory, list_of_arg_lists)
 
@@ -264,17 +290,47 @@
 
 
 def main(argv):
-  deps_file_path = os.environ.get('GIT_SYNC_DEPS_PATH', DEFAULT_DEPS_PATH)
-  verbose = not bool(os.environ.get('GIT_SYNC_DEPS_QUIET', False))
+  argparser = argparse.ArgumentParser(
+          prog = "git-sync-deps",
+          description = "Checkout git-based dependencies as specified by the DEPS file",
+          add_help=False # Because we want to print deps_os with -h option
+          )
+  argparser.add_argument("--help", "-h",
+                         action='store_true',
+                         help="show this help message and exit")
+  argparser.add_argument("--deps",
+                         default = os.environ.get('GIT_SYNC_DEPS_PATH', DEFAULT_DEPS_PATH),
+                         help="location of the the DEPS file")
+  argparser.add_argument("--verbose",
+                         default=not bool(os.environ.get('GIT_SYNC_DEPS_QUIET', False)),
+                         action='store_true',
+                         help="be verbose: print status messages")
+  argparser.add_argument("--treeless",
+                         default=False,
+                         action='store_true',
+                         help="""
+    Clone repos without trees (--filter=tree:0).
+    This is the fastest option for a build machine,
+    when you only need a single commit.
+    Defers getting objects until checking out a commit.
 
-  if '--help' in argv or '-h' in argv:
-    usage(deps_file_path)
-    return 1
+    The default is to clone with trees but without blobs.
 
-  git_sync_deps(deps_file_path, argv, verbose)
-  # subprocess.check_call(
-  #     [sys.executable,
-  #      os.path.join(os.path.dirname(deps_file_path), 'bin', 'fetch-gn')])
+    Only takes effect if using git 2.20 or later.
+
+    See https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
+                              """)
+  argparser.add_argument("os_requests",nargs="*",
+                         help="OS requests, as keys in the deps_os dictionariy in the DEPS file")
+
+  args = argparser.parse_args()
+  if args.help:
+    print(argparser.format_help())
+    print(EXTRA_HELP)
+    print(get_deps_os_str(args.deps))
+    return 0
+
+  git_sync_deps(args.deps, args.os_requests, args.verbose, args.treeless)
   return 0
 
 
diff --git a/third_party/SPIRV-Tools/utils/roll_deps.sh b/third_party/SPIRV-Tools/utils/roll_deps.sh
index 20c061f..bf6d693 100755
--- a/third_party/SPIRV-Tools/utils/roll_deps.sh
+++ b/third_party/SPIRV-Tools/utils/roll_deps.sh
@@ -20,14 +20,23 @@
 
 set -eo pipefail
 
-effcee_dir="external/effcee/"
-effcee_trunk="origin/main"
-googletest_dir="external/googletest/"
-googletest_trunk="origin/main"
-re2_dir="external/re2/"
-re2_trunk="origin/main"
-spirv_headers_dir="external/spirv-headers/"
-spirv_headers_trunk="origin/master"
+function ExitIfIsInterestingError() {
+  local return_code=$1
+  if [[ ${return_code} -ne 0 && ${return_code} -ne 2 ]]; then
+    exit ${return_code}
+  fi
+  return 0
+}
+
+
+# We are not rolling google test for now. The latest version requires C++14.
+dependencies=("external/effcee/"
+#             "external/googletest/")
+              "external/re2/"
+              "external/spirv-headers/")
+
+
+branch="origin/main"
 
 # This script assumes it's parent directory is the repo root.
 repo_path=$(dirname "$0")/..
@@ -44,10 +53,9 @@
 old_head=$(git rev-parse HEAD)
 
 set +e
-roll-dep --ignore-dirty-tree --roll-to="${effcee_trunk}" "${effcee_dir}"
-roll-dep --ignore-dirty-tree --roll-to="${googletest_trunk}" "${googletest_dir}"
-roll-dep --ignore-dirty-tree --roll-to="${re2_trunk}" "${re2_dir}"
-roll-dep --ignore-dirty-tree --roll-to="${spirv_headers_trunk}" "${spirv_headers_dir}"
 
-git rebase --interactive "${old_head}"
-
+for dep in ${dependencies[@]}; do
+  echo "Rolling $dep"
+  roll-dep --ignore-dirty-tree --roll-to="${branch}" "${dep}"
+  ExitIfIsInterestingError $?
+done
diff --git a/third_party/SPIRV-Tools/utils/update_build_version.py b/third_party/SPIRV-Tools/utils/update_build_version.py
index 2a1ca60..b1c7b21 100755
--- a/third_party/SPIRV-Tools/utils/update_build_version.py
+++ b/third_party/SPIRV-Tools/utils/update_build_version.py
@@ -35,9 +35,13 @@
 import os.path
 import re
 import subprocess
+import logging
 import sys
 import time
 
+# Format of the output generated by this script. Example:
+# "v2023.1", "SPIRV-Tools v2023.1 0fc5526f2b01a0cc89192c10cf8bef77f1007a62, 2023-01-18T14:51:49"
+OUTPUT_FORMAT = '"{version_tag}", "SPIRV-Tools {version_tag} {description}"\n'
 
 def mkdir_p(directory):
     """Make the directory, and all its ancestors as required.  Any of the
@@ -55,7 +59,6 @@
         else:
             raise
 
-
 def command_output(cmd, directory):
     """Runs a command in a directory and returns its standard output stream.
 
@@ -63,23 +66,29 @@
 
     Raises a RuntimeError if the command fails to launch or otherwise fails.
     """
-    p = subprocess.Popen(cmd,
-                         cwd=directory,
-                         stdout=subprocess.PIPE,
-                         stderr=subprocess.PIPE)
-    (stdout, _) = p.communicate()
-    if p.returncode != 0:
-        raise RuntimeError('Failed to run %s in %s' % (cmd, directory))
-    return stdout
-
+    try:
+      p = subprocess.Popen(cmd,
+                           cwd=directory,
+                           stdout=subprocess.PIPE,
+                           stderr=subprocess.PIPE)
+      (stdout, stderr) = p.communicate()
+      if p.returncode != 0:
+        logging.error('Failed to run "{}" in "{}": {}'.format(cmd, directory, stderr.decode()))
+    except Exception as e:
+        logging.error('Failed to run "{}" in "{}": {}'.format(cmd, directory, str(e)))
+        return False, None
+    return p.returncode == 0, stdout
 
 def deduce_software_version(changes_file):
-    """Returns a software version number parsed from the given CHANGES file.
+    """Returns a tuple (success, software version number) parsed from the
+    given CHANGES file.
 
-    The CHANGES file describes most recent versions first.
+    Success is set to True if the software version could be deduced.
+    Software version is undefined if success if False.
+    Function expects the CHANGES file to describes most recent versions first.
     """
 
-    # Match the first well-formed version-and-date line.
+    # Match the first well-formed version-and-date line
     # Allow trailing whitespace in the checked-out source code has
     # unexpected carriage returns on a linefeed-only system such as
     # Linux.
@@ -88,60 +97,69 @@
         for line in f.readlines():
             match = pattern.match(line)
             if match:
-                return match.group(1)
-    raise Exception('No version number found in {}'.format(changes_file))
+                return True, match.group(1)
+    return False, None
 
 
-def describe(directory):
+def describe(repo_path):
     """Returns a string describing the current Git HEAD version as descriptively
     as possible.
 
     Runs 'git describe', or alternately 'git rev-parse HEAD', in directory.  If
     successful, returns the output; otherwise returns 'unknown hash, <date>'."""
-    try:
-        # decode() is needed here for Python3 compatibility. In Python2,
-        # str and bytes are the same type, but not in Python3.
-        # Popen.communicate() returns a bytes instance, which needs to be
-        # decoded into text data first in Python3. And this decode() won't
-        # hurt Python2.
-        return command_output(['git', 'describe'], directory).rstrip().decode()
-    except:
-        try:
-            return command_output(
-                ['git', 'rev-parse', 'HEAD'], directory).rstrip().decode()
-        except:
-            # This is the fallback case where git gives us no information,
-            # e.g. because the source tree might not be in a git tree.
-            # In this case, usually use a timestamp.  However, to ensure
-            # reproducible builds, allow the builder to override the wall
-            # clock time with environment variable SOURCE_DATE_EPOCH
-            # containing a (presumably) fixed timestamp.
-            timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
-            formatted = datetime.datetime.utcfromtimestamp(timestamp).isoformat()
-            return 'unknown hash, {}'.format(formatted)
 
+    success, output = command_output(['git', 'describe'], repo_path)
+    if not success:
+      output = command_output(['git', 'rev-parse', 'HEAD'], repo_path)
+
+    if success:
+      # decode() is needed here for Python3 compatibility. In Python2,
+      # str and bytes are the same type, but not in Python3.
+      # Popen.communicate() returns a bytes instance, which needs to be
+      # decoded into text data first in Python3. And this decode() won't
+      # hurt Python2.
+      return output.rstrip().decode()
+
+    # This is the fallback case where git gives us no information,
+    # e.g. because the source tree might not be in a git tree.
+    # In this case, usually use a timestamp.  However, to ensure
+    # reproducible builds, allow the builder to override the wall
+    # clock time with environment variable SOURCE_DATE_EPOCH
+    # containing a (presumably) fixed timestamp.
+    timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
+    iso_date = datetime.datetime.utcfromtimestamp(timestamp).isoformat()
+    return "unknown hash, {}".format(iso_date)
 
 def main():
+    FORMAT = '%(asctime)s %(message)s'
+    logging.basicConfig(format="[%(asctime)s][%(levelname)-8s] %(message)s", datefmt="%H:%M:%S")
     if len(sys.argv) != 3:
-        print('usage: {} <changes-files> <output-file>'.format(sys.argv[0]))
+        logging.error("usage: {} <repo-path> <output-file>".format(sys.argv[0]))
         sys.exit(1)
 
-    output_file = sys.argv[2]
-    mkdir_p(os.path.dirname(output_file))
+    changes_file_path = os.path.realpath(sys.argv[1])
+    output_file_path = sys.argv[2]
 
-    software_version = deduce_software_version(sys.argv[1])
-    directory = os.path.dirname(sys.argv[1])
-    new_content = '"{}", "SPIRV-Tools {} {}"\n'.format(
-        software_version, software_version,
-        describe(directory).replace('"', '\\"'))
+    success, version = deduce_software_version(changes_file_path)
+    if not success:
+      logging.error("Could not deduce latest release version from {}.".format(changes_file_path))
+      sys.exit(1)
 
-    if os.path.isfile(output_file):
-        with open(output_file, 'r') as f:
-            if new_content == f.read():
-                return
+    repo_path = os.path.dirname(changes_file_path)
+    description = describe(repo_path)
+    content = OUTPUT_FORMAT.format(version_tag=version, description=description)
 
-    with open(output_file, 'w') as f:
-        f.write(new_content)
+    # Escape file content.
+    content.replace('"', '\\"')
+
+    if os.path.isfile(output_file_path):
+      with open(output_file_path, 'r') as f:
+        if content == f.read():
+          return
+
+    mkdir_p(os.path.dirname(output_file_path))
+    with open(output_file_path, 'w') as f:
+        f.write(content)
 
 if __name__ == '__main__':
     main()