Merge remote-tracking branch 'origin/main' into bazel-gpu
diff --git a/README.md b/README.md
index b1fd668..129547c 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@
 working on enabling macOS support. For deployment, IREE aims to additionally
 cover Android and iOS.
 
-Please see the [Getting Started](https://google.github.io/iree/get_started)
+Please see the [Getting Started](https://google.github.io/iree/get-started)
 pages on IREE's [documentation hub](https://google.github.io/iree) to configure,
 compile, and run IREE in your favorite development environment!
 
diff --git a/SUBMODULE_VERSIONS b/SUBMODULE_VERSIONS
index b802f7d..f291e40 100644
--- a/SUBMODULE_VERSIONS
+++ b/SUBMODULE_VERSIONS
@@ -4,7 +4,7 @@
 a5d9d0f7d368054fd1691aedf1db4116efcc233e third_party/flatbuffers
 4fb0ff7069bd88ee85902f4d0bb62794e5f6d021 third_party/flatcc
 f2fb48c3b3d79a75a88a99fba6576b25d42ec528 third_party/googletest
-99ad956fdaee5398fdcf46fa49cb433cf52dc461 third_party/llvm-project
+f7ffb122d08e7a8203557898c67eaac3a857b152 third_party/llvm-project
 17b12a4481daa150e2d1ea3ada086b551b856707 third_party/marl
 67f3ccebee84f3488b46a8d3ac005178c52ff264 third_party/mlir-emitc
 80d452484c5409444b0ec19383faa84bb7a4d351 third_party/pybind11
@@ -12,7 +12,7 @@
 b73f111094da3e380a1774b56b15f16c90ae8e23 third_party/sdl2
 f8bf11a0253a32375c32cad92c841237b96696c0 third_party/spirv_headers
 57eb48aed36160c4876bc8310d9ca84d42ee9e2a third_party/swiftshader
-e4a48da690fac3443825b535ec02cb31c5625337 third_party/tensorflow
+63b8670dae816422d73dde511566a4cbd329ca18 third_party/tensorflow
 864d86e8b6d21449474db5e9313dbff90aa9c24f third_party/tracy
 9bd3f561bcee3f01d22912de10bb07ce4e23d378 third_party/vulkan_headers
 909f36b714c9239ee0b112a321220213a474ba53 third_party/vulkan_memory_allocator
diff --git a/build_tools/bazel/build_tensorflow.sh b/build_tools/bazel/build_tensorflow.sh
index 07b0eb8..fdade7c 100755
--- a/build_tools/bazel/build_tensorflow.sh
+++ b/build_tools/bazel/build_tensorflow.sh
@@ -43,6 +43,11 @@
   --test_env=IREE_LLVMJIT_DISABLE=$IREE_LLVMJIT_DISABLE
   --test_env=IREE_VULKAN_DISABLE=$IREE_VULKAN_DISABLE
 )
+# Pass in VK_ICD_FILENAMES if exists so that the Vulkan loader can find the
+# Vulkan implementation.
+if  [[ -v VK_ICD_FILENAMES ]]; then
+  test_env_args+=(--test_env=VK_ICD_FILENAMES=$VK_ICD_FILENAMES)
+fi
 
 declare -a default_build_tag_filters=("-nokokoro")
 declare -a default_test_tag_filters=("-nokokoro")
diff --git a/build_tools/docker/bazel_swiftshader/Dockerfile b/build_tools/docker/bazel_swiftshader/Dockerfile
new file mode 100644
index 0000000..2af027d
--- /dev/null
+++ b/build_tools/docker/bazel_swiftshader/Dockerfile
@@ -0,0 +1,92 @@
+# Copyright 2020 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
+#
+#      https://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.
+
+# An image for building IREE with tensorflow integrations using bazel and
+# running Vulkan tests on SwiftShader.
+
+# Build using:
+# docker build --tag gcr.io/iree-oss/bazel-swiftshader \
+#   build_tools/docker/bazel_swiftshader/
+
+# Run interactively using the following, where IREE_WORKDIR is the path to your
+# local dev environment:
+# docker run -it --rm --entrypoint bash --volume ${IREE_WORKDIR}:/usr/src/iree/ \
+#   gcr.io/iree-oss/bazel-swiftshader
+
+# Set up the image and working directory.
+FROM gcr.io/iree-oss/bazel-tensorflow
+
+# TODO(#2651): The following steps are copied from cmake, cmake-vulkan, and
+# cmake-swiftshader. We might want to consider using docker multi-stage
+# builds to factor them out.
+
+# Additionally, we need to install the Vulkan SDK.
+
+ARG VULKAN_SDK_VERSION=1.2.141
+
+# Disable apt-key parse waring. If someone knows how to do whatever the "proper"
+# thing is then feel free. The warning complains about parsing apt-key output,
+# which we're not even doing.
+ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1
+
+RUN wget -qO - http://packages.lunarg.com/lunarg-signing-key-pub.asc \
+    | apt-key add - \
+  && wget -qO \
+    "/etc/apt/sources.list.d/lunarg-vulkan-${VULKAN_SDK_VERSION?}-bionic.list" \
+    "http://packages.lunarg.com/vulkan/${VULKAN_SDK_VERSION?}/lunarg-vulkan-${VULKAN_SDK_VERSION?}-bionic.list" \
+  && apt-get update \
+  && apt-get install -y vulkan-sdk
+
+ARG SWIFTSHADER_COMMIT=6a8a74986c357b0c6fa0dfd2b4b9230af8d39d1a
+
+# Then compile and install SwiftShader.
+
+# cmake, ninja, and zlib is needed for compiling SwiftShader.
+RUN apt-get update && apt-get install -y cmake ninja-build zlib1g-dev
+
+# Update cmake to v3.13+, which is ahead of apt-get's version (3.10.2).
+ENV CMAKE_VERSION 3.13.5
+RUN apt-get update \
+  && mkdir ./cmake_install \
+  && cd cmake_install \
+  && wget "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION?}/cmake-${CMAKE_VERSION?}.tar.gz" \
+  && tar -xzvf "cmake-${CMAKE_VERSION?}.tar.gz" \
+  && cd "cmake-${CMAKE_VERSION?}/" \
+  && cmake . \
+  && make \
+  && make install
+
+RUN git clone https://github.com/google/swiftshader \
+  && cd swiftshader && git checkout "${SWIFTSHADER_COMMIT?}" && cd .. \
+  # Only build SwiftShader Vulkan ICD.
+  && cmake -S swiftshader/ -B build-swiftshader/ \
+           -GNinja \
+           -DSWIFTSHADER_BUILD_VULKAN=ON \
+           -DSWIFTSHADER_BUILD_EGL=OFF \
+           -DSWIFTSHADER_BUILD_GLESv2=OFF \
+           -DSWIFTSHADER_BUILD_GLES_CM=OFF \
+           -DSWIFTSHADER_BUILD_PVR=OFF \
+           -DSWIFTSHADER_BUILD_TESTS=OFF \
+  && cmake --build build-swiftshader/ \
+           --config Release \
+           --target vk_swiftshader \
+  # Copy the ICD JSON and .so to a known place.
+  && cp -rf build-swiftshader/Linux /swiftshader \
+  # Keep track of the commit we are using.
+  && echo "${SWIFTSHADER_COMMIT?}" > /swiftshader/git-commit \
+  # Clean up everything.
+  && rm -rf swiftshader build-swiftshader
+
+# Set VK_ICD_FILENAMES so Vulkan loader can find the SwiftShader ICD.
+ENV VK_ICD_FILENAMES /swiftshader/vk_swiftshader_icd.json
diff --git a/build_tools/docker/build_and_update_gcr.py b/build_tools/docker/build_and_update_gcr.py
index 95f7c14..6de59a4 100755
--- a/build_tools/docker/build_and_update_gcr.py
+++ b/build_tools/docker/build_and_update_gcr.py
@@ -34,9 +34,12 @@
     'bazel-bindings': ['bazel'],
     'bazel-tensorflow': ['bazel-bindings'],
     'bazel-nvidia': ['bazel-tensorflow'],
+    'bazel-swiftshader': ['bazel-tensorflow'],
     'cmake': [],
     'cmake-android': ['cmake'],
     'cmake-nvidia': ['cmake'],
+    'cmake-vulkan': ['cmake'],
+    'cmake-swiftshader': ['cmake-vulkan'],
     'rbe-toolchain': [],
 }
 
diff --git a/build_tools/docker/cmake_nvidia/Dockerfile b/build_tools/docker/cmake_nvidia/Dockerfile
index c25519f..1fdeaee 100644
--- a/build_tools/docker/cmake_nvidia/Dockerfile
+++ b/build_tools/docker/cmake_nvidia/Dockerfile
@@ -34,6 +34,7 @@
 #      does not support Ubuntu 18.04.
 # This allows to share configuration with base CMake, but it also means we need
 # to MATCH the driver version between the host machine and the docker image.
+# TODO: use cmake-vulkan as the base.
 FROM gcr.io/iree-oss/cmake
 
 # Additionally, we need to install the Vulkan SDK and the NVIDIA Vulkan driver.
diff --git a/build_tools/docker/cmake_swiftshader/Dockerfile b/build_tools/docker/cmake_swiftshader/Dockerfile
new file mode 100644
index 0000000..b92ce02
--- /dev/null
+++ b/build_tools/docker/cmake_swiftshader/Dockerfile
@@ -0,0 +1,60 @@
+# Copyright 2020 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
+#
+#      https://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.
+
+# An image for building IREE using CMake and testing IREE with SwiftShader
+# Vulkan implementation.
+
+# Build using:
+# docker build --tag gcr.io/iree-oss/cmake-swiftshader \
+#   build_tools/docker/cmake_swiftshader/
+
+# Run interactively using the following, where IREE_WORKDIR is the path to your
+# local dev environment:
+# docker run -it --rm --entrypoint bash \
+#   --volume "${IREE_WORKDIR?}:/usr/src/iree/" \
+#   --gpus all \
+#   gcr.io/iree-oss/cmake-swiftshader
+
+# Set up the image and working directory by inheriting the base
+# CMake configuration.
+FROM gcr.io/iree-oss/cmake-vulkan
+
+ARG SWIFTSHADER_COMMIT=6a8a74986c357b0c6fa0dfd2b4b9230af8d39d1a
+
+# zlib is needed for compiling SwiftShader.
+RUN apt-get update && apt-get install zlib1g-dev
+
+RUN git clone https://github.com/google/swiftshader \
+  && cd swiftshader && git checkout "${SWIFTSHADER_COMMIT?}" && cd .. \
+  # Only build SwiftShader Vulkan ICD.
+  && cmake -S swiftshader/ -B build-swiftshader/ \
+           -GNinja \
+           -DSWIFTSHADER_BUILD_VULKAN=ON \
+           -DSWIFTSHADER_BUILD_EGL=OFF \
+           -DSWIFTSHADER_BUILD_GLESv2=OFF \
+           -DSWIFTSHADER_BUILD_GLES_CM=OFF \
+           -DSWIFTSHADER_BUILD_PVR=OFF \
+           -DSWIFTSHADER_BUILD_TESTS=OFF \
+  && cmake --build build-swiftshader/ \
+           --config Release \
+           --target vk_swiftshader \
+  # Copy the ICD JSON and .so to a known place.
+  && cp -rf build-swiftshader/Linux /swiftshader \
+  # Keep track of the commit we are using.
+  && echo "${SWIFTSHADER_COMMIT?}" > /swiftshader/git-commit \
+  # Clean up everything.
+  && rm -rf swiftshader build-swiftshader
+
+# Set VK_ICD_FILENAMES so Vulkan loader can find the SwiftShader ICD.
+ENV VK_ICD_FILENAMES /swiftshader/vk_swiftshader_icd.json
diff --git a/build_tools/docker/cmake_vulkan/Dockerfile b/build_tools/docker/cmake_vulkan/Dockerfile
new file mode 100644
index 0000000..f2cdee6
--- /dev/null
+++ b/build_tools/docker/cmake_vulkan/Dockerfile
@@ -0,0 +1,47 @@
+# Copyright 2020 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
+#
+#      https://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.
+
+# An image with Vulkan SDK for building IREE using CMake.
+
+# Build using:
+# docker build --tag gcr.io/iree-oss/cmake-vulkan \
+#   build_tools/docker/cmake_vulkan/
+
+# Run interactively using the following, where IREE_WORKDIR is the path to your
+# local dev environment:
+# docker run -it --rm --entrypoint bash \
+#   --volume "${IREE_WORKDIR?}:/usr/src/iree/" \
+#   --gpus all \
+#   gcr.io/iree-oss/cmake-vulkan
+
+# Set up the image and working directory by inheriting the base
+# CMake configuration.
+FROM gcr.io/iree-oss/cmake
+
+# Additionally, we need to install the Vulkan SDK.
+
+ARG VULKAN_SDK_VERSION=1.2.141
+
+# Disable apt-key parse waring. If someone knows how to do whatever the "proper"
+# thing is then feel free. The warning complains about parsing apt-key output,
+# which we're not even doing.
+ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1
+
+RUN wget -qO - http://packages.lunarg.com/lunarg-signing-key-pub.asc \
+    | apt-key add - \
+  && wget -qO \
+    "/etc/apt/sources.list.d/lunarg-vulkan-${VULKAN_SDK_VERSION?}-bionic.list" \
+    "http://packages.lunarg.com/vulkan/${VULKAN_SDK_VERSION?}/lunarg-vulkan-${VULKAN_SDK_VERSION?}-bionic.list" \
+  && apt-get update \
+  && apt-get install -y vulkan-sdk
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/build.sh b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/build.sh
new file mode 100755
index 0000000..32c061f
--- /dev/null
+++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/build.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Copyright 2019 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
+#
+#      https://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.
+
+# For use within a IREE bazel-swiftshader docker image on a Kokoro VM.
+# Log some information about the environment, initialize the submodules and then
+# run the bazel integrations tests.
+
+set -e
+set -x
+
+# Print the UTC time when set -x is on
+export PS4='[$(date -u "+%T %Z")] '
+
+# Check these exist and print the versions for later debugging
+bazel --version
+"$CXX" --version
+"$CC" --version
+"$PYTHON_BIN" -V
+# TODO(#1875): Make PYTHON_BIN also control the runtime version
+python3 -V
+
+# Print Vulkan related information: SDK version and GPU ICD version
+vulkaninfo 2>/dev/null | grep "Vulkan Instance" || echo "Vulkan Instance not found!"
+vulkaninfo 2>/dev/null | grep -A7 "VkPhysicalDeviceProperties"  || echo "VkPhysicalDeviceProperties not found!"
+
+# Print SwiftShader git commit
+cat /swiftshader/git-commit
+
+echo "Initializing submodules"
+./scripts/git/submodule_versions.py init
+
+echo "Building and testing with bazel"
+./build_tools/bazel/build_tensorflow.sh
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/build_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/build_kokoro.sh
new file mode 100755
index 0000000..63c5893
--- /dev/null
+++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/build_kokoro.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+# Copyright 2020 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
+#
+#      https://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.
+
+# Build and test IREE's integrations within gcr.io/iree-oss/bazel-swiftshader
+# image using Kokoro.
+# Requires the environment variables KOKORO_ROOT and KOKORO_ARTIFACTS_DIR, which
+# are set by Kokoro.
+
+set -x
+set -e
+set -o pipefail
+
+# Print the UTC time when set -x is on
+export PS4='[$(date -u "+%T %Z")] '
+
+source "${KOKORO_ARTIFACTS_DIR?}/github/iree/build_tools/kokoro/gcp_ubuntu/docker_common.sh"
+
+# Sets DOCKER_RUN_ARGS
+docker_setup
+
+docker run "${DOCKER_RUN_ARGS[@]?}" \
+  --env IREE_VULKAN_DISABLE=0 \
+  gcr.io/iree-oss/bazel-swiftshader:prod \
+  build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/build.sh
+
+# Kokoro will rsync this entire directory back to the executor orchestrating the
+# build which takes forever and is totally useless.
+rm -rf "${KOKORO_ARTIFACTS_DIR?}"/*
+
+# Print out artifacts dir contents after deleting them as a coherence check.
+ls -1a "${KOKORO_ARTIFACTS_DIR?}/"
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/common.cfg
similarity index 76%
rename from build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/continuous.cfg
rename to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/common.cfg
index 50a7eed..609936e 100644
--- a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/bindings/continuous.cfg
+++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/common.cfg
@@ -14,6 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
+build_file: "iree/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/build_kokoro.sh"
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/google.cfg
similarity index 100%
rename from build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/continuous.cfg
rename to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/google.cfg
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/main.cfg
similarity index 100%
copy from build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/continuous.cfg
copy to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/main.cfg
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/presubmit.cfg
similarity index 100%
copy from build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/continuous.cfg
copy to build_tools/kokoro/gcp_ubuntu/bazel/linux/x86-swiftshader/integrations/presubmit.cfg
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/continuous.cfg
deleted file mode 100755
index 50a7eed..0000000
--- a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/core/continuous.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
-
-# Copyright 2019 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
-#
-#      https://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.
-
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build_kokoro.sh
index c35d897..19af965 100755
--- a/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build_kokoro.sh
+++ b/build_tools/kokoro/gcp_ubuntu/bazel/linux/x86/integrations/build_kokoro.sh
@@ -26,10 +26,16 @@
 # Print the UTC time when set -x is on
 export PS4='[$(date -u "+%T %Z")] '
 
-source "${KOKORO_ARTIFACTS_DIR?}/github/iree/build_tools/kokoro/gcp_ubuntu/docker_common.sh"
+WORKDIR="${KOKORO_ARTIFACTS_DIR?}/github/iree"
 
-# Sets DOCKER_RUN_ARGS
-docker_setup
+# TODO(#2653): Don't run docker as root
+DOCKER_RUN_ARGS=(
+      # Make the source repository available
+      --volume="${WORKDIR?}:${WORKDIR?}"
+      --workdir="${WORKDIR?}"
+      # Delete the container after
+      --rm
+)
 
 docker run "${DOCKER_RUN_ARGS[@]?}" \
   gcr.io/iree-oss/bazel-tensorflow:prod \
@@ -37,7 +43,8 @@
 
 # Kokoro will rsync this entire directory back to the executor orchestrating the
 # build which takes forever and is totally useless.
-rm -rf "${KOKORO_ARTIFACTS_DIR?}"/*
+# TODO(#2653): Remove sudo when docker doesn't run as root
+sudo rm -rf "${KOKORO_ARTIFACTS_DIR?}"/*
 
 # Print out artifacts dir contents after deleting them as a coherence check.
 ls -1a "${KOKORO_ARTIFACTS_DIR?}/"
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/build.sh b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/build.sh
new file mode 100755
index 0000000..ddd5a74
--- /dev/null
+++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/build.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+# Copyright 2020 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
+#
+#      https://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.
+
+# Build the project with cmake using Kokoro.
+
+set -e
+set -x
+
+# Print the UTC time when set -x is on
+export PS4='[$(date -u "+%T %Z")] '
+
+# Check these exist and print the versions for later debugging
+export CMAKE_BIN="$(which cmake)"
+"$CMAKE_BIN" --version
+"$CC" --version
+"$CXX" --version
+python3 --version
+
+# For some reason the environment variable set in base `cmake` image cannot
+# reach the child `cmake-swiftshader` image. Given this environment variable
+# is just a temporary solution, duplicate it here instead of spending all
+# the effort trying to figure out why.
+# TODO(#2645): remove this once we have a better solution for AOT linker
+# discovery.
+export IREE_LLVMAOT_LINKER_PATH=/usr/bin/ld
+
+# Print Vulkan related information: SDK version and GPU ICD version
+vulkaninfo 2>/dev/null | grep "Vulkan Instance" || echo "Vulkan Instance not found!"
+vulkaninfo 2>/dev/null | grep -A7 "VkPhysicalDeviceProperties"  || echo "VkPhysicalDeviceProperties not found!"
+
+# Print SwiftShader git commit
+cat /swiftshader/git-commit
+
+echo "Initializing submodules"
+./scripts/git/submodule_versions.py init
+
+# TODO(gcmn): It would be nice to be able to build and test as much as possible,
+# so a build failure only prevents building/testing things that depend on it and
+# we can still run the other tests.
+echo "Building with cmake"
+./build_tools/cmake/clean_build.sh
+
+echo "Testing with ctest"
+./build_tools/cmake/test.sh
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/build_kokoro.sh b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/build_kokoro.sh
new file mode 100755
index 0000000..82426ec
--- /dev/null
+++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/build_kokoro.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+# Copyright 2020 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
+#
+#      https://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.
+
+# Build and test the project within the gcr.io/iree-oss/cmake-swiftshader image
+# using Kokoro.
+# Requires the environment variables KOKORO_ROOT and KOKORO_ARTIFACTS_DIR, which
+# are set by Kokoro.
+
+set -x
+set -e
+set -o pipefail
+
+# Print the UTC time when set -x is on
+export PS4='[$(date -u "+%T %Z")] '
+
+source "${KOKORO_ARTIFACTS_DIR?}/github/iree/build_tools/kokoro/gcp_ubuntu/docker_common.sh"
+
+# Sets DOCKER_RUN_ARGS
+docker_setup
+
+docker run "${DOCKER_RUN_ARGS[@]?}" \
+  --env IREE_VULKAN_DISABLE=0 \
+  gcr.io/iree-oss/cmake-swiftshader:prod \
+  build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/build.sh
+
+# Kokoro will rsync this entire directory back to the executor orchestrating the
+# build which takes forever and is totally useless.
+rm -rf "${KOKORO_ARTIFACTS_DIR?}"/*
+
+# Print out artifacts dir contents after deleting them as a coherence check.
+ls -1a "${KOKORO_ARTIFACTS_DIR?}/"
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/common.cfg
similarity index 76%
rename from build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/continuous.cfg
rename to build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/common.cfg
index e4cc270..9f4a82c 100644
--- a/build_tools/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/continuous.cfg
+++ b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/common.cfg
@@ -14,6 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
+build_file: "iree/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/build_kokoro.sh"
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/continuous.cfg
similarity index 100%
rename from build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg
rename to build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/continuous.cfg
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/google.cfg
similarity index 100%
copy from build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg
copy to build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/google.cfg
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/main.cfg
similarity index 100%
copy from build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg
copy to build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/main.cfg
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/presubmit.cfg
similarity index 100%
copy from build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg
copy to build_tools/kokoro/gcp_ubuntu/cmake/linux/x86-swiftshader/presubmit.cfg
diff --git a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/continuous.cfg b/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/continuous.cfg
deleted file mode 100644
index e4cc270..0000000
--- a/build_tools/kokoro/gcp_ubuntu/cmake/linux/x86/continuous.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
-
-# Copyright 2020 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
-#
-#      https://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.
-
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
diff --git a/build_tools/kokoro/gcp_ubuntu/docker_common.sh b/build_tools/kokoro/gcp_ubuntu/docker_common.sh
index 81dc0b3..fbc896f 100644
--- a/build_tools/kokoro/gcp_ubuntu/docker_common.sh
+++ b/build_tools/kokoro/gcp_ubuntu/docker_common.sh
@@ -32,13 +32,10 @@
     mkdir -p "${fake_etc_dir?}"
 
     local fake_group="${fake_etc_dir?}/group"
-    local fake_passwd="${fake_etc_dir?}/group"
+    local fake_passwd="${fake_etc_dir?}/passwd"
 
-    cp /etc/passwd "${fake_group?}"
-    cp /etc/group "${fake_passwd?}"
-    getent group "$(id -g)" >> "${fake_group?}"
-    getent passwd "$(id -u)" >> "${fake_passwd?}"
-
+    getent group > "${fake_group?}"
+    getent passwd > "${fake_passwd?}"
 
     local workdir="${KOKORO_ARTIFACTS_DIR?}/github/iree"
 
diff --git a/build_tools/third_party/sdl2/SDL_config_windows.h b/build_tools/third_party/sdl2/SDL_config_windows.h
index 460fb3b..7626de6 100644
--- a/build_tools/third_party/sdl2/SDL_config_windows.h
+++ b/build_tools/third_party/sdl2/SDL_config_windows.h
@@ -227,6 +227,9 @@
 /* Enable filesystem support */
 #define SDL_FILESYSTEM_WINDOWS 1
 
+/* Disable sensor support */
+#define SDL_SENSOR_DISABLED 1
+
 /* Enable assembly routines (Win64 doesn't have inline asm) */
 #ifndef _WIN64
 #define SDL_ASSEMBLY_ROUTINES 1
diff --git a/docs/design_docs/codegen_passes.md b/docs/design_docs/codegen_passes.md
index e3fd371..83e37fc 100644
--- a/docs/design_docs/codegen_passes.md
+++ b/docs/design_docs/codegen_passes.md
@@ -47,8 +47,9 @@
   }
 }
 ```
-<a name="snippet1"></a>
-Snippet 1 : Dispatch region with matrix-matrix multiply operation.
+
+<a name="snippet1"></a> Snippet 1 : Dispatch region with matrix-matrix multiply
+operation.
 
 ```mlir
 hal.executable.target "vulkan*" {
@@ -82,13 +83,14 @@
   }
 }
 ```
-<a name="snippet2"></a>
-Snippet 2 : Dispatch region with element-wise operations.
+
+<a name="snippet2"></a> Snippet 2 : Dispatch region with element-wise
+operations.
 
 __Roadmap Note__: The current implementation might not actually fuse the
 operations grouped into a dispatch region into a single kernel. It is possible
-to end up with multiple kernels per dispatch region. Over time we plan to address
-this by using fusion at different levels (see below).
+to end up with multiple kernels per dispatch region. Over time we plan to
+address this by using fusion at different levels (see below).
 
 The inputs to the dispatch region are materialized within the entry point
 function using the `hal.interface.load.tensor` operation, This operation returns
@@ -109,13 +111,13 @@
 
 ## Conversion from MHLO dialect to Linalg on buffers
 
-The code generation pipeline heavily relies on use of [Structured
-Operations][LinalgRationale], specifically the [Linalg Dialect][LinalgDialect].
-Both, the Linalg operations on `tensor`s and on `memref`s are central to the
-progressive lowering approach followed here. The first part of the code
-generation pipeline is to convert the MHLO operations on `tensor`s to Linalg
-operation on `memref`s. This part of the pipeline is common to both CPU and GPU
-code generation.
+The code generation pipeline heavily relies on use of
+[Structured Operations][LinalgRationale], specifically the
+[Linalg Dialect][LinalgDialect]. Both, the Linalg operations on `tensor`s and on
+`memref`s are central to the progressive lowering approach followed here. The
+first part of the code generation pipeline is to convert the MHLO operations on
+`tensor`s to Linalg operation on `memref`s. This part of the pipeline is common
+to both CPU and GPU code generation.
 
 The steps involved in this conversion is shown below. Each of the arrows
 represents a pass in the pipeline:
@@ -124,7 +126,6 @@
 
 The next sections describe each of these passes in more detail.
 
-
 ### MHLO to Linalg on tensors
 
 The first step is to convert MHLO operations to Linalg on tensors. This is done
@@ -151,8 +152,9 @@
        linalg.yield %5 : f32
      }: tensor<10x5xf32>, tensor<10x5xf32> -> tensor<10x5xf32>
 ```
-<a name="snippet3"></a>
-Snippet 3 : MHLO to Linalg conversion for [element-wise operations](#snippet2)
+
+<a name="snippet3"></a> Snippet 3 : MHLO to Linalg conversion for
+[element-wise operations](#snippet2)
 
 At the time of writing the representation of Linalg on `tensor`s does not model
 reduction iterator types completely. Specifically, the reduction in Linalg is
@@ -181,7 +183,7 @@
 The Linalg on `tensor` operations generated at the previous step are fused using
 the [LinalgFusionOfTensorOps][LinalgFusionOfTensorOps] from MLIR. Since
 `tensor`s are SSA values, fusion at this stage can be done without using alias
-analysis or dependence analysis based on reads and writes.  Instead the use-def
+analysis or dependence analysis based on reads and writes. Instead the use-def
 chains for the `tensor` values can be used to implement producer-consumer
 fusion. This stage fuses most elementwise operations, broadcast operations and
 data movement operations. An example of the fused op is shown below.
@@ -198,9 +200,9 @@
        linalg.yield %5 : f32
      }: tensor<?x5xf32>, tensor<?x5xf32>, tensor<?x5xf32> -> tensor<?x5xf32>
 ```
-<a name="snippet4"></a>
-Snippet 4: Fusion of Linalg operation on tensors for element-wise operations
-shown in [Snippet 3](#snippet3)
+
+<a name="snippet4"></a> Snippet 4: Fusion of Linalg operation on tensors for
+element-wise operations shown in [Snippet 3](#snippet3)
 
 ### Conversion of Linalg on tensors to Linalg on buffers
 
@@ -253,8 +255,8 @@
 __Roadmap Note__ : Right now the code-generation pipeline relies on fusion of
 operations on tensor level. In the near future, we want to be able to fuse
 operations like `linalg.matmul` and `linalg.conv` with consumers/producers that
-are element-wise operations using the [fusion of Linalg operation on
-`memref`s][LinalgFusionOnBuffers].
+are element-wise operations using the
+[fusion of Linalg operation on `memref`s][LinalgFusionOnBuffers].
 
 At this stage of the compilation all operations must have been converted to
 Linalg operations on buffers. Shown below are the IR at the end of this stage
@@ -275,8 +277,8 @@
   return
 }
 ```
-<a name="snippet5"></a>
-Snippet 5 : Matrix-matrix multiply after conversion to
+
+<a name="snippet5"></a> Snippet 5 : Matrix-matrix multiply after conversion to
 Linalg operation on `memref`s.
 
 ```mlir
@@ -303,9 +305,9 @@
   return
 }
 ```
-<a name="snippet6"></a>
-Snippet 6 : Elementwise operations after conversion to Linalg operation on
-`memref`s
+
+<a name="snippet6"></a> Snippet 6 : Elementwise operations after conversion to
+Linalg operation on `memref`s
 
 The rest of the code-generation differs on whether the compilation is for CPU
 (using LLVM) or for GPU (using SPIR-V).
@@ -314,9 +316,10 @@
 
 The following sections describe the progressive lowering of Linalg operation on
 buffers to SPIR-V dialect. Once lowered to the SPIR-V dialect, it can be
-serialized into a SPIR-V binary using the [serialization mechanism provided by
-the SPIR-V dialect][SpirvSerialization]. The steps involved in the lowering are
-described below, with each of the arrows representing a pass.
+serialized into a SPIR-V binary using the
+[serialization mechanism provided by the SPIR-V dialect][SpirvSerialization].
+The steps involved in the lowering are described below, with each of the arrows
+representing a pass.
 
 ![Linalg on `memref` to SPIR-V conversion](./linalg_to_spirv.png)
 
@@ -329,18 +332,18 @@
 warps and threads, respectively, in CUDA terminology. Tiling is a way to map the
 computations to each level of the compute hierarchy. For example 3-D tiling a
 `linalg.matmul` operation decomposes the computation into several tiled
-matrix-matrix multiplies. [Tiling transformation in Linalg
-dialect][LinalgTiling] generates the outer-loops that iterate over tiled
-`linalg.matmul` operations. These outer loops can be mapped to different
-workgroups, if they are parallel. The tiled `linalg.matmul` operation can be
-further tiled to map to subgroups. Finally, the tiled operation can be lowered
-to loops with individual iterations mapped to workitems. The
-[LinalgTileAndFusePass][LinalgTileAndFuse] uses the Linalg Tiling patterns
-([defined here][LinalgTilingPatterns]) to tile operations like `linalg.matmul`,
-`linalg.conv` and `linalg.*_pooling`. The result of tiling the code in Snippet 5
-is shown below. As expected there are 2-parallel loops that iterate over tiles
-of the original iteration space (i.e. inter-tile loops) and can be distributed
-to workgroups.
+matrix-matrix multiplies.
+[Tiling transformation in Linalg dialect][LinalgTiling] generates the
+outer-loops that iterate over tiled `linalg.matmul` operations. These outer
+loops can be mapped to different workgroups, if they are parallel. The tiled
+`linalg.matmul` operation can be further tiled to map to subgroups. Finally, the
+tiled operation can be lowered to loops with individual iterations mapped to
+workitems. The [LinalgTileAndFusePass][LinalgTileAndFuse] uses the Linalg Tiling
+patterns ([defined here][LinalgTilingPatterns]) to tile operations like
+`linalg.matmul`, `linalg.conv` and `linalg.*_pooling`. The result of tiling the
+code in Snippet 5 is shown below. As expected there are 2-parallel loops that
+iterate over tiles of the original iteration space (i.e. inter-tile loops) and
+can be distributed to workgroups.
 
 ```mlir
 func @main_ex_dispatch_0()
@@ -372,15 +375,14 @@
   return
 }
 ```
-<a name="snippet7"></a>
-Snippet 7 : `linalg.matmul` after tiling.
+
+<a name="snippet7"></a> Snippet 7 : `linalg.matmul` after tiling.
 
 #### Tile Size and Workgroup Size
 
 When operations that are to be tiled exist within the dispatch function (like
-`linalg.matmul` or `linalg.conv`), this pass also decides the
-1. Tile size to be used for the tiling.
-1. The workgroup size to be used.
+`linalg.matmul` or `linalg.conv`), this pass also decides the 1. Tile size to be
+used for the tiling. 1. The workgroup size to be used.
 
 The tile size and workgroup size are closely linked since the code within the
 tiled loops are to be collectively executed by the entire workgroup. In other
@@ -397,14 +399,13 @@
 Downstream passes have to handle tiled Linalg operations and untiled Linalg
 operation that might exist in the same function in different ways. For example,
 while the former are to be executed collectively by workitems within a
-workgroup, the latter have to be executed by all workitems across
-workgroups. One way to distinguish these two operations is to use the marker
-mechanism in Linalg ([LinalgMarker][LinalgTilingPatterns]). This is a `StrAttr`
-whose value can be used to encode the scope of the operation. For example, in
-Snippet 7 above, the tiled `linalg.matmul` operation has a marker `workgroup` to
-indicate that this operation needs to be executed by a workgroup in a collective
-manner. At this time, the code-generation pipeline uses only the `workgroup`
-marker.
+workgroup, the latter have to be executed by all workitems across workgroups.
+One way to distinguish these two operations is to use the marker mechanism in
+Linalg ([LinalgMarker][LinalgTilingPatterns]). This is a `StrAttr` whose value
+can be used to encode the scope of the operation. For example, in Snippet 7
+above, the tiled `linalg.matmul` operation has a marker `workgroup` to indicate
+that this operation needs to be executed by a workgroup in a collective manner.
+At this time, the code-generation pipeline uses only the `workgroup` marker.
 
 __Roadmap Note__ : Markers are meant to be short-lived, ideally set and consumed
 within the same pass. In the current pipeline the lifetime spans passes to allow
@@ -422,18 +423,18 @@
 multiply case, the same data row (column) of the LHS (RHS) matrix is read by
 multiple workitems. Prefetching the data into `Workgroup` memory can reduce the
 number of loads to `StorageClass` memory by an order of magnitude. This
-transformation can be achieved by using the [`Linalg
-Promotion`][LinalgPromotionPatterns] which modifies the `subview`s that are the
-operands to the tiled Linalg operation to use a new `memref` object. The size of
-this `memref` is computed from the size of the `subview`. This `memref` object
-is later lowered to use `Workgroup` memory Storage Class. The snippet below
-shows this transformation when applied to `linalg.matmul` (along with
+transformation can be achieved by using the
+[`Linalg Promotion`][LinalgPromotionPatterns] which modifies the `subview`s that
+are the operands to the tiled Linalg operation to use a new `memref` object. The
+size of this `memref` is computed from the size of the `subview`. This `memref`
+object is later lowered to use `Workgroup` memory Storage Class. The snippet
+below shows this transformation when applied to `linalg.matmul` (along with
 tiling). The newly created `memref` objects are annotated with the memory space
 `3` to indicate that they are to be lowered to use `Workgroup` memory. The copy
 of data from the original `memref` into the new `memref`, as well as the
 necessary synchronization constructs are generated as well. Note the memory
-space annotation used here is consistent with what [address space annotations
-used in NVVM][NVVMAddressSpace].
+space annotation used here is consistent with what
+[address space annotations used in NVVM][NVVMAddressSpace].
 
 ```mlir
 func @matmul_tile()
@@ -479,41 +480,39 @@
 }
 ```
 
-<a name="snippet8"></a>
-Snippet 8: `linalg.matmul` after tiling and promotion of operand subviews to use
-`Workgroup` memory.
+<a name="snippet8"></a> Snippet 8: `linalg.matmul` after tiling and promotion of
+operand subviews to use `Workgroup` memory.
 
 ### Distributing to workgroups and workitems
 
 After tiling the operations within the dispatch functions are either
 `scf.parallel` operations or Linalg operations.
 
-- The outer `scf.parallel` operations represent parallel loops that are to be
-  distributed across workgroups. The distribution here assumes that the number
-  of workgroups along each dimension is equal to the number of iterations of the
-  `scf.parallel` operation.
+-   The outer `scf.parallel` operations represent parallel loops that are to be
+    distributed across workgroups. The distribution here assumes that the number
+    of workgroups along each dimension is equal to the number of iterations of
+    the `scf.parallel` operation.
 
-- Linalg operations that are not tiled, and are therefore __not within__ `scf`
-  operations, are lowered to loops. The resulting outer `scf.parallel` operations are
-  collapsed to have a single induction variable. This loop is then distributed
-  across workitems using their `GlobalInvocationId`, (which is same as
-  `blockIdx * blockDim + threadIdx` in CUDA terminology).
+-   Linalg operations that are not tiled, and are therefore __not within__ `scf`
+    operations, are lowered to loops. The resulting outer `scf.parallel`
+    operations are collapsed to have a single induction variable. This loop is
+    then distributed across workitems using their `GlobalInvocationId`, (which
+    is same as `blockIdx * blockDim + threadIdx` in CUDA terminology).
 
-- Linalg operations that are tiled, and are therefore __within__ `scf`
-  operations, are lowered to loops and the iterations of the `scf.parallel`
-  operations are mapped to workitems using their `LocalInvocationId` (which is
-  same as `threadIdx` in CUDA terminology). Note that these operations are
-  tagged with the `workgroup` marker which makes it easy to disambiguate from
-  the case where Linalg operations are outside of `scf` operations. Here too,
-  the distribution assumes that the workgroup size is greater than or equal to
-  the number of iterations of the partitioned loop.
+-   Linalg operations that are tiled, and are therefore __within__ `scf`
+    operations, are lowered to loops and the iterations of the `scf.parallel`
+    operations are mapped to workitems using their `LocalInvocationId` (which is
+    same as `threadIdx` in CUDA terminology). Note that these operations are
+    tagged with the `workgroup` marker which makes it easy to disambiguate from
+    the case where Linalg operations are outside of `scf` operations. Here too,
+    the distribution assumes that the workgroup size is greater than or equal to
+    the number of iterations of the partitioned loop.
 
-These transformations are applied by the
-[`ConvertToGPUPass`][ConvertToGPU]. Below is the result of applying this pass to
-Snippet 7. The outer `scf.parallel` loop is distributed across workgroups. The
-tiled `linalg.matmul` operation is lowered to loops, and the outer
-`scf.parallel` operation generated during this lowering are distributed across
-workitems within the workgroup.
+These transformations are applied by the [`ConvertToGPUPass`][ConvertToGPU].
+Below is the result of applying this pass to Snippet 7. The outer `scf.parallel`
+loop is distributed across workgroups. The tiled `linalg.matmul` operation is
+lowered to loops, and the outer `scf.parallel` operation generated during this
+lowering are distributed across workitems within the workgroup.
 
 ```mlir
 func @main_ex_dispatch_0_dispatch_1()
@@ -557,9 +556,9 @@
   return
 }
 ```
-<a name="snippet9"></a>
-Snippet 9: `linalg.matmul` after distributing parallel inter-tile loops to
-workgroups and intra-tile loops to workitems.
+
+<a name="snippet9"></a> Snippet 9: `linalg.matmul` after distributing parallel
+inter-tile loops to workgroups and intra-tile loops to workitems.
 
 [Snippet 6](#snippet6) shows the fused element-wise operations represented using
 a `linalg.generic` operation. This operation is not tiled in the
@@ -601,8 +600,9 @@
   return
 }
 ```
-<a name="snippet10"></a>
-Snippet 10: Distributing the iterations for pointwise operations for GPU execution.
+
+<a name="snippet10"></a> Snippet 10: Distributing the iterations for pointwise
+operations for GPU execution.
 
 ### Lowering to SPIR-V dialect
 
@@ -612,10 +612,10 @@
 by applying all the patterns that lower all the different IR constructs into
 SPIR-V within the [`ConvertToSPIRVPass`][ConvertToSPIRV]. These are
 
-- [GPU dialect to SPIR-V conversion][GPUToSPIRV].
-- [SCF dialect to SPIR-V conversion][SCFToSPIRV].
-- [Standard dialect to SPIR-V conversion][StandardToSPIRV].
-- Patterns that lower the `iree.placeholder` instruction into a SPIR-V.
+-   [GPU dialect to SPIR-V conversion][GPUToSPIRV].
+-   [SCF dialect to SPIR-V conversion][SCFToSPIRV].
+-   [Standard dialect to SPIR-V conversion][StandardToSPIRV].
+-   Patterns that lower the `iree.placeholder` instruction into a SPIR-V.
 
 Once applied the resulting IR is in SPIR-V dialect that can be serialized to a
 SPIR-V binary.
diff --git a/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils_test.py b/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils_test.py
index fe25f97..b1d9adb 100644
--- a/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils_test.py
+++ b/integrations/tensorflow/bindings/python/pyiree/tf/support/tf_utils_test.py
@@ -65,7 +65,9 @@
           artifacts_dir=artifacts_dir)
 
       artifacts_to_check = [
-          'saved_model', 'tf_input.mlir', 'iree_input.mlir',
+          'saved_model',
+          'tf_input.mlir',
+          'iree_input.mlir',
           f'compiled__{tf_utils.backends_to_str(target_backends)}.vmfb',
       ]
       for artifact in artifacts_to_check:
diff --git a/iree/compiler/Conversion/LinalgToLLVM/ConvertToLLVM.cpp b/iree/compiler/Conversion/LinalgToLLVM/ConvertToLLVM.cpp
index 8686dca..76fb2c5 100644
--- a/iree/compiler/Conversion/LinalgToLLVM/ConvertToLLVM.cpp
+++ b/iree/compiler/Conversion/LinalgToLLVM/ConvertToLLVM.cpp
@@ -17,6 +17,7 @@
 #include "iree/compiler/Dialect/HAL/IR/HALOps.h"
 #include "iree/compiler/Dialect/IREE/IR/IREEOps.h"
 #include "iree/compiler/Dialect/Shape/IR/ShapeOps.h"
+#include "iree/compiler/Dialect/Shape/IR/ShapeTypes.h"
 #include "mlir/Conversion/AffineToStandard/AffineToStandard.h"
 #include "mlir/Conversion/LinalgToLLVM/LinalgToLLVM.h"
 #include "mlir/Conversion/SCFToStandard/SCFToStandard.h"
@@ -308,8 +309,13 @@
 
 void ConvertToLLVMPass::runOnOperation() {
   auto module = getOperation();
-  OwningRewritePatternList patterns;
+
   LLVMTypeConverter converter(&getContext());
+  converter.addConversion([](Shape::RankedShapeType, SmallVectorImpl<Type> &) {
+    return success();
+  });
+
+  OwningRewritePatternList patterns;
   populateAffineToStdConversionPatterns(patterns, &getContext());
   populateLoopToStdConversionPatterns(patterns, &getContext());
   populateExpandTanhPattern(patterns, &getContext());
diff --git a/iree/compiler/Conversion/LinalgToLLVM/test/convert_to_llvm.mlir b/iree/compiler/Conversion/LinalgToLLVM/test/convert_to_llvm.mlir
index c8bf6d8..d362688 100644
--- a/iree/compiler/Conversion/LinalgToLLVM/test/convert_to_llvm.mlir
+++ b/iree/compiler/Conversion/LinalgToLLVM/test/convert_to_llvm.mlir
@@ -1,24 +1,34 @@
 // RUN: iree-opt -iree-codegen-convert-to-llvm -split-input-file %s | IreeFileCheck %s
 
-// CHECK-LABEL: func @convert_dynamic_shape
-func @convert_dynamic_shape(%arg0: memref<?x?xf32>, %arg1: memref<2xi32>){
-    %c0 = constant 0 : index
-    %c1 = constant 1 : index
-    %0 = load %arg1[%c0] : memref<2xi32>
-    %1 = index_cast %0 : i32 to index
-    %3 = load %arg1[%c1] : memref<2xi32>
-    %4 = index_cast %3 : i32 to index
-    %5 = shapex.make_ranked_shape %1, %4 : (index, index) -> !shapex.ranked_shape<[?,?]>
-    %6 = shapex.tie_shape %arg0, %5 : memref<?x?xf32>, !shapex.ranked_shape<[?,?]>
-    return
+func @convert_dynamic_shape() {
+  %0 = iree.placeholder for "interface buffer" {binding = @legacy_io::@arg0} : memref<?x?xf32>
+  %1 = hal.interface.load.constant offset = 0 : index
+  %2 = hal.interface.load.constant offset = 1 : index
+  %3 = shapex.make_ranked_shape %1, %2 : (index, index) -> !shapex.ranked_shape<[?,?]>
+  %6 = shapex.tie_shape %0, %3 : memref<?x?xf32>, !shapex.ranked_shape<[?,?]>
+  return
 }
-// CHECK: %[[DIM0:.+]] = llvm.sext
-// CHECK: %[[DIM1:.+]] = llvm.sext
-// CHECK: llvm.insertvalue %[[DIM0]], %[[MEMREFBASEPTR:.+]][3, 0]
-// CHECK: %[[MEMREFBASEPTR_1:.+]] = llvm.insertvalue %[[DIM1]], %[[MEMREFBASEPTR:.+]][3, 1]
-// CHECK: %[[STRIDE1:.+]] = llvm.mlir.constant(1 : index) : !llvm.i64
-// CHECK: %[[MEMREFBASEPTR_2:.+]] = llvm.insertvalue %[[STRIDE1]], %[[MEMREFBASEPTR_1]][4, 1]
-// CHECK: %[[ESTRIDE1:.+]] = llvm.extractvalue %[[MEMREFBASEPTR_2]][4, 1] 
-// CHECK: %[[EDIM1:.+]] = llvm.extractvalue %[[MEMREFBASEPTR_2]][3, 1] 
-// CHECK: %[[STRIDE0:.+]] = llvm.mul %[[ESTRIDE1]], %[[EDIM1]] : !llvm.i64
-// CHECK: llvm.insertvalue %[[STRIDE0]], %[[MEMREFBASEPTR_2]][4, 0]
\ No newline at end of file
+hal.interface @legacy_io attributes {push_constants = 2 : i32, sym_visibility = "private"} {
+    hal.interface.binding @arg0, set=0, binding=0, type="StorageBuffer", access="Read"
+}
+// CHECK: llvm.func @convert_dynamic_shape(%[[ARG0:.+]]: !llvm<"i8**">, %[[ARG1:.+]]: !llvm<"i64*">)
+// CHECK: %[[PACKED_ARGS_PTR:.+]] = llvm.bitcast %[[ARG0]] : !llvm<"i8**"> to !llvm<"{ float* }*">
+// CHECK: %[[PACKED_ARGS:.+]] = llvm.load %[[PACKED_ARGS_PTR]] : !llvm<"{ float* }*">
+// CHECK: %[[MEMREF0_DATA_PTR:.+]] = llvm.extractvalue %[[PACKED_ARGS]][0] : !llvm<"{ float* }">
+// CHECK: %[[MEMREF0:.+]] = llvm.mlir.undef : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
+// CHECK: %[[MEMREF0_0:.+]] = llvm.insertvalue %[[MEMREF0_DATA_PTR]], %[[MEMREF0]][0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
+// CHECK: %[[MEMREF0_1:.+]] = llvm.insertvalue %[[MEMREF0_DATA_PTR]], %[[MEMREF0_0]][1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
+// CHECK: %[[CONST0:.+]] = llvm.mlir.constant(0 : i64) : !llvm.i64
+// CHECK: %[[DIM0_PTR:.+]] = llvm.getelementptr %[[ARG1]][%[[CONST0]]] : (!llvm<"i64*">, !llvm.i64) -> !llvm<"i64*">
+// CHECK: %[[DIM0:.+]] = llvm.load %[[DIM0_PTR]] : !llvm<"i64*">
+// CHECK: %[[CONST1:.+]] = llvm.mlir.constant(1 : i64) : !llvm.i64
+// CHECK: %[[DIM1_PTR:.+]] = llvm.getelementptr %[[ARG1]][%[[CONST1]]] : (!llvm<"i64*">, !llvm.i64) -> !llvm<"i64*">
+// CHECK: %[[DIM1:.+]] = llvm.load %[[DIM1_PTR]] : !llvm<"i64*">
+// CHECK: %[[MEMREF0_2:.+]] = llvm.insertvalue %[[DIM0]], %[[MEMREF0_1]][3, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
+// CHECK: %[[MEMREF0_3:.+]] = llvm.insertvalue %[[DIM1]], %[[MEMREF0_2]][3, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
+// CHECK: %[[CONST1_STRIDE:.+]] = llvm.mlir.constant(1 : index) : !llvm.i64
+// CHECK: %[[MEMREF0_4:.+]] = llvm.insertvalue %[[CONST1_STRIDE]], %[[MEMREF0_3]][4, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
+// CHECK: %[[STRIDE_DIM1:.+]] = llvm.extractvalue %[[MEMREF0_4]][4, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
+// CHECK: %[[DIM1_0:.+]] = llvm.extractvalue %[[MEMREF0_4]][3, 1] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
+// CHECK: %[[STRIDE_DIM0:.+]] = llvm.mul %[[STRIDE_DIM1]], %[[DIM1_0]] : !llvm.i64
+// CHECK: llvm.insertvalue %[[STRIDE_DIM0]], %[[MEMREF0_4]][4, 0] : !llvm<"{ float*, float*, i64, [2 x i64], [2 x i64] }">
diff --git a/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp b/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
index 668442f..de6e351 100644
--- a/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
+++ b/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
@@ -80,13 +80,12 @@
       });
 
   // TODO(b/145876978): materialize conversion for other types
-  addMaterialization([](PatternRewriter &rewriter,
-                        Shape::RankedShapeType resultType, ValueRange inputs,
-                        Location loc) -> Optional<Value> {
+  addArgumentMaterialization([](OpBuilder &builder,
+                                Shape::RankedShapeType resultType,
+                                ValueRange inputs, Location loc) -> Value {
     LLVM_DEBUG(llvm::dbgs()
                << "MATERIALIZE CONVERSION: " << resultType << "\n");
-    return rewriter.create<Shape::MakeRankedShapeOp>(loc, resultType, inputs)
-        .getResult();
+    return builder.create<Shape::MakeRankedShapeOp>(loc, resultType, inputs);
   });
 }
 
diff --git a/iree/test/e2e/xla_ops/BUILD b/iree/test/e2e/xla_ops/BUILD
index 9af6bd1..b492e10 100644
--- a/iree/test/e2e/xla_ops/BUILD
+++ b/iree/test/e2e/xla_ops/BUILD
@@ -82,9 +82,7 @@
         "tanh.mlir",
         "torch_index_select.mlir",
         "transpose.mlir",
-
-        # TODO(#2022): fails on real devices.
-        # "while.mlir",
+        "while.mlir",
     ],
     driver = "vulkan",
     target_backend = "vulkan-spirv",
diff --git a/iree/test/e2e/xla_ops/CMakeLists.txt b/iree/test/e2e/xla_ops/CMakeLists.txt
index 7f65b06..e2ab883 100644
--- a/iree/test/e2e/xla_ops/CMakeLists.txt
+++ b/iree/test/e2e/xla_ops/CMakeLists.txt
@@ -66,6 +66,7 @@
     "tanh.mlir"
     "torch_index_select.mlir"
     "transpose.mlir"
+    "while.mlir"
   TARGET_BACKEND
     vulkan-spirv
   DRIVER
diff --git a/kokoro/gcp_ubuntu/bazel/bindings/continuous.cfg b/kokoro/gcp_ubuntu/bazel/bindings/continuous.cfg
deleted file mode 100644
index 50a7eed..0000000
--- a/kokoro/gcp_ubuntu/bazel/bindings/continuous.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
-
-# Copyright 2019 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
-#
-#      https://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.
-
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/bazel/core/continuous.cfg b/kokoro/gcp_ubuntu/bazel/core/continuous.cfg
deleted file mode 100755
index 50a7eed..0000000
--- a/kokoro/gcp_ubuntu/bazel/core/continuous.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
-
-# Copyright 2019 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
-#
-#      https://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.
-
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/bazel/integrations/continuous.cfg b/kokoro/gcp_ubuntu/bazel/integrations/continuous.cfg
deleted file mode 100644
index 50a7eed..0000000
--- a/kokoro/gcp_ubuntu/bazel/integrations/continuous.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
-
-# Copyright 2019 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
-#
-#      https://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.
-
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/continuous.cfg b/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/continuous.cfg
deleted file mode 100644
index e4cc270..0000000
--- a/kokoro/gcp_ubuntu/cmake/android/arm64-v8a/continuous.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
-
-# Copyright 2020 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
-#
-#      https://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.
-
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/cmake/continuous.cfg b/kokoro/gcp_ubuntu/cmake/continuous.cfg
deleted file mode 100644
index e4cc270..0000000
--- a/kokoro/gcp_ubuntu/cmake/continuous.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
-
-# Copyright 2020 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
-#
-#      https://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.
-
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
diff --git a/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg b/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg
deleted file mode 100644
index e4cc270..0000000
--- a/kokoro/gcp_ubuntu/cmake/linux/x86-turing/continuous.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Format: //devtools/kokoro/config/proto/build.proto
-
-# Copyright 2020 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
-#
-#      https://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.
-
-# Deliberately blank as everything necessary is configured in common files, but
-# file must still exist to match corresponding (Google internal) job
-# configurations that trigger the builds.
diff --git a/third_party/llvm-project b/third_party/llvm-project
index 99ad956..f7ffb12 160000
--- a/third_party/llvm-project
+++ b/third_party/llvm-project
@@ -1 +1 @@
-Subproject commit 99ad956fdaee5398fdcf46fa49cb433cf52dc461
+Subproject commit f7ffb122d08e7a8203557898c67eaac3a857b152
diff --git a/third_party/tensorflow b/third_party/tensorflow
index e4a48da..63b8670 160000
--- a/third_party/tensorflow
+++ b/third_party/tensorflow
@@ -1 +1 @@
-Subproject commit e4a48da690fac3443825b535ec02cb31c5625337
+Subproject commit 63b8670dae816422d73dde511566a4cbd329ca18