Removing unused HAL files/functions/types.
diff --git a/bindings/python/pyiree/rt/hal.cc b/bindings/python/pyiree/rt/hal.cc
index 858e29c..4741b84 100644
--- a/bindings/python/pyiree/rt/hal.cc
+++ b/bindings/python/pyiree/rt/hal.cc
@@ -167,9 +167,6 @@
   py::class_<HalMappedMemory>(m, "MappedMemory", py::buffer_protocol())
       .def_buffer(&HalMappedMemory::ToBufferInfo);
   py::class_<HalBuffer>(m, "HalBuffer")
-      .def_static("allocate_heap", &HalBuffer::AllocateHeapBuffer,
-                  py::arg("memory_type"), py::arg("usage"),
-                  py::arg("allocation_size"))
       .def("fill_zero", &HalBuffer::FillZero, py::arg("byte_offset"),
            py::arg("byte_length"))
       .def("create_view", &HalBuffer::CreateView, py::arg("shape"),
diff --git a/bindings/python/pyiree/rt/hal.h b/bindings/python/pyiree/rt/hal.h
index beee3b1..3b18cb2 100644
--- a/bindings/python/pyiree/rt/hal.h
+++ b/bindings/python/pyiree/rt/hal.h
@@ -92,18 +92,6 @@
 
 class HalBuffer : public ApiRefCounted<HalBuffer, iree_hal_buffer_t> {
  public:
-  static HalBuffer AllocateHeapBuffer(int32_t memory_type, int32_t usage,
-                                      iree_host_size_t allocation_size) {
-    iree_hal_buffer_t* buffer = nullptr;
-    CheckApiStatus(
-        iree_hal_heap_buffer_allocate(
-            static_cast<iree_hal_memory_type_t>(memory_type),
-            static_cast<iree_hal_buffer_usage_t>(usage), allocation_size,
-            iree_allocator_system(), iree_allocator_system(), &buffer),
-        "Error allocating heap buffer");
-    return HalBuffer::CreateRetained(buffer);
-  }
-
   iree_device_size_t byte_length() const {
     return iree_hal_buffer_byte_length(raw_ptr());
   }
diff --git a/bindings/python/pyiree/rt/hal_test.py b/bindings/python/pyiree/rt/hal_test.py
index 12c0460..cd83026 100644
--- a/bindings/python/pyiree/rt/hal_test.py
+++ b/bindings/python/pyiree/rt/hal_test.py
@@ -25,27 +25,6 @@
     logging.info("MemoryType: %s", rt.MemoryType)
     logging.info("HOST_VISIBLE: %s", int(rt.MemoryType.HOST_VISIBLE))
 
-  def testAllocateHeap(self):
-    b = rt.HalBuffer.allocate_heap(memory_type=int(rt.MemoryType.HOST_LOCAL),
-                                   usage=int(rt.BufferUsage.ALL),
-                                   allocation_size=4096)
-    self.assertIsNot(b, None)
-    b.fill_zero(0, 4096)
-    shape = rt.Shape([1, 1024])
-    unused_bv = b.create_view(shape, 4)
-
-  def testStrideCalculation(self):
-    b = rt.HalBuffer.allocate_heap(memory_type=int(rt.MemoryType.HOST_LOCAL),
-                                   usage=int(rt.BufferUsage.ALL),
-                                   allocation_size=4096)
-    self.assertIsNot(b, None)
-    b.fill_zero(0, 4096)
-    shape = rt.Shape([16, 1, 8, 4, 2])
-    bv = b.create_view(shape, 4)
-    self.assertEqual(
-        np.array(bv.map()).strides,
-        (1 * 8 * 4 * 2 * 4, 8 * 4 * 2 * 4, 4 * 2 * 4, 2 * 4, 4))
-
 
 if __name__ == "__main__":
   absltest.main()
diff --git a/iree/hal/BUILD b/iree/hal/BUILD
index 367ed3e..c1939be 100644
--- a/iree/hal/BUILD
+++ b/iree/hal/BUILD
@@ -40,7 +40,6 @@
     visibility = ["//visibility:public"],
     deps = [
         ":hal",
-        ":heap_buffer",
         "//iree/base:api",
         "//iree/base:core_headers",
         "//iree/base:ref_ptr",
@@ -80,8 +79,6 @@
         "allocator.cc",
         "buffer.cc",
         "command_buffer.cc",
-        "deferred_buffer.cc",
-        "executable_cache.cc",
     ],
     hdrs = [
         "allocator.h",
@@ -89,22 +86,18 @@
         "command_buffer.h",
         "command_queue.h",
         "debug_capture_manager.h",
-        "deferred_buffer.h",
         "descriptor_set.h",
         "descriptor_set_layout.h",
         "device.h",
         "device_info.h",
-        "device_placement.h",
         "driver.h",
         "event.h",
         "executable.h",
         "executable_cache.h",
         "executable_format.h",
         "executable_layout.h",
-        "executable_spec.h",
         "resource.h",
         "semaphore.h",
-        "stack_trace.h",
     ],
     deps = [
         "//iree/base:core_headers",
@@ -126,7 +119,6 @@
     ],
     deps = [
         ":hal",
-        ":heap_buffer",
         "//iree/base:status",
         "//iree/testing:gtest",
         "//iree/testing:gtest_main",
@@ -134,19 +126,6 @@
     ],
 )
 
-cc_test(
-    name = "deferred_buffer_test",
-    srcs = ["deferred_buffer_test.cc"],
-    deps = [
-        ":hal",
-        ":heap_buffer",
-        "//iree/hal/testing:mock_allocator",
-        "//iree/testing:gtest",
-        "//iree/testing:gtest_main",
-        "@com_google_absl//absl/memory",
-    ],
-)
-
 #===------------------------------------------------------------------------===#
 # Debugging utilities and tools
 #===------------------------------------------------------------------------===#
@@ -162,39 +141,3 @@
         "@com_google_absl//absl/strings",
     ],
 )
-
-#===------------------------------------------------------------------------===#
-# Internal device management and driver registry
-#===------------------------------------------------------------------------===#
-# TODO(benvanik): port these to C and merge into main API.
-
-cc_library(
-    name = "device_manager",
-    srcs = ["device_manager.cc"],
-    hdrs = ["device_manager.h"],
-    deps = [
-        ":hal",
-        ":heap_buffer",
-        "//iree/base:status",
-        "//iree/base:time",
-        "//iree/base:tracing",
-        "@com_google_absl//absl/synchronization",
-        "@com_google_absl//absl/types:span",
-    ],
-)
-
-#===------------------------------------------------------------------------===#
-# Internal implementation details
-#===------------------------------------------------------------------------===#
-
-cc_library(
-    name = "heap_buffer",
-    srcs = ["heap_buffer.cc"],
-    hdrs = ["heap_buffer.h"],
-    deps = [
-        ":hal",
-        "//iree/base:status",
-        "//iree/base:tracing",
-        "//iree/hal/host:host_buffer",
-    ],
-)
diff --git a/iree/hal/CMakeLists.txt b/iree/hal/CMakeLists.txt
index 438ce0f..990fb31 100644
--- a/iree/hal/CMakeLists.txt
+++ b/iree/hal/CMakeLists.txt
@@ -25,7 +25,6 @@
     "api.cc"
   DEPS
     ::hal
-    ::heap_buffer
     absl::inlined_vector
     absl::span
     absl::strings
@@ -63,28 +62,22 @@
     "command_buffer.h"
     "command_queue.h"
     "debug_capture_manager.h"
-    "deferred_buffer.h"
     "descriptor_set.h"
     "descriptor_set_layout.h"
     "device.h"
     "device_info.h"
-    "device_placement.h"
     "driver.h"
     "event.h"
     "executable.h"
     "executable_cache.h"
     "executable_format.h"
     "executable_layout.h"
-    "executable_spec.h"
     "resource.h"
     "semaphore.h"
-    "stack_trace.h"
   SRCS
     "allocator.cc"
     "buffer.cc"
     "command_buffer.cc"
-    "deferred_buffer.cc"
-    "executable_cache.cc"
   DEPS
     absl::span
     absl::strings
@@ -105,27 +98,12 @@
     "buffer_test.cc"
   DEPS
     ::hal
-    ::heap_buffer
     absl::span
     iree::base::status
     iree::testing::gtest
     iree::testing::gtest_main
 )
 
-iree_cc_test(
-  NAME
-    deferred_buffer_test
-  SRCS
-    "deferred_buffer_test.cc"
-  DEPS
-    ::hal
-    ::heap_buffer
-    absl::memory
-    iree::hal::testing::mock_allocator
-    iree::testing::gtest
-    iree::testing::gtest_main
-)
-
 iree_cc_library(
   NAME
     command_buffer_validation
@@ -140,36 +118,3 @@
     iree::base::status
   PUBLIC
 )
-
-iree_cc_library(
-  NAME
-    device_manager
-  HDRS
-    "device_manager.h"
-  SRCS
-    "device_manager.cc"
-  DEPS
-    ::hal
-    ::heap_buffer
-    absl::span
-    absl::synchronization
-    iree::base::status
-    iree::base::time
-    iree::base::tracing
-  PUBLIC
-)
-
-iree_cc_library(
-  NAME
-    heap_buffer
-  HDRS
-    "heap_buffer.h"
-  SRCS
-    "heap_buffer.cc"
-  DEPS
-    ::hal
-    iree::base::status
-    iree::base::tracing
-    iree::hal::host::host_buffer
-  PUBLIC
-)
diff --git a/iree/hal/allocator.cc b/iree/hal/allocator.cc
index af219b3..2a7af8d 100644
--- a/iree/hal/allocator.cc
+++ b/iree/hal/allocator.cc
@@ -31,33 +31,6 @@
                           buffer->usage(), intended_usage);
 }
 
-StatusOr<ref_ptr<Buffer>> Allocator::AllocateConstant(
-    BufferUsageBitfield buffer_usage, ref_ptr<Buffer> source_buffer) {
-  if (AnyBitSet(source_buffer->usage() & BufferUsage::kConstant) &&
-      CanUseBuffer(source_buffer.get(), buffer_usage)) {
-    // Buffer can be used directly by the device.
-    return source_buffer;
-  }
-
-  IREE_TRACE_SCOPE0("Allocator::AllocateConstant");
-
-  // We need to map so we can copy into it.
-  buffer_usage |= BufferUsage::kMapping;
-  // It will be constant after we write it.
-  buffer_usage |= BufferUsage::kConstant;
-
-  MemoryTypeBitfield memory_type =
-      MemoryType::kDeviceLocal | MemoryType::kHostVisible;
-  IREE_ASSIGN_OR_RETURN(
-      auto device_buffer,
-      Allocate(memory_type, buffer_usage, source_buffer->byte_length()));
-  IREE_ASSIGN_OR_RETURN(auto source_mapping,
-                        source_buffer->MapMemory<uint8_t>(MemoryAccess::kRead));
-  IREE_RETURN_IF_ERROR(device_buffer->WriteData(0, source_mapping.data(),
-                                                source_mapping.byte_length()));
-  return device_buffer;
-}
-
 StatusOr<ref_ptr<Buffer>> Allocator::Wrap(MemoryTypeBitfield memory_type,
                                           BufferUsageBitfield buffer_usage,
                                           const void* data,
diff --git a/iree/hal/allocator.h b/iree/hal/allocator.h
index 11f65ec..8781561 100644
--- a/iree/hal/allocator.h
+++ b/iree/hal/allocator.h
@@ -78,12 +78,6 @@
                                              BufferUsageBitfield buffer_usage,
                                              size_t allocation_size) = 0;
 
-  // Allocates a buffer from the allocator for use as a constant value.
-  // The provided |source_buffer| may be returned if the device can use it
-  // directly and otherwise will be copied.
-  virtual StatusOr<ref_ptr<Buffer>> AllocateConstant(
-      BufferUsageBitfield buffer_usage, ref_ptr<Buffer> source_buffer);
-
   // Wraps an existing host heap allocation in a buffer.
   // Ownership of the host allocation remains with the caller and the memory
   // must remain valid for so long as the Buffer may be in use.
diff --git a/iree/hal/api.cc b/iree/hal/api.cc
index 65b310f..362e94d 100644
--- a/iree/hal/api.cc
+++ b/iree/hal/api.cc
@@ -35,7 +35,6 @@
 #include "iree/hal/command_buffer.h"
 #include "iree/hal/device.h"
 #include "iree/hal/driver.h"
-#include "iree/hal/heap_buffer.h"
 #include "iree/hal/host/host_local_allocator.h"
 #include "iree/hal/semaphore.h"
 #include "third_party/half/half.hpp"
@@ -935,81 +934,6 @@
 }
 
 //===----------------------------------------------------------------------===//
-// iree::hal::HeapBuffer
-//===----------------------------------------------------------------------===//
-
-IREE_API_EXPORT iree_status_t IREE_API_CALL iree_hal_heap_buffer_allocate(
-    iree_hal_memory_type_t memory_type, iree_hal_buffer_usage_t usage,
-    iree_host_size_t allocation_size, iree_allocator_t contents_allocator,
-    iree_allocator_t allocator, iree_hal_buffer_t** out_buffer) {
-  IREE_TRACE_SCOPE0("iree_hal_heap_buffer_allocate");
-  IREE_ASSERT_ARGUMENT(out_buffer);
-  *out_buffer = nullptr;
-
-  if (!allocation_size) {
-    return iree_make_status(IREE_STATUS_INVALID_ARGUMENT,
-                            "allocation size must be >= 0");
-  }
-
-  auto handle = HeapBuffer::Allocate(
-      static_cast<MemoryTypeBitfield>(memory_type),
-      static_cast<BufferUsageBitfield>(usage), allocation_size);
-
-  *out_buffer = reinterpret_cast<iree_hal_buffer_t*>(
-      static_cast<Buffer*>(handle.release()));
-
-  return iree_ok_status();
-}
-
-IREE_API_EXPORT iree_status_t IREE_API_CALL iree_hal_heap_buffer_allocate_copy(
-    iree_hal_memory_type_t memory_type, iree_hal_buffer_usage_t usage,
-    iree_hal_memory_access_t allowed_access, iree_byte_span_t contents,
-    iree_allocator_t contents_allocator, iree_allocator_t allocator,
-    iree_hal_buffer_t** out_buffer) {
-  IREE_TRACE_SCOPE0("iree_hal_heap_buffer_allocate_copy");
-  IREE_ASSERT_ARGUMENT(out_buffer);
-
-  *out_buffer = nullptr;
-
-  if (!contents.data || !contents.data_length) {
-    return iree_make_status(IREE_STATUS_INVALID_ARGUMENT,
-                            "no contents specified (0 length)");
-  }
-
-  auto handle = HeapBuffer::AllocateCopy(
-      static_cast<BufferUsageBitfield>(usage),
-      static_cast<MemoryAccessBitfield>(allowed_access), contents.data,
-      contents.data_length);
-
-  *out_buffer = reinterpret_cast<iree_hal_buffer_t*>(handle.release());
-  return iree_ok_status();
-}
-
-IREE_API_EXPORT iree_status_t IREE_API_CALL iree_hal_heap_buffer_wrap(
-    iree_hal_memory_type_t memory_type, iree_hal_memory_access_t allowed_access,
-    iree_hal_buffer_usage_t usage, iree_byte_span_t contents,
-    iree_allocator_t allocator, iree_hal_buffer_t** out_buffer) {
-  IREE_TRACE_SCOPE0("iree_hal_heap_buffer_wrap");
-  IREE_ASSERT_ARGUMENT(out_buffer);
-
-  *out_buffer = nullptr;
-
-  if (!contents.data || !contents.data_length) {
-    return iree_make_status(IREE_STATUS_INVALID_ARGUMENT,
-                            "no contents specified (0 length)");
-  }
-
-  auto handle =
-      HeapBuffer::WrapMutable(static_cast<MemoryTypeBitfield>(memory_type),
-                              static_cast<MemoryAccessBitfield>(allowed_access),
-                              static_cast<BufferUsageBitfield>(usage),
-                              contents.data, contents.data_length);
-
-  *out_buffer = reinterpret_cast<iree_hal_buffer_t*>(handle.release());
-  return iree_ok_status();
-}
-
-//===----------------------------------------------------------------------===//
 // iree::hal::BufferView
 //===----------------------------------------------------------------------===//
 
@@ -1923,13 +1847,11 @@
   *out_executable = nullptr;
   auto* handle = reinterpret_cast<ExecutableCache*>(executable_cache);
 
-  ExecutableSpec spec;
-  spec.executable_data = {executable_data.data, executable_data.data_length};
   IREE_ASSIGN_OR_RETURN(
       auto executable,
       handle->PrepareExecutable(
           reinterpret_cast<ExecutableLayout*>(executable_layout),
-          static_cast<ExecutableCachingMode>(caching_mode), spec));
+          static_cast<ExecutableCachingMode>(caching_mode), executable_data));
 
   *out_executable =
       reinterpret_cast<iree_hal_executable_t*>(executable.release());
diff --git a/iree/hal/api.h b/iree/hal/api.h
index a943100..1ccf29e 100644
--- a/iree/hal/api.h
+++ b/iree/hal/api.h
@@ -768,52 +768,6 @@
     iree_hal_buffer_t* buffer, iree_hal_mapped_memory_t* mapped_memory);
 
 //===----------------------------------------------------------------------===//
-// iree::hal::HeapBuffer
-//===----------------------------------------------------------------------===//
-
-// Allocates a zeroed host heap buffer of the given size.
-// The buffer contents will be allocated with |contents_allocator| while
-// |allocator| is used for the iree_hal_buffer_t.
-//
-// Returns a buffer allocated with malloc that may not be usable by devices
-// without copies. |memory_type| should be set to
-// IREE_HAL_MEMORY_TYPE_HOST_LOCAL in most cases.
-// |out_buffer| must be released by the caller.
-IREE_API_EXPORT iree_status_t IREE_API_CALL iree_hal_heap_buffer_allocate(
-    iree_hal_memory_type_t memory_type, iree_hal_buffer_usage_t usage,
-    iree_host_size_t allocation_size, iree_allocator_t contents_allocator,
-    iree_allocator_t allocator, iree_hal_buffer_t** out_buffer);
-
-// Allocates a host heap buffer with a copy of the given data.
-// The buffer contents will be allocated with |contents_allocator| while
-// |allocator| is used for the iree_hal_buffer_t.
-//
-// Returns a buffer allocated with malloc that may not be usable by devices
-// without copies. |memory_type| should be set to
-// IREE_HAL_MEMORY_TYPE_HOST_LOCAL in most cases.
-// |out_buffer| must be released by the caller.
-IREE_API_EXPORT iree_status_t IREE_API_CALL iree_hal_heap_buffer_allocate_copy(
-    iree_hal_memory_type_t memory_type, iree_hal_buffer_usage_t usage,
-    iree_hal_memory_access_t allowed_access, iree_byte_span_t contents,
-    iree_allocator_t contents_allocator, iree_allocator_t allocator,
-    iree_hal_buffer_t** out_buffer);
-
-// Wraps an existing host heap allocation in a buffer.
-// Ownership of the host allocation remains with the caller and the memory
-// must remain valid for so long as the iree_hal_buffer_t may be in use.
-//
-// Returns a buffer allocated with malloc that may not be usable by devices
-// without copies. |memory_type| should be set to
-// IREE_HAL_MEMORY_TYPE_HOST_LOCAL in most cases.
-// |out_buffer| must be released by the caller.
-IREE_API_EXPORT iree_status_t IREE_API_CALL iree_hal_heap_buffer_wrap(
-    iree_hal_memory_type_t memory_type, iree_hal_memory_access_t allowed_access,
-    iree_hal_buffer_usage_t usage, iree_byte_span_t contents,
-    iree_allocator_t allocator, iree_hal_buffer_t** out_buffer);
-
-// TODO(benvanik): add a wrap that takes an allocator just for the buffer.
-
-//===----------------------------------------------------------------------===//
 // iree::hal::BufferView
 //===----------------------------------------------------------------------===//
 
diff --git a/iree/hal/buffer_test.cc b/iree/hal/buffer_test.cc
index bf58539..d509cc7 100644
--- a/iree/hal/buffer_test.cc
+++ b/iree/hal/buffer_test.cc
@@ -20,10 +20,11 @@
 
 #include <vector>
 
-#include "iree/hal/heap_buffer.h"
 #include "iree/testing/gtest.h"
 #include "iree/testing/status_matchers.h"
 
+#if 0  // DISABLED: this will have changes in future commits in this branch.
+
 namespace iree {
 namespace hal {
 namespace {
@@ -1011,3 +1012,5 @@
 }  // namespace
 }  // namespace hal
 }  // namespace iree
+
+#endif  // 0
diff --git a/iree/hal/deferred_buffer.cc b/iree/hal/deferred_buffer.cc
deleted file mode 100644
index 07b6894..0000000
--- a/iree/hal/deferred_buffer.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// 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.
-
-#include "iree/hal/deferred_buffer.h"
-
-#include "iree/base/status.h"
-
-namespace iree {
-namespace hal {
-
-DeferredBuffer::DeferredBuffer(Allocator* allocator,
-                               MemoryTypeBitfield memory_type,
-                               MemoryAccessBitfield allowed_access,
-                               BufferUsageBitfield usage,
-                               device_size_t byte_length)
-    : Buffer(allocator, memory_type, allowed_access, usage, 0, 0, byte_length) {
-}
-
-DeferredBuffer::~DeferredBuffer() = default;
-
-Status DeferredBuffer::GrowByteLength(device_size_t new_byte_length) {
-  if (parent_buffer_) {
-    return FailedPreconditionErrorBuilder(IREE_LOC)
-           << "Attempting to set min allocation size while bound to an "
-              "allocation";
-  }
-  if (byte_length_ != kWholeBuffer && new_byte_length < byte_length_) {
-    return InvalidArgumentErrorBuilder(IREE_LOC)
-           << "Attempting to shrink a buffer to " << new_byte_length
-           << " when it has a minimum size of " << byte_length_;
-  }
-  byte_length_ = new_byte_length;
-  return OkStatus();
-}
-
-Status DeferredBuffer::BindAllocation(ref_ptr<Buffer> allocated_buffer,
-                                      device_size_t byte_offset,
-                                      device_size_t byte_length) {
-  // We can only be bound to allocations that are compatible with our specified
-  // allocator and usage.
-  if (!allocator_->CanUseBuffer(allocated_buffer.get(), usage())) {
-    return InvalidArgumentErrorBuilder(IREE_LOC)
-           << "Allocation is not compatible with the allocator specified for "
-              "the deferred buffer";
-  }
-
-  // Calculate the range in the allocated_buffer that we are interested in.
-  IREE_RETURN_IF_ERROR(
-      Buffer::CalculateRange(0, allocated_buffer->byte_length(), byte_offset,
-                             byte_length, &byte_offset, &byte_length));
-
-  // Verify that we have enough bytes for what we've promised.
-  if (byte_length < byte_length_) {
-    return OutOfRangeErrorBuilder(IREE_LOC)
-           << "Allocation range is too small; min_allocation_size="
-           << byte_length_ << " but the range of " << byte_offset << "-"
-           << (byte_offset + byte_length - 1) << " (" << byte_length
-           << "b) is too small";
-  }
-
-  allocated_buffer_ = allocated_buffer.get();
-  parent_buffer_ = std::move(allocated_buffer);
-  byte_offset_ = byte_offset;
-  return OkStatus();
-}
-
-void DeferredBuffer::ResetAllocation() {
-  allocated_buffer_ = this;
-  parent_buffer_.reset();
-  byte_offset_ = 0;
-}
-
-StatusOr<Buffer*> DeferredBuffer::ResolveAllocation() const {
-  // If you get errors here then someone allocated the buffer with
-  // MemoryType::kTransient and you are trying to use it outside of the time
-  // it is actually allocated (such as during CommandBuffer evaluation). If
-  // you need to use the buffer in non-transient ways then allocate the buffer
-  // without the MemoryType::kTransient flag.
-  if (!parent_buffer_) {
-    return FailedPreconditionErrorBuilder(IREE_LOC)
-           << "Attempting to use a transient buffer prior to allocation: "
-           << DebugString();
-  }
-  return parent_buffer_.get();
-}
-
-Status DeferredBuffer::FillImpl(device_size_t byte_offset,
-                                device_size_t byte_length, const void* pattern,
-                                device_size_t pattern_length) {
-  IREE_ASSIGN_OR_RETURN(auto* allocated_buffer, ResolveAllocation());
-  return allocated_buffer->FillImpl(byte_offset, byte_length, pattern,
-                                    pattern_length);
-}
-
-Status DeferredBuffer::ReadDataImpl(device_size_t source_offset, void* data,
-                                    device_size_t data_length) {
-  IREE_ASSIGN_OR_RETURN(auto* allocated_buffer, ResolveAllocation());
-  return allocated_buffer->ReadDataImpl(source_offset, data, data_length);
-}
-
-Status DeferredBuffer::WriteDataImpl(device_size_t target_offset,
-                                     const void* data,
-                                     device_size_t data_length) {
-  IREE_ASSIGN_OR_RETURN(auto* allocated_buffer, ResolveAllocation());
-  return allocated_buffer->WriteDataImpl(target_offset, data, data_length);
-}
-
-Status DeferredBuffer::CopyDataImpl(device_size_t target_offset,
-                                    Buffer* source_buffer,
-                                    device_size_t source_offset,
-                                    device_size_t data_length) {
-  IREE_ASSIGN_OR_RETURN(auto* allocated_buffer, ResolveAllocation());
-  return allocated_buffer->CopyDataImpl(target_offset, source_buffer,
-                                        source_offset, data_length);
-}
-
-Status DeferredBuffer::MapMemoryImpl(MappingMode mapping_mode,
-                                     MemoryAccessBitfield memory_access,
-                                     device_size_t local_byte_offset,
-                                     device_size_t local_byte_length,
-                                     void** out_data) {
-  IREE_ASSIGN_OR_RETURN(auto* allocated_buffer, ResolveAllocation());
-  return allocated_buffer->MapMemoryImpl(mapping_mode, memory_access,
-                                         local_byte_offset, local_byte_length,
-                                         out_data);
-}
-
-Status DeferredBuffer::UnmapMemoryImpl(device_size_t local_byte_offset,
-                                       device_size_t local_byte_length,
-                                       void* data) {
-  IREE_ASSIGN_OR_RETURN(auto* allocated_buffer, ResolveAllocation());
-  return allocated_buffer->UnmapMemoryImpl(local_byte_offset, local_byte_length,
-                                           data);
-}
-
-Status DeferredBuffer::InvalidateMappedMemoryImpl(
-    device_size_t local_byte_offset, device_size_t local_byte_length) {
-  IREE_ASSIGN_OR_RETURN(auto* allocated_buffer, ResolveAllocation());
-  return allocated_buffer->InvalidateMappedMemoryImpl(local_byte_offset,
-                                                      local_byte_length);
-}
-
-Status DeferredBuffer::FlushMappedMemoryImpl(device_size_t local_byte_offset,
-                                             device_size_t local_byte_length) {
-  IREE_ASSIGN_OR_RETURN(auto* allocated_buffer, ResolveAllocation());
-  return allocated_buffer->FlushMappedMemoryImpl(local_byte_offset,
-                                                 local_byte_length);
-}
-
-}  // namespace hal
-}  // namespace iree
diff --git a/iree/hal/deferred_buffer.h b/iree/hal/deferred_buffer.h
deleted file mode 100644
index e378541..0000000
--- a/iree/hal/deferred_buffer.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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.
-
-#ifndef IREE_HAL_DEFERRED_BUFFER_H_
-#define IREE_HAL_DEFERRED_BUFFER_H_
-
-#include <cstddef>
-#include <memory>
-#include <utility>
-
-#include "iree/base/status.h"
-#include "iree/hal/allocator.h"
-#include "iree/hal/buffer.h"
-
-namespace iree {
-namespace hal {
-
-// A Buffer that can have its underlying allocation changed at runtime.
-// Unbound buffers act as a way to logically group dependent ranges of memory
-// without needing to have allocated that memory yet.
-//
-// Usage:
-//  // Setup two spans referencing ranges of a deferred buffer.
-//  auto deferred_buffer = make_ref<DeferredBuffer>(..., 200);
-//  IREE_ASSIGN_OR_RETURN(auto span0, Buffer::Subspan(deferred_buffer, 0, 100));
-//  IREE_ASSIGN_OR_RETURN(auto span1, Buffer::Subspan(deferred_buffer, 100,
-//  100));
-//
-//  // Attempting to access |deferred_buffer| or |span0| or |span1| will fail.
-//  // ERROR: span0->Fill(false);
-//
-//  // Now allocate a real buffer to serve as storage for the data.
-//  IREE_ASSIGN_OR_RETURN(auto allocated_buffer, Buffer::Allocate(..., 200));
-//  IREE_RETURN_IF_ERROR(deferred_buffer->BindAllocation(
-//      allocated_buffer, 0, kWholeBuffer));
-//
-//  // And now we can use the spans.
-//  IREE_RETURN_IF_ERROR(span0->Fill(false));
-//
-//  // If at some point we want to detach the buffer from the allocation (so we
-//  // can use a different allocation, reuse the memory, etc).
-//  deferred_buffer->ResetAllocation();
-//
-// Thread-compatible. Attempting to rebind the allocation while other threads
-// are using the buffer will lead to undefined behavior.
-class DeferredBuffer : public Buffer {
- public:
-  DeferredBuffer(Allocator* allocator, MemoryTypeBitfield memory_type,
-                 MemoryAccessBitfield allowed_access, BufferUsageBitfield usage,
-                 device_size_t byte_length);
-  ~DeferredBuffer() override;
-
-  // Grows the minimum allocation size of the buffer to |new_byte_length|.
-  // Attempting to bind an allocation less than this size will fail. This must
-  // only be called when the buffer is not bound to an allocation.
-  Status GrowByteLength(device_size_t new_byte_length);
-
-  // Binds or rebinds the deferred buffer to an allocated buffer.
-  Status BindAllocation(ref_ptr<Buffer> allocated_buffer,
-                        device_size_t byte_offset, device_size_t byte_length);
-
-  // Resets the deferred buffer to have no binding.
-  void ResetAllocation();
-
- private:
-  // Resolves the allocated buffer that this subspan references into.
-  // This will fail if the buffer has not yet been bound to an allocation or
-  // the allocated buffer has not been committed.
-  StatusOr<Buffer*> ResolveAllocation() const;
-
-  Status FillImpl(device_size_t byte_offset, device_size_t byte_length,
-                  const void* pattern, device_size_t pattern_length) override;
-  Status ReadDataImpl(device_size_t source_offset, void* data,
-                      device_size_t data_length) override;
-  Status WriteDataImpl(device_size_t target_offset, const void* data,
-                       device_size_t data_length) override;
-  Status CopyDataImpl(device_size_t target_offset, Buffer* source_buffer,
-                      device_size_t source_offset,
-                      device_size_t data_length) override;
-  Status MapMemoryImpl(MappingMode mapping_mode,
-                       MemoryAccessBitfield memory_access,
-                       device_size_t local_byte_offset,
-                       device_size_t local_byte_length,
-                       void** out_data) override;
-  Status UnmapMemoryImpl(device_size_t local_byte_offset,
-                         device_size_t local_byte_length, void* data) override;
-  Status InvalidateMappedMemoryImpl(device_size_t local_byte_offset,
-                                    device_size_t local_byte_length) override;
-  Status FlushMappedMemoryImpl(device_size_t local_byte_offset,
-                               device_size_t local_byte_length) override;
-};
-
-}  // namespace hal
-}  // namespace iree
-
-#endif  // IREE_HAL_DEFERRED_BUFFER_H_
diff --git a/iree/hal/deferred_buffer_test.cc b/iree/hal/deferred_buffer_test.cc
deleted file mode 100644
index 454fe2d..0000000
--- a/iree/hal/deferred_buffer_test.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-// 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.
-
-#include "iree/hal/deferred_buffer.h"
-
-#include "absl/memory/memory.h"
-#include "iree/hal/heap_buffer.h"
-#include "iree/hal/testing/mock_allocator.h"
-#include "iree/testing/gtest.h"
-#include "iree/testing/status_matchers.h"
-
-namespace iree {
-namespace hal {
-namespace {
-
-using ::iree::hal::testing::MockAllocator;
-using ::testing::_;
-using ::testing::Return;
-
-// Tests properties of unbound buffers.
-TEST(DeferredBufferTest, Unbound) {
-  MockAllocator allocator;
-  auto deferred_buffer = absl::make_unique<DeferredBuffer>(
-      &allocator, MemoryType::kHostLocal, MemoryAccess::kAll, BufferUsage::kAll,
-      100);
-  EXPECT_EQ(&allocator, deferred_buffer->allocator());
-  EXPECT_EQ(deferred_buffer.get(), deferred_buffer->allocated_buffer());
-  EXPECT_EQ(0, deferred_buffer->allocation_size());
-  EXPECT_EQ(0, deferred_buffer->byte_offset());
-  EXPECT_EQ(100, deferred_buffer->byte_length());
-}
-
-// Tests that binding verifies allocators are compatible.
-TEST(DeferredBufferTest, AllocatorCheck) {
-  MockAllocator allocator;
-  auto deferred_buffer = absl::make_unique<DeferredBuffer>(
-      &allocator, MemoryType::kHostLocal, MemoryAccess::kAll, BufferUsage::kAll,
-      100);
-  auto real_buffer =
-      HeapBuffer::Allocate(MemoryType::kHostLocal, BufferUsage::kAll, 256);
-  EXPECT_CALL(
-      allocator,
-      CanUseBufferLike(real_buffer->allocator(), real_buffer->memory_type(),
-                       real_buffer->usage(), BufferUsage::kAll))
-      .WillOnce(Return(false));
-  EXPECT_TRUE(IsInvalidArgument(
-      deferred_buffer->BindAllocation(std::move(real_buffer), 0, 100)));
-}
-
-// Tests that binding verifies allocation sizes.
-TEST(DeferredBufferTest, SizeCheck) {
-  MockAllocator allocator;
-  auto deferred_buffer = absl::make_unique<DeferredBuffer>(
-      &allocator, MemoryType::kHostLocal, MemoryAccess::kAll, BufferUsage::kAll,
-      100);
-  auto real_buffer =
-      HeapBuffer::Allocate(MemoryType::kHostLocal, BufferUsage::kAll, 256);
-  EXPECT_CALL(allocator, CanUseBufferLike(_, _, _, _))
-      .WillRepeatedly(Return(true));
-
-  IREE_EXPECT_OK(
-      deferred_buffer->BindAllocation(add_ref(real_buffer), 10, 100));
-  EXPECT_EQ(256, deferred_buffer->allocation_size());
-  EXPECT_EQ(10, deferred_buffer->byte_offset());
-  EXPECT_EQ(100, deferred_buffer->byte_length());
-  IREE_EXPECT_OK(
-      deferred_buffer->BindAllocation(add_ref(real_buffer), 10, kWholeBuffer));
-  EXPECT_EQ(256, deferred_buffer->allocation_size());
-  EXPECT_EQ(10, deferred_buffer->byte_offset());
-  EXPECT_EQ(100, deferred_buffer->byte_length());
-
-  EXPECT_TRUE(IsOutOfRange(
-      deferred_buffer->BindAllocation(add_ref(real_buffer), 200, 100)));
-  EXPECT_TRUE(IsOutOfRange(deferred_buffer->BindAllocation(add_ref(real_buffer),
-                                                           200, kWholeBuffer)));
-  EXPECT_TRUE(IsOutOfRange(
-      deferred_buffer->BindAllocation(add_ref(real_buffer), 10, 10)));
-}
-
-// Tests resizing buffers after they have been allocated.
-TEST(DeferredBufferTest, Resizing) {
-  MockAllocator allocator;
-  auto deferred_buffer = absl::make_unique<DeferredBuffer>(
-      &allocator, MemoryType::kHostLocal, MemoryAccess::kAll, BufferUsage::kAll,
-      100);
-  auto real_buffer =
-      HeapBuffer::Allocate(MemoryType::kHostLocal, BufferUsage::kAll, 256);
-  EXPECT_CALL(allocator, CanUseBufferLike(_, _, _, _))
-      .WillRepeatedly(Return(true));
-
-  // Grow.
-  EXPECT_EQ(100, deferred_buffer->byte_length());
-  IREE_EXPECT_OK(deferred_buffer->GrowByteLength(150));
-  EXPECT_EQ(150, deferred_buffer->byte_length());
-
-  // Shrinking should fail.
-  EXPECT_TRUE(IsInvalidArgument(deferred_buffer->GrowByteLength(5)));
-
-  // Growing should fail if bound.
-  IREE_EXPECT_OK(
-      deferred_buffer->BindAllocation(std::move(real_buffer), 0, 150));
-  EXPECT_TRUE(IsFailedPrecondition(deferred_buffer->GrowByteLength(100)));
-}
-
-// Tests binding and rebinding behavior.
-TEST(DeferredBufferTest, Rebinding) {
-  MockAllocator allocator;
-  auto deferred_buffer = absl::make_unique<DeferredBuffer>(
-      &allocator, MemoryType::kHostLocal, MemoryAccess::kAll, BufferUsage::kAll,
-      100);
-  auto real_buffer =
-      HeapBuffer::Allocate(MemoryType::kHostLocal, BufferUsage::kAll, 256);
-  EXPECT_CALL(allocator, CanUseBufferLike(_, _, _, _))
-      .WillRepeatedly(Return(true));
-
-  // Safe to reset when not bound.
-  deferred_buffer->ResetAllocation();
-  EXPECT_EQ(deferred_buffer.get(), deferred_buffer->allocated_buffer());
-  EXPECT_EQ(0, deferred_buffer->allocation_size());
-
-  IREE_EXPECT_OK(deferred_buffer->BindAllocation(add_ref(real_buffer), 0, 100));
-  EXPECT_EQ(real_buffer.get(), deferred_buffer->allocated_buffer());
-  EXPECT_EQ(256, deferred_buffer->allocation_size());
-  deferred_buffer->ResetAllocation();
-  EXPECT_EQ(deferred_buffer.get(), deferred_buffer->allocated_buffer());
-  EXPECT_EQ(0, deferred_buffer->allocation_size());
-  IREE_EXPECT_OK(deferred_buffer->BindAllocation(add_ref(real_buffer), 0, 100));
-  EXPECT_EQ(real_buffer.get(), deferred_buffer->allocated_buffer());
-  EXPECT_EQ(256, deferred_buffer->allocation_size());
-}
-
-// Tests normal usage of bound buffers.
-TEST(DeferredBufferTest, BoundUsage) {
-  MockAllocator allocator;
-  auto deferred_buffer = absl::make_unique<DeferredBuffer>(
-      &allocator, MemoryType::kHostLocal, MemoryAccess::kAll, BufferUsage::kAll,
-      100);
-  auto real_buffer =
-      HeapBuffer::Allocate(MemoryType::kHostLocal, BufferUsage::kAll, 256);
-  EXPECT_CALL(allocator, CanUseBufferLike(_, _, _, _))
-      .WillRepeatedly(Return(true));
-  IREE_EXPECT_OK(
-      deferred_buffer->BindAllocation(std::move(real_buffer), 0, 100));
-
-  EXPECT_FALSE(deferred_buffer->DebugString().empty());
-  EXPECT_FALSE(deferred_buffer->DebugStringShort().empty());
-
-  IREE_EXPECT_OK(deferred_buffer->Fill8(0, 10, 0xFF));
-}
-
-// Tests that unbound buffers fail to perform any buffer actions.
-TEST(DeferredBufferTest, UnboundUsage) {
-  MockAllocator allocator;
-  auto deferred_buffer = absl::make_unique<DeferredBuffer>(
-      &allocator, MemoryType::kHostLocal, MemoryAccess::kAll, BufferUsage::kAll,
-      100);
-  EXPECT_FALSE(deferred_buffer->DebugString().empty());
-  EXPECT_FALSE(deferred_buffer->DebugStringShort().empty());
-
-  EXPECT_TRUE(IsFailedPrecondition(deferred_buffer->Fill8(0, 10, 0xFF)));
-}
-
-}  // namespace
-}  // namespace hal
-}  // namespace iree
diff --git a/iree/hal/device_manager.cc b/iree/hal/device_manager.cc
deleted file mode 100644
index 5a527f3..0000000
--- a/iree/hal/device_manager.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-// 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.
-
-#include "iree/hal/device_manager.h"
-
-#include <algorithm>
-
-#include "iree/base/status.h"
-#include "iree/base/tracing.h"
-#include "iree/hal/heap_buffer.h"
-
-namespace iree {
-namespace hal {
-
-DeviceManager::DeviceManager() = default;
-
-DeviceManager::~DeviceManager() {
-  IREE_TRACE_SCOPE0("DeviceManager::dtor");
-  WaitIdle().IgnoreError();
-}
-
-Status DeviceManager::RegisterDevice(ref_ptr<Device> device) {
-  IREE_TRACE_SCOPE0("DeviceManager::RegisterDevice");
-  absl::MutexLock lock(&device_mutex_);
-  if (std::find(devices_.begin(), devices_.end(), device) != devices_.end()) {
-    return FailedPreconditionErrorBuilder(IREE_LOC)
-           << "Device already registered";
-  }
-  devices_.push_back(std::move(device));
-  return OkStatus();
-}
-
-Status DeviceManager::UnregisterDevice(Device* device) {
-  IREE_TRACE_SCOPE0("DeviceManager::UnregisterDevice");
-  absl::MutexLock lock(&device_mutex_);
-  auto it = std::find_if(devices_.begin(), devices_.end(),
-                         [device](const ref_ptr<Device>& other_device) {
-                           return device == other_device.get();
-                         });
-  if (it == devices_.end()) {
-    return NotFoundErrorBuilder(IREE_LOC) << "Device not registered";
-  }
-  devices_.erase(it);
-  return OkStatus();
-}
-
-StatusOr<DevicePlacement> DeviceManager::ResolvePlacement(
-    const PlacementSpec& placement_spec) const {
-  IREE_TRACE_SCOPE0("DeviceManager::ResolvePlacement");
-  absl::MutexLock lock(&device_mutex_);
-  if (devices_.empty()) {
-    return NotFoundErrorBuilder(IREE_LOC) << "No devices registered";
-  }
-
-  // TODO(benvanik): multiple devices and placement.
-  IREE_QCHECK_EQ(devices_.size(), 1)
-      << "Multiple devices not yet supported (need placement)";
-  DevicePlacement device_placement;
-  device_placement.device = devices_.front().get();
-
-  return device_placement;
-}
-
-StatusOr<Allocator*> DeviceManager::FindCompatibleAllocator(
-    MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
-    absl::Span<const DevicePlacement> device_placements) const {
-  IREE_TRACE_SCOPE0("DeviceManager::FindCompatibleAllocator");
-  if (device_placements.empty()) {
-    return InvalidArgumentErrorBuilder(IREE_LOC) << "No placements provided";
-  }
-
-  // Find the first allocator. As we only return an allocator if all placements
-  // are compatible we'll compare allocator[0] against allocator[1,N].
-  Allocator* some_allocator = nullptr;
-  for (const auto& device_placement : device_placements) {
-    auto* allocator = device_placement.device->allocator();
-    if (!some_allocator) {
-      some_allocator = allocator;
-      continue;
-    }
-    // NOTE: as there can be asymmetry between usage restrictions (A can use B
-    // but B cannot use A) we have to compare both directions.
-    if (!some_allocator->CanUseBufferLike(allocator, memory_type, buffer_usage,
-                                          buffer_usage) ||
-        !allocator->CanUseBufferLike(some_allocator, memory_type, buffer_usage,
-                                     buffer_usage)) {
-      // Allocators are not compatible.
-      return NotFoundErrorBuilder(IREE_LOC)
-             << "No single allocator found that is compatible with all "
-                "placements";
-    }
-  }
-  return some_allocator;
-}
-
-StatusOr<ref_ptr<Buffer>> DeviceManager::TryAllocateDeviceVisibleBuffer(
-    MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
-    device_size_t allocation_size,
-    absl::Span<const DevicePlacement> device_placements) {
-  IREE_TRACE_SCOPE0("DeviceManager::TryAllocateDeviceVisibleBuffer:size");
-  if (!AnyBitSet(memory_type & MemoryType::kHostLocal)) {
-    return InvalidArgumentErrorBuilder(IREE_LOC)
-           << "Host-local buffers require the kHostLocal bit: "
-           << MemoryTypeString(memory_type);
-  }
-
-  // Strip kDeviceVisible as we conditionally add it based on support.
-  memory_type &= ~MemoryType::kDeviceVisible;
-
-  // Find an allocator that works for device-visible buffers.
-  // If this fails we'll fall back to allocation a non-device-visible buffer.
-  auto allocator_or =
-      FindCompatibleAllocator(memory_type | MemoryType::kDeviceVisible,
-                              buffer_usage, device_placements);
-  if (allocator_or.ok()) {
-    return allocator_or.value()->Allocate(
-        memory_type | MemoryType::kDeviceVisible, buffer_usage,
-        allocation_size);
-  }
-
-  // Fallback to allocating a host-local buffer.
-  return HeapBuffer::Allocate(memory_type, buffer_usage, allocation_size);
-}
-
-StatusOr<ref_ptr<Buffer>> DeviceManager::AllocateDeviceVisibleBuffer(
-    MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
-    device_size_t allocation_size,
-    absl::Span<const DevicePlacement> device_placements) {
-  IREE_TRACE_SCOPE0("DeviceManager::AllocateDeviceVisibleBuffer:size");
-  if (!AnyBitSet(memory_type & MemoryType::kHostLocal)) {
-    return InvalidArgumentErrorBuilder(IREE_LOC)
-           << "Host-local buffers require the kHostLocal bit: "
-           << MemoryTypeString(memory_type);
-  }
-
-  // Always use device-visible.
-  memory_type |= MemoryType::kDeviceVisible;
-
-  // Find an allocator that works for device-visible buffers.
-  IREE_ASSIGN_OR_RETURN(
-      auto* allocator,
-      FindCompatibleAllocator(memory_type, buffer_usage, device_placements));
-  return allocator->Allocate(memory_type, buffer_usage, allocation_size);
-}
-
-StatusOr<ref_ptr<Buffer>> DeviceManager::AllocateDeviceLocalBuffer(
-    MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
-    device_size_t allocation_size,
-    absl::Span<const DevicePlacement> device_placements) {
-  IREE_TRACE_SCOPE0("DeviceManager::AllocateDeviceLocalBuffer:size");
-  if (!AnyBitSet(memory_type & MemoryType::kDeviceLocal)) {
-    return InvalidArgumentErrorBuilder(IREE_LOC)
-           << "Device-local buffers require the kDeviceLocal bit: "
-           << MemoryTypeString(memory_type);
-  }
-
-  // Find an allocator that works for device-local buffers.
-  IREE_ASSIGN_OR_RETURN(
-      auto* allocator,
-      FindCompatibleAllocator(memory_type, buffer_usage, device_placements));
-  return allocator->Allocate(memory_type, buffer_usage, allocation_size);
-}
-
-Status DeviceManager::Submit(Device* device, CommandQueue* command_queue,
-                             absl::Span<const SubmissionBatch> batches,
-                             Time deadline_ns) {
-  IREE_TRACE_SCOPE0("DeviceManager::Submit");
-  return command_queue->Submit(batches);
-}
-
-Status DeviceManager::Flush() {
-  IREE_TRACE_SCOPE0("DeviceManager::Flush");
-  return OkStatus();
-}
-
-Status DeviceManager::WaitIdle(Time deadline_ns) {
-  IREE_TRACE_SCOPE0("DeviceManager::WaitIdle");
-  absl::MutexLock lock(&device_mutex_);
-  for (const auto& device : devices_) {
-    IREE_RETURN_IF_ERROR(device->WaitIdle(deadline_ns));
-  }
-  return OkStatus();
-}
-
-}  // namespace hal
-}  // namespace iree
diff --git a/iree/hal/device_manager.h b/iree/hal/device_manager.h
deleted file mode 100644
index 492b824..0000000
--- a/iree/hal/device_manager.h
+++ /dev/null
@@ -1,207 +0,0 @@
-// 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.
-
-#ifndef IREE_HAL_DEVICE_MANAGER_H_
-#define IREE_HAL_DEVICE_MANAGER_H_
-
-#include <vector>
-
-#include "absl/synchronization/mutex.h"
-#include "absl/types/span.h"
-#include "iree/base/status.h"
-#include "iree/base/time.h"
-#include "iree/hal/allocator.h"
-#include "iree/hal/buffer.h"
-#include "iree/hal/command_queue.h"
-#include "iree/hal/device.h"
-#include "iree/hal/device_placement.h"
-#include "iree/hal/executable_format.h"
-#include "iree/hal/semaphore.h"
-
-namespace iree {
-namespace hal {
-
-// Specifies how devices should be resolved to DevicePlacements.
-// Most fields are optional and when not included will be ignored.
-struct PlacementSpec {
-  // TODO(benvanik): other requirements (features/caps, power, etc).
-
-  // A list of executable formats that the placement should support.
-  // If more than one format is provided any device satisfying at least one
-  // will be considered for placement. The formats can be sorted in descending
-  // priority order to prefer the first available format in the case of ties.
-  absl::Span<const ExecutableFormat> available_formats;
-};
-
-// Manages device lifetime and placement resolution.
-// Optionally the DeviceManager may be used for automatic device selection for
-// allocations or batched submissions, however this is not required if specific
-// devices and scheduling behavior are known to the caller.
-//
-// Thread-safe. Note that callers must ensure that unregistered devices are kept
-// alive for as long as any commands are in-flight that may be using them.
-class DeviceManager final {
- public:
-  DeviceManager();
-  ~DeviceManager();
-
-  // Registers a device with the manager.
-  // The device will be used to resolve placements. Any placements resolved
-  // prior to the addition of the device will need to be refreshed by the caller
-  // if they want to make use of the new device.
-  Status RegisterDevice(ref_ptr<Device> device);
-
-  // Unregisters a device with the manager.
-  // Placements that resolved to the device prior to unregistering will remain
-  // valid for that device. Callers will need to refresh the placements to
-  // ensure the device stops being used.
-  Status UnregisterDevice(Device* device);
-
-  // TODO(benvanik): dispatch info + requirements + etc -> DevicePlacement.
-
-  // Resolves a placement spec to a device placement based on the registered
-  // devices.
-  // If the placement is not fully specified the device and queue may be chosen
-  // at random. See PlacementSpec for more information about resolution and
-  // ranking.
-  StatusOr<DevicePlacement> ResolvePlacement(
-      const PlacementSpec& placement_spec) const;
-
-  // Finds an allocator that can allocate buffers of the given |memory_type| and
-  // |buffer_usage| such that the buffers can be used interchangebly.
-  // Fails if there is no Allocator that can satisfy that requirement.
-  StatusOr<Allocator*> FindCompatibleAllocator(
-      MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
-      absl::Span<const DevicePlacement> device_placements) const;
-
-  // Tries to allocate a host-local buffer that _may_ be optimal for use with
-  // the given |device_placements| and _may_ be device-visible. The buffer can
-  // be used for staging uploads to device-local buffers and is useful for times
-  // when the buffer will be used more on the host than the device. If a buffer
-  // never needs to be used with a device prefer instead
-  // Allocator::host_local()::Allocate.
-  //
-  // Returns a buffer even if it's not possible to satisfy the requested
-  // |buffer_usage| for the |device_placements| at the cost of a run-time
-  // performance hit.
-  StatusOr<ref_ptr<Buffer>> TryAllocateDeviceVisibleBuffer(
-      MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
-      device_size_t allocation_size,
-      absl::Span<const DevicePlacement> device_placements);
-  StatusOr<ref_ptr<Buffer>> TryAllocateDeviceVisibleBuffer(
-      BufferUsageBitfield buffer_usage, device_size_t allocation_size,
-      absl::Span<const DevicePlacement> device_placements) {
-    return TryAllocateDeviceVisibleBuffer(
-        MemoryType::kHostLocal | MemoryType::kDeviceVisible, buffer_usage,
-        allocation_size, device_placements);
-  }
-
-  // Allocates a host-local buffer that is optimal for use on the host but is
-  // usable by the given |device_placements| (at a possible performance
-  // penalty). The buffer can be used for staging uploads to device-local
-  // buffers and is useful for times when the buffer will be used more on the
-  // host than the device. If a buffer never needs to be used with a device
-  // prefer instead HeapBuffer::Allocate.
-  //
-  // Fails if it is not possible to allocate and satisfy all |device_placements|
-  // for the requested |buffer_usage|.
-  StatusOr<ref_ptr<Buffer>> AllocateDeviceVisibleBuffer(
-      MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
-      device_size_t allocation_size,
-      absl::Span<const DevicePlacement> device_placements);
-  StatusOr<ref_ptr<Buffer>> AllocateDeviceVisibleBuffer(
-      BufferUsageBitfield buffer_usage, device_size_t allocation_size,
-      absl::Span<const DevicePlacement> device_placements) {
-    return AllocateDeviceVisibleBuffer(
-        MemoryType::kHostLocal | MemoryType::kDeviceVisible, buffer_usage,
-        allocation_size, device_placements);
-  }
-
-  // Allocates a device-local buffer that is optimal for use with the given
-  // |device_placements|. The buffer will not be host-visible and can only be
-  // used from compatible device queues.
-  //
-  // Fails if it is not possible to allocate and satisfy all |device_placements|
-  // for the requested |buffer_usage|.
-  StatusOr<ref_ptr<Buffer>> AllocateDeviceLocalBuffer(
-      MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
-      device_size_t allocation_size,
-      absl::Span<const DevicePlacement> device_placements);
-  StatusOr<ref_ptr<Buffer>> AllocateDeviceLocalBuffer(
-      BufferUsageBitfield buffer_usage, device_size_t allocation_size,
-      absl::Span<const DevicePlacement> device_placements) {
-    return AllocateDeviceLocalBuffer(MemoryType::kDeviceLocal, buffer_usage,
-                                     allocation_size, device_placements);
-  }
-
-  // Enqueues a submission against the given target |device| |command_queue|.
-  // The provided |deadline| is used to determine how long the submission can
-  // stay waiting in the queue prior to flushing, with absl::InfinitePast
-  // indicating immediate submission and absl::InfiniteFuture indicating that
-  // Flush must be called.
-  //
-  // If |batches| signal_semaphores are provided they will be signaled when
-  // their corresponding submission has completed. If a sequence of submissions
-  // are performed then the semaphore value relationships can be used to elide
-  // waits.
-  //
-  // All provided resources must remain alive until the provided semaphores are
-  // signaled indicating that the resources used are no longer required.
-  //
-  // Submissions may be made from any thread. Behavior is undefined
-  // if a thread is performing a WaitIdle while another thread submits work.
-  Status Submit(Device* device, CommandQueue* command_queue,
-                absl::Span<const SubmissionBatch> batches, Time deadline_ns);
-  Status Submit(Device* device, CommandQueue* command_queue,
-                absl::Span<const SubmissionBatch> batches,
-                Duration timeout_ns) {
-    return Submit(device, command_queue, batches,
-                  RelativeTimeoutToDeadlineNanos(timeout_ns));
-  }
-  Status Submit(Device* device, CommandQueue* command_queue,
-                absl::Span<const SubmissionBatch> batches) {
-    return Submit(device, command_queue, batches, InfinitePast());
-  }
-
-  // Flushes any requests that are pending in the scheduler and ensures they
-  // begin executing ASAP regardless of policy.
-  //
-  // If any used device has encountered an error during submission at any
-  // point it will be returned here (repeatedly).
-  Status Flush();
-
-  // Blocks until all outstanding requests have been completed.
-  // This is equivalent to having waited on all outstanding semaphore signal
-  // operations in all previously submitted batches.
-  // Implicitly calls Flush to ensure delayed requests are scheduled.
-  // Work submitted from other threads during a wait may not be included in the
-  // wait set.
-  //
-  // If any used device has encountered an error during submission at any
-  // point it will be returned here (repeatedly).
-  Status WaitIdle(Time deadline_ns);
-  inline Status WaitIdle(Duration timeout_ns) {
-    return WaitIdle(RelativeTimeoutToDeadlineNanos(timeout_ns));
-  }
-  inline Status WaitIdle() { return WaitIdle(InfiniteFuture()); }
-
- private:
-  mutable absl::Mutex device_mutex_;
-  std::vector<ref_ptr<Device>> devices_ ABSL_GUARDED_BY(device_mutex_);
-};
-
-}  // namespace hal
-}  // namespace iree
-
-#endif  // IREE_HAL_DEVICE_MANAGER_H_
diff --git a/iree/hal/device_placement.h b/iree/hal/device_placement.h
deleted file mode 100644
index bd337ff..0000000
--- a/iree/hal/device_placement.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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.
-
-#ifndef IREE_HAL_DEVICE_PLACEMENT_H_
-#define IREE_HAL_DEVICE_PLACEMENT_H_
-
-namespace iree {
-namespace hal {
-
-class Device;
-
-// TODO(benvanik): define device-specific placement info - possibly opaque.
-struct DevicePlacement {
-  Device* device = nullptr;
-  int queue_id = 0;
-};
-
-}  // namespace hal
-}  // namespace iree
-
-#endif  // IREE_HAL_DEVICE_PLACEMENT_H_
diff --git a/iree/hal/dylib/dylib_executable.cc b/iree/hal/dylib/dylib_executable.cc
index 2aa7292..a5d7b0a 100644
--- a/iree/hal/dylib/dylib_executable.cc
+++ b/iree/hal/dylib/dylib_executable.cc
@@ -76,9 +76,10 @@
 namespace dylib {
 
 // static
-StatusOr<ref_ptr<DyLibExecutable>> DyLibExecutable::Load(ExecutableSpec spec) {
+StatusOr<ref_ptr<DyLibExecutable>> DyLibExecutable::Load(
+    iree_const_byte_span_t executable_data) {
   auto executable = make_ref<DyLibExecutable>();
-  IREE_RETURN_IF_ERROR(executable->Initialize(spec));
+  IREE_RETURN_IF_ERROR(executable->Initialize(executable_data));
   return executable;
 }
 
@@ -101,12 +102,10 @@
   }
 }
 
-Status DyLibExecutable::Initialize(ExecutableSpec spec) {
+Status DyLibExecutable::Initialize(iree_const_byte_span_t executable_data) {
   IREE_TRACE_SCOPE0("DyLibExecutable::Initialize");
 
   // Verify and fetch the executable flatbuffer wrapper.
-  iree_const_byte_span_t executable_data = iree_make_const_byte_span(
-      spec.executable_data.data(), spec.executable_data.size());
   IREE_RETURN_IF_ERROR(
       iree_hal_dylib_executable_flatbuffer_verify(executable_data));
   iree_DyLibExecutableDef_table_t executable_def =
diff --git a/iree/hal/dylib/dylib_executable.h b/iree/hal/dylib/dylib_executable.h
index 424c096..1408d42 100644
--- a/iree/hal/dylib/dylib_executable.h
+++ b/iree/hal/dylib/dylib_executable.h
@@ -22,7 +22,6 @@
 #include "iree/base/dynamic_library.h"
 #include "iree/base/status.h"
 #include "iree/base/tracing.h"
-#include "iree/hal/executable_spec.h"
 #include "iree/hal/host/host_executable.h"
 
 namespace iree {
@@ -33,20 +32,19 @@
 
 class DyLibExecutable final : public HostExecutable {
  public:
-  static StatusOr<ref_ptr<DyLibExecutable>> Load(ExecutableSpec spec);
+  static StatusOr<ref_ptr<DyLibExecutable>> Load(
+      iree_const_byte_span_t executable_data);
 
   DyLibExecutable();
   ~DyLibExecutable() override;
 
-  bool supports_debugging() const override { return false; }
-
   StatusOr<ref_ptr<DispatchState>> PrepareDispatch(
       const DispatchParams& params) override;
   Status DispatchTile(DispatchState* state,
                       std::array<uint32_t, 3> workgroup_xyz) override;
 
  private:
-  Status Initialize(ExecutableSpec spec);
+  Status Initialize(iree_const_byte_span_t executable_data);
 
   absl::InlinedVector<std::string, 4> temp_file_paths_;
   std::unique_ptr<DynamicLibrary> executable_library_;
diff --git a/iree/hal/dylib/dylib_executable_cache.cc b/iree/hal/dylib/dylib_executable_cache.cc
index 010e5d9..6121ddd 100644
--- a/iree/hal/dylib/dylib_executable_cache.cc
+++ b/iree/hal/dylib/dylib_executable_cache.cc
@@ -33,7 +33,7 @@
 
 StatusOr<ref_ptr<Executable>> DyLibExecutableCache::PrepareExecutable(
     ExecutableLayout* executable_layout, ExecutableCachingModeBitfield mode,
-    const ExecutableSpec& spec) {
+    iree_const_byte_span_t executable_data) {
   IREE_TRACE_SCOPE0("DyLibExecutableCache::PrepareExecutable");
 
   // TODO(scotttodd): Options for using in-memory files where supported, or not
@@ -43,7 +43,7 @@
   //    hash data into a filename and read from / write to GetTempPath() or
   //    GetCachePath() rather than use GetTempFile().
 
-  return DyLibExecutable::Load(spec);
+  return DyLibExecutable::Load(executable_data);
 }
 
 }  // namespace dylib
diff --git a/iree/hal/dylib/dylib_executable_cache.h b/iree/hal/dylib/dylib_executable_cache.h
index 68c9872..1b97745 100644
--- a/iree/hal/dylib/dylib_executable_cache.h
+++ b/iree/hal/dylib/dylib_executable_cache.h
@@ -31,7 +31,7 @@
 
   StatusOr<ref_ptr<Executable>> PrepareExecutable(
       ExecutableLayout* executable_layout, ExecutableCachingModeBitfield mode,
-      const ExecutableSpec& spec) override;
+      iree_const_byte_span_t executable_data) override;
 };
 
 }  // namespace dylib
diff --git a/iree/hal/executable.h b/iree/hal/executable.h
index d724d01..baf635e 100644
--- a/iree/hal/executable.h
+++ b/iree/hal/executable.h
@@ -22,33 +22,6 @@
 
 class Executable : public Resource {
  public:
-  ~Executable() override = default;
-
-  // True if the executable was prepared with debugging enabled and the device
-  // and input data support debugging (symbols present, etc).
-  virtual bool supports_debugging() const = 0;
-
-  // TODO(benvanik): disassembly methods.
-
-  // TODO(benvanik): relative offset calculation:
-  //   - step once
-  //   - step over
-  //   - step out
-
-  // TODO(benvanik): create executable split on breakpoint.
-  // Executable should return when the breakpoint is hit without any future
-  // modifications to output buffers. If the breakpoint is not hit the
-  // executable should run to completion as normal.
-
-  // TODO(benvanik): retrieve coverage info.
-  // Returns a buffer containing offset -> coverage metrics. Note that depending
-  // on the device this may only contain a single coverage metric for the entire
-  // executable or some subset of the available offsets.
-
-  // TODO(benvanik): retrieve profiling info.
-
- protected:
-  Executable() = default;
 };
 
 }  // namespace hal
diff --git a/iree/hal/executable_cache.cc b/iree/hal/executable_cache.cc
deleted file mode 100644
index 26ce40c..0000000
--- a/iree/hal/executable_cache.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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.
-
-#include "iree/hal/executable_cache.h"
-
-namespace iree {
-namespace hal {
-
-ExecutableCache::ExecutableCache() = default;
-
-ExecutableCache::~ExecutableCache() = default;
-
-}  // namespace hal
-}  // namespace iree
diff --git a/iree/hal/executable_cache.h b/iree/hal/executable_cache.h
index a083855..ce80851 100644
--- a/iree/hal/executable_cache.h
+++ b/iree/hal/executable_cache.h
@@ -15,13 +15,13 @@
 #ifndef IREE_HAL_EXECUTABLE_CACHE_H_
 #define IREE_HAL_EXECUTABLE_CACHE_H_
 
+#include "iree/base/api.h"
 #include "iree/base/bitfield.h"
 #include "iree/base/ref_ptr.h"
 #include "iree/base/status.h"
 #include "iree/hal/executable.h"
 #include "iree/hal/executable_format.h"
 #include "iree/hal/executable_layout.h"
-#include "iree/hal/executable_spec.h"
 
 namespace iree {
 namespace hal {
@@ -92,7 +92,7 @@
 // executable) simultaneously.
 class ExecutableCache : public RefObject<ExecutableCache> {
  public:
-  virtual ~ExecutableCache();
+  virtual ~ExecutableCache() = default;
 
   // TODO(benvanik): status/queries (size, etc).
 
@@ -116,10 +116,10 @@
   // PrepareExecutables method to batch and wait on the results.
   virtual StatusOr<ref_ptr<Executable>> PrepareExecutable(
       ExecutableLayout* executable_layout, ExecutableCachingModeBitfield mode,
-      const ExecutableSpec& spec) = 0;
+      iree_const_byte_span_t executable_data) = 0;
 
  protected:
-  ExecutableCache();
+  ExecutableCache() = default;
 };
 
 }  // namespace hal
diff --git a/iree/hal/executable_spec.h b/iree/hal/executable_spec.h
deleted file mode 100644
index c9486d3..0000000
--- a/iree/hal/executable_spec.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// 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.
-
-#ifndef IREE_HAL_EXECUTABLE_SPEC_H_
-#define IREE_HAL_EXECUTABLE_SPEC_H_
-
-#include "absl/types/span.h"
-#include "iree/hal/executable_format.h"
-
-namespace iree {
-namespace hal {
-
-// Defines an executable specification used by a cache to prepare an executable.
-struct ExecutableSpec {
-  // TODO(benvanik): pre-populated hash_code/key to avoid calculation.
-
-  // A reference to the executable data as input to the cache.
-  // If ExecutableCachingMode::kAliasProvidedData is set then this reference
-  // may be retained by the cache and the backing buffer must be kept valid for
-  // the lifetime of the cache.
-  absl::Span<const uint8_t> executable_data;
-
-  // TODO(benvanik): add specialization info (constants/defines).
-  // TODO(benvanik): add compiler flags? could treat as opaque.
-};
-
-}  // namespace hal
-}  // namespace iree
-
-#endif  // IREE_HAL_EXECUTABLE_SPEC_H_
diff --git a/iree/hal/heap_buffer.cc b/iree/hal/heap_buffer.cc
deleted file mode 100644
index fae1134..0000000
--- a/iree/hal/heap_buffer.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-// 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.
-
-#include "iree/hal/heap_buffer.h"
-
-#include <cstdint>
-#include <cstdlib>
-#include <string>
-#include <utility>
-
-#include "iree/base/status.h"
-#include "iree/base/tracing.h"
-#include "iree/hal/allocator.h"
-#include "iree/hal/host/host_buffer.h"
-
-namespace iree {
-namespace hal {
-
-namespace {
-
-// An allocator that allocates or wraps host-only buffers.
-// The resulting buffers are not usable by most devices without a copy and
-// using a device allocator is strongly preferred.
-class HeapAllocator : public Allocator {
- public:
-  // Returns a singleton heap allocator that can provide buffers that have
-  // MemoryType::kHostLocal and are allocated with malloc/free.
-  // These buffers will not be usable by devices directly and may incur
-  // additional copies.
-  static Allocator* std_heap();
-
-  // TODO(benvanik): specify custom allocator (not malloc/free).
-  HeapAllocator();
-  ~HeapAllocator() override;
-
-  bool CanUseBufferLike(Allocator* source_allocator,
-                        MemoryTypeBitfield memory_type,
-                        BufferUsageBitfield buffer_usage,
-                        BufferUsageBitfield intended_usage) const override;
-
-  bool CanAllocate(MemoryTypeBitfield memory_type,
-                   BufferUsageBitfield buffer_usage,
-                   size_t allocation_size) const override;
-
-  StatusOr<ref_ptr<Buffer>> Allocate(MemoryTypeBitfield memory_type,
-                                     BufferUsageBitfield buffer_usage,
-                                     size_t allocation_size) override;
-
-  StatusOr<ref_ptr<Buffer>> WrapMutable(MemoryTypeBitfield memory_type,
-                                        MemoryAccessBitfield allowed_access,
-                                        BufferUsageBitfield buffer_usage,
-                                        void* data,
-                                        size_t data_length) override;
-};
-
-// static
-Allocator* HeapAllocator::std_heap() {
-  static Allocator* std_heap_allocator = new HeapAllocator();
-  return std_heap_allocator;
-}
-
-HeapAllocator::HeapAllocator() = default;
-
-HeapAllocator::~HeapAllocator() = default;
-
-bool HeapAllocator::CanUseBufferLike(Allocator* source_allocator,
-                                     MemoryTypeBitfield memory_type,
-                                     BufferUsageBitfield buffer_usage,
-                                     BufferUsageBitfield intended_usage) const {
-  // The host can use anything with kHostVisible.
-  if (!AnyBitSet(memory_type & MemoryType::kHostVisible)) {
-    return false;
-  }
-
-  // Host currently uses mapping to copy buffers, which is done a lot.
-  if (!AnyBitSet(buffer_usage & BufferUsage::kMapping)) {
-    return false;
-  }
-
-  return true;
-}
-
-bool HeapAllocator::CanAllocate(MemoryTypeBitfield memory_type,
-                                BufferUsageBitfield buffer_usage,
-                                size_t allocation_size) const {
-  // This host only allocator cannot serve device visible allocation as we
-  // can't know which devices these buffers will be used with.
-  return (memory_type & MemoryType::kHostLocal) == MemoryType::kHostLocal &&
-         !AnyBitSet(memory_type & MemoryType::kDeviceLocal) &&
-         !AnyBitSet(memory_type & MemoryType::kDeviceVisible);
-}
-
-StatusOr<ref_ptr<Buffer>> HeapAllocator::Allocate(
-    MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
-    size_t allocation_size) {
-  IREE_TRACE_SCOPE0("HeapAllocator::Allocate");
-
-  if (!CanAllocate(memory_type, buffer_usage, allocation_size)) {
-    return FailedPreconditionErrorBuilder(IREE_LOC)
-           << "Allocation not supported; memory_type="
-           << MemoryTypeString(memory_type)
-           << ", buffer_usage=" << BufferUsageString(buffer_usage)
-           << ", allocation_size=" << allocation_size;
-  }
-
-  void* malloced_data = std::calloc(1, allocation_size);
-  if (!malloced_data) {
-    return ResourceExhaustedErrorBuilder(IREE_LOC)
-           << "Failed to malloc " << allocation_size << " bytes";
-  }
-
-  auto buffer =
-      make_ref<HostBuffer>(this, memory_type, MemoryAccess::kAll, buffer_usage,
-                           allocation_size, malloced_data, true);
-  return buffer;
-}
-
-StatusOr<ref_ptr<Buffer>> HeapAllocator::WrapMutable(
-    MemoryTypeBitfield memory_type, MemoryAccessBitfield allowed_access,
-    BufferUsageBitfield buffer_usage, void* data, size_t data_length) {
-  auto buffer = make_ref<HostBuffer>(this, memory_type, allowed_access,
-                                     buffer_usage, data_length, data, false);
-  return buffer;
-}
-
-}  // namespace
-
-// static
-ref_ptr<Buffer> HeapBuffer::Allocate(MemoryTypeBitfield memory_type,
-                                     BufferUsageBitfield usage,
-                                     size_t allocation_size) {
-  auto buffer_or =
-      HeapAllocator::std_heap()->Allocate(memory_type, usage, allocation_size);
-  return std::move(buffer_or.value());
-}
-
-// static
-ref_ptr<Buffer> HeapBuffer::AllocateCopy(BufferUsageBitfield usage,
-                                         const void* data, size_t data_length) {
-  return AllocateCopy(usage, MemoryAccess::kAll, data, data_length);
-}
-
-// static
-ref_ptr<Buffer> HeapBuffer::AllocateCopy(BufferUsageBitfield usage,
-                                         MemoryAccessBitfield allowed_access,
-                                         const void* data, size_t data_length) {
-  IREE_TRACE_SCOPE0("HeapBuffer::AllocateCopy");
-  // Ensure we can map so that we can copy into it.
-  usage |= BufferUsage::kMapping;
-  auto buffer_or = HeapAllocator::std_heap()->Allocate(MemoryType::kHostLocal,
-                                                       usage, data_length);
-  auto buffer = std::move(buffer_or.value());
-  buffer->WriteData(0, data, data_length).IgnoreError();
-  buffer->set_allowed_access(allowed_access);
-  return buffer;
-}
-
-// static
-ref_ptr<Buffer> HeapBuffer::Wrap(MemoryTypeBitfield memory_type,
-                                 BufferUsageBitfield usage, const void* data,
-                                 size_t data_length) {
-  auto buffer_or =
-      HeapAllocator::std_heap()->Wrap(memory_type, usage, data, data_length);
-  return std::move(buffer_or.value());
-}
-
-// static
-ref_ptr<Buffer> HeapBuffer::WrapMutable(MemoryTypeBitfield memory_type,
-                                        MemoryAccessBitfield allowed_access,
-                                        BufferUsageBitfield usage, void* data,
-                                        size_t data_length) {
-  auto buffer_or = HeapAllocator::std_heap()->WrapMutable(
-      memory_type, allowed_access, usage, data, data_length);
-  return std::move(buffer_or.value());
-}
-
-}  // namespace hal
-}  // namespace iree
diff --git a/iree/hal/heap_buffer.h b/iree/hal/heap_buffer.h
deleted file mode 100644
index eba9b72..0000000
--- a/iree/hal/heap_buffer.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// 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.
-
-#ifndef IREE_HAL_HEAP_BUFFER_H_
-#define IREE_HAL_HEAP_BUFFER_H_
-
-#include <memory>
-
-#include "iree/base/status.h"
-#include "iree/hal/buffer.h"
-
-namespace iree {
-namespace hal {
-
-// Factory for buffers that are allocated from the host heap (malloc/free).
-// These buffers cannot be used by devices and will incur copies/transfers when
-// used. Prefer device-specific allocators instead.
-class HeapBuffer {
- public:
-  // Allocates a zeroed host heap buffer of the given size.
-  // Returns a buffer allocated with malloc and have MemoryType::kHostLocal
-  // and will not be usable by devices without copies.
-  static ref_ptr<Buffer> Allocate(MemoryTypeBitfield memory_type,
-                                  BufferUsageBitfield usage,
-                                  size_t allocation_size);
-  static ref_ptr<Buffer> Allocate(BufferUsageBitfield usage,
-                                  size_t allocation_size) {
-    return Allocate(MemoryType::kHostLocal, usage, allocation_size);
-  }
-
-  // Allocates a host heap buffer with a copy of the given data.
-  // Returns a buffer allocated with malloc and have MemoryType::kHostLocal
-  // and will not be usable by devices without copies.
-  static ref_ptr<Buffer> AllocateCopy(BufferUsageBitfield usage,
-                                      const void* data, size_t data_length);
-  static ref_ptr<Buffer> AllocateCopy(BufferUsageBitfield usage,
-                                      MemoryAccessBitfield allowed_access,
-                                      const void* data, size_t data_length);
-  template <typename T>
-  static ref_ptr<Buffer> AllocateCopy(BufferUsageBitfield usage,
-                                      absl::Span<const T> data);
-  template <typename T>
-  static ref_ptr<Buffer> AllocateCopy(BufferUsageBitfield usage,
-                                      MemoryAccessBitfield allowed_access,
-                                      absl::Span<const T> data);
-
-  // Wraps an existing host heap allocation in a buffer.
-  // Ownership of the host allocation remains with the caller and the memory
-  // must remain valid for so long as the Buffer may be in use.
-  // Will have MemoryType::kHostLocal in most cases and may not be usable
-  // by the device.
-  static ref_ptr<Buffer> Wrap(MemoryTypeBitfield memory_type,
-                              BufferUsageBitfield usage, const void* data,
-                              size_t data_length);
-  static ref_ptr<Buffer> WrapMutable(MemoryTypeBitfield memory_type,
-                                     MemoryAccessBitfield allowed_access,
-                                     BufferUsageBitfield usage, void* data,
-                                     size_t data_length);
-  template <typename T>
-  static ref_ptr<Buffer> Wrap(MemoryTypeBitfield memory_type,
-                              BufferUsageBitfield usage,
-                              absl::Span<const T> data);
-  template <typename T>
-  static ref_ptr<Buffer> WrapMutable(MemoryTypeBitfield memory_type,
-                                     MemoryAccessBitfield allowed_access,
-                                     BufferUsageBitfield usage,
-                                     absl::Span<T> data);
-};
-
-// Inline functions and template definitions follow:
-
-template <typename T>
-ref_ptr<Buffer> HeapBuffer::AllocateCopy(BufferUsageBitfield usage,
-                                         absl::Span<const T> data) {
-  return HeapBuffer::AllocateCopy(usage, MemoryAccess::kAll, data);
-}
-
-template <typename T>
-ref_ptr<Buffer> HeapBuffer::AllocateCopy(BufferUsageBitfield usage,
-                                         MemoryAccessBitfield allowed_access,
-                                         absl::Span<const T> data) {
-  return HeapBuffer::AllocateCopy(usage, allowed_access, data.data(),
-                                  data.size() * sizeof(T));
-}
-
-template <typename T>
-ref_ptr<Buffer> HeapBuffer::Wrap(MemoryTypeBitfield memory_type,
-                                 BufferUsageBitfield usage,
-                                 absl::Span<const T> data) {
-  return HeapBuffer::Wrap(memory_type, usage, data.data(),
-                          data.size() * sizeof(T));
-}
-
-template <typename T>
-ref_ptr<Buffer> HeapBuffer::WrapMutable(MemoryTypeBitfield memory_type,
-                                        MemoryAccessBitfield allowed_access,
-                                        BufferUsageBitfield usage,
-                                        absl::Span<T> data) {
-  return HeapBuffer::WrapMutable(memory_type, allowed_access, usage,
-                                 data.data(), data.size() * sizeof(T));
-}
-
-}  // namespace hal
-}  // namespace iree
-
-#endif  // IREE_HAL_HEAP_BUFFER_H_
diff --git a/iree/hal/metal/metal_direct_allocator.h b/iree/hal/metal/metal_direct_allocator.h
index bf8dde8..c365c1f 100644
--- a/iree/hal/metal/metal_direct_allocator.h
+++ b/iree/hal/metal/metal_direct_allocator.h
@@ -54,9 +54,6 @@
                                      BufferUsageBitfield buffer_usage,
                                      size_t allocation_size) override;
 
-  StatusOr<ref_ptr<Buffer>> AllocateConstant(
-      BufferUsageBitfield buffer_usage, ref_ptr<Buffer> source_buffer) override;
-
   StatusOr<ref_ptr<Buffer>> WrapMutable(MemoryTypeBitfield memory_type,
                                         MemoryAccessBitfield allowed_access,
                                         BufferUsageBitfield buffer_usage,
diff --git a/iree/hal/metal/metal_direct_allocator.mm b/iree/hal/metal/metal_direct_allocator.mm
index 3a88c70..e30f481 100644
--- a/iree/hal/metal/metal_direct_allocator.mm
+++ b/iree/hal/metal/metal_direct_allocator.mm
@@ -132,18 +132,6 @@
   return AllocateInternal(memory_type, buffer_usage, MemoryAccess::kAll, allocation_size);
 }
 
-StatusOr<ref_ptr<Buffer>> MetalDirectAllocator::AllocateConstant(BufferUsageBitfield buffer_usage,
-                                                                 ref_ptr<Buffer> source_buffer) {
-  IREE_TRACE_SCOPE0("MetalDirectAllocator::AllocateConstant");
-  // TODO(benvanik): import memory to avoid the copy.
-  IREE_ASSIGN_OR_RETURN(
-      auto buffer, AllocateInternal(MemoryType::kDeviceLocal | MemoryType::kHostVisible,
-                                    buffer_usage, MemoryAccess::kRead | MemoryAccess::kDiscardWrite,
-                                    source_buffer->byte_length()));
-  IREE_RETURN_IF_ERROR(buffer->CopyData(0, source_buffer.get(), 0, kWholeBuffer));
-  return buffer;
-}
-
 StatusOr<ref_ptr<Buffer>> MetalDirectAllocator::WrapMutable(MemoryTypeBitfield memory_type,
                                                             MemoryAccessBitfield allowed_access,
                                                             BufferUsageBitfield buffer_usage,
diff --git a/iree/hal/metal/metal_kernel_library.h b/iree/hal/metal/metal_kernel_library.h
index 7ac2506..87137d7 100644
--- a/iree/hal/metal/metal_kernel_library.h
+++ b/iree/hal/metal/metal_kernel_library.h
@@ -23,7 +23,6 @@
 #include "iree/base/status.h"
 #include "iree/hal/executable.h"
 #include "iree/hal/executable_cache.h"
-#include "iree/hal/executable_spec.h"
 
 // flatcc schemas:
 #include "iree/base/flatcc.h"
@@ -46,11 +45,9 @@
  public:
   static StatusOr<ref_ptr<MetalKernelLibrary>> Create(
       id<MTLDevice> device, ExecutableCachingModeBitfield mode,
-      const ExecutableSpec& spec);
+      iree_const_byte_span_t executable_data);
   ~MetalKernelLibrary() override;
 
-  bool supports_debugging() const override { return false; }
-
   // Returns the MTLFunction for the entry point with the given |ordinal|.
   StatusOr<id<MTLFunction>> GetKernelForEntryPoint(int ordinal) const;
 
diff --git a/iree/hal/metal/metal_kernel_library.mm b/iree/hal/metal/metal_kernel_library.mm
index 8ea7e6a..424f1e2 100644
--- a/iree/hal/metal/metal_kernel_library.mm
+++ b/iree/hal/metal/metal_kernel_library.mm
@@ -89,7 +89,7 @@
 // static
 StatusOr<ref_ptr<MetalKernelLibrary>> MetalKernelLibrary::Create(id<MTLDevice> device,
                                                                  ExecutableCachingModeBitfield mode,
-                                                                 const ExecutableSpec& spec) {
+                                                                 iree_const_byte_span_t executable_data) {
   IREE_TRACE_SCOPE0("MetalKernelLibrary::Create");
 
   // Verify and fetch the executable flatbuffer wrapper.
diff --git a/iree/hal/metal/metal_pipeline_cache.h b/iree/hal/metal/metal_pipeline_cache.h
index 1b59e1c..a953dbf 100644
--- a/iree/hal/metal/metal_pipeline_cache.h
+++ b/iree/hal/metal/metal_pipeline_cache.h
@@ -34,7 +34,7 @@
 
   StatusOr<ref_ptr<Executable>> PrepareExecutable(
       ExecutableLayout* executable_layout, ExecutableCachingModeBitfield mode,
-      const ExecutableSpec& spec) override;
+      iree_const_byte_span_t executable_data) override;
 
  private:
   id<MTLDevice> metal_device_;
diff --git a/iree/hal/metal/metal_pipeline_cache.mm b/iree/hal/metal/metal_pipeline_cache.mm
index 1e98770..162c8c6 100644
--- a/iree/hal/metal/metal_pipeline_cache.mm
+++ b/iree/hal/metal/metal_pipeline_cache.mm
@@ -33,11 +33,11 @@
 
 StatusOr<ref_ptr<Executable>> MetalPipelineCache::PrepareExecutable(
     ExecutableLayout* executable_layout, ExecutableCachingModeBitfield mode,
-    const ExecutableSpec& spec) {
+    iree_const_byte_span_t executable_data) {
   IREE_TRACE_SCOPE0("MetalPipelineCache::PrepareExecutable");
 
   // Create the Metal library (which may itself own many pipeline states).
-  IREE_ASSIGN_OR_RETURN(auto executable, MetalKernelLibrary::Create(metal_device_, mode, spec));
+  IREE_ASSIGN_OR_RETURN(auto executable, MetalKernelLibrary::Create(metal_device_, mode, executable_data));
 
   return executable;
 }
diff --git a/iree/hal/stack_trace.h b/iree/hal/stack_trace.h
deleted file mode 100644
index ca4c450..0000000
--- a/iree/hal/stack_trace.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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.
-
-#ifndef IREE_HAL_STACK_TRACE_H_
-#define IREE_HAL_STACK_TRACE_H_
-
-namespace iree {
-namespace hal {
-
-class StackTrace {
- public:
-  // TODO(benvanik): define contents.
-  //  frame:
-  //    device type (cpu, etc)
-  //    effective processor type (determines disasm/etc) <- r52, vliw, etc
-  //    effective offset <- in disasm (abstract, could be op ordinal, byte
-  //      offset)
-  //    source offset <- used in source map lookup
-  //    physical offset <- informative, void* (real memory address)
-  // physical_context (x86 registers, etc)
-  // effective_context (??)
-  // source_context (buffer views/etc?)
-};
-
-}  // namespace hal
-}  // namespace iree
-
-#endif  // IREE_HAL_STACK_TRACE_H_
diff --git a/iree/hal/vmla/vmla_cache.cc b/iree/hal/vmla/vmla_cache.cc
index 3b71bb2..7b8940f 100644
--- a/iree/hal/vmla/vmla_cache.cc
+++ b/iree/hal/vmla/vmla_cache.cc
@@ -41,14 +41,15 @@
 
 StatusOr<ref_ptr<Executable>> VMLACache::PrepareExecutable(
     ExecutableLayout* executable_layout, ExecutableCachingModeBitfield mode,
-    const ExecutableSpec& spec) {
+    iree_const_byte_span_t executable_data) {
   IREE_TRACE_SCOPE0("VMLACache::PrepareExecutable");
   // Wrap the data (or copy it).
   bool allow_aliasing_data =
       AllBitsSet(mode, ExecutableCachingMode::kAliasProvidedData);
   IREE_ASSIGN_OR_RETURN(
       auto executable,
-      VMLAExecutable::Load(instance_, vmla_module_, spec, allow_aliasing_data));
+      VMLAExecutable::Load(instance_, vmla_module_, executable_data,
+                           allow_aliasing_data));
 
   return executable;
 }
diff --git a/iree/hal/vmla/vmla_cache.h b/iree/hal/vmla/vmla_cache.h
index 560d4bd..11860ce 100644
--- a/iree/hal/vmla/vmla_cache.h
+++ b/iree/hal/vmla/vmla_cache.h
@@ -34,7 +34,7 @@
 
   StatusOr<ref_ptr<Executable>> PrepareExecutable(
       ExecutableLayout* executable_layout, ExecutableCachingModeBitfield mode,
-      const ExecutableSpec& spec) override;
+      iree_const_byte_span_t executable_data) override;
 
  private:
   iree_vm_instance_t* instance_ = nullptr;
diff --git a/iree/hal/vmla/vmla_executable.cc b/iree/hal/vmla/vmla_executable.cc
index da0cff2..eb9cecf 100644
--- a/iree/hal/vmla/vmla_executable.cc
+++ b/iree/hal/vmla/vmla_executable.cc
@@ -72,23 +72,27 @@
 // static
 StatusOr<ref_ptr<VMLAExecutable>> VMLAExecutable::Load(
     iree_vm_instance_t* instance, iree_vm_module_t* vmla_module,
-    ExecutableSpec spec, bool allow_aliasing_data) {
+    iree_const_byte_span_t executable_data, bool allow_aliasing_data) {
   IREE_TRACE_SCOPE0("VMLAExecutable::Load");
   // Allocate the executable now.
   // We do this here so that if we need to clone the data we are passing that
   // to the VM loader instead of the data we may not have access to later.
-  auto executable = make_ref<VMLAExecutable>(spec, allow_aliasing_data);
+  auto executable =
+      make_ref<VMLAExecutable>(executable_data, allow_aliasing_data);
   IREE_RETURN_IF_ERROR(executable->Initialize(instance, vmla_module));
   return executable;
 }
 
-VMLAExecutable::VMLAExecutable(ExecutableSpec spec, bool allow_aliasing_data)
-    : spec_(spec) {
+VMLAExecutable::VMLAExecutable(iree_const_byte_span_t executable_data,
+                               bool allow_aliasing_data)
+    : executable_data_(executable_data) {
   if (!allow_aliasing_data) {
     // Clone data.
-    cloned_executable_data_ = {spec.executable_data.begin(),
-                               spec.executable_data.end()};
-    spec_.executable_data = absl::MakeConstSpan(cloned_executable_data_);
+    cloned_executable_data_ = {
+        executable_data.data,
+        executable_data.data + executable_data.data_length};
+    executable_data_ = iree_make_const_byte_span(
+        cloned_executable_data_.data(), cloned_executable_data_.size());
   }
 }
 
@@ -103,12 +107,10 @@
   IREE_TRACE_SCOPE0("VMLAExecutable::Initialize");
 
   // Verify and fetch the executable flatbuffer wrapper.
-  iree_const_byte_span_t executable_data = iree_make_const_byte_span(
-      spec_.executable_data.data(), spec_.executable_data.size());
   IREE_RETURN_IF_ERROR(
-      iree_hal_vmla_executable_flatbuffer_verify(executable_data));
+      iree_hal_vmla_executable_flatbuffer_verify(executable_data_));
   iree_VMLAExecutableDef_table_t executable_def =
-      iree_VMLAExecutableDef_as_root(executable_data.data);
+      iree_VMLAExecutableDef_as_root(executable_data_.data);
 
   // Load bytecode module from the executable spec.
   flatbuffers_uint8_vec_t bytecode_module_vec =
diff --git a/iree/hal/vmla/vmla_executable.h b/iree/hal/vmla/vmla_executable.h
index 7eb3c27..5bcdc4c 100644
--- a/iree/hal/vmla/vmla_executable.h
+++ b/iree/hal/vmla/vmla_executable.h
@@ -20,7 +20,6 @@
 #include "absl/container/inlined_vector.h"
 #include "absl/types/span.h"
 #include "iree/base/status.h"
-#include "iree/hal/executable_spec.h"
 #include "iree/hal/host/host_executable.h"
 #include "iree/vm/api.h"
 
@@ -32,21 +31,14 @@
 
 class VMLAExecutable final : public HostExecutable {
  public:
-  static StatusOr<ref_ptr<VMLAExecutable>> Load(iree_vm_instance_t* instance,
-                                                iree_vm_module_t* vmla_module,
-                                                ExecutableSpec spec,
-                                                bool allow_aliasing_data);
+  static StatusOr<ref_ptr<VMLAExecutable>> Load(
+      iree_vm_instance_t* instance, iree_vm_module_t* vmla_module,
+      iree_const_byte_span_t executable_data, bool allow_aliasing_data);
 
-  VMLAExecutable(ExecutableSpec spec, bool allow_aliasing_data);
+  VMLAExecutable(iree_const_byte_span_t executable_data,
+                 bool allow_aliasing_data);
   ~VMLAExecutable() override;
 
-  bool supports_debugging() const override { return false; }
-
-  // Reference to the bytecode blob contents.
-  absl::Span<const uint8_t> executable_data() const {
-    return spec_.executable_data;
-  }
-
   // VM context containing the loaded executable module.
   iree_vm_context_t* context() const { return context_; }
 
@@ -64,7 +56,7 @@
   Status Initialize(iree_vm_instance_t* instance,
                     iree_vm_module_t* vmla_module);
 
-  ExecutableSpec spec_;
+  iree_const_byte_span_t executable_data_;
   std::vector<uint8_t> cloned_executable_data_;
 
   iree_vm_context_t* context_ = nullptr;
diff --git a/iree/hal/vulkan/pipeline_cache.cc b/iree/hal/vulkan/pipeline_cache.cc
index 5404cf9..47544f0 100644
--- a/iree/hal/vulkan/pipeline_cache.cc
+++ b/iree/hal/vulkan/pipeline_cache.cc
@@ -34,7 +34,7 @@
 
 StatusOr<ref_ptr<Executable>> PipelineCache::PrepareExecutable(
     ExecutableLayout* executable_layout, ExecutableCachingModeBitfield mode,
-    const ExecutableSpec& spec) {
+    iree_const_byte_span_t executable_data) {
   IREE_TRACE_SCOPE0("PipelineCache::PrepareExecutable");
 
   // Create the executable (which may itself own many pipelines).
@@ -44,7 +44,7 @@
           add_ref(logical_device_),
           /*pipeline_cache=*/VK_NULL_HANDLE,
           static_cast<PipelineExecutableLayout*>(executable_layout), mode,
-          spec));
+          executable_data));
   return executable;
 }
 
diff --git a/iree/hal/vulkan/pipeline_cache.h b/iree/hal/vulkan/pipeline_cache.h
index 60d2675..ecc2f2d 100644
--- a/iree/hal/vulkan/pipeline_cache.h
+++ b/iree/hal/vulkan/pipeline_cache.h
@@ -42,7 +42,7 @@
 
   StatusOr<ref_ptr<Executable>> PrepareExecutable(
       ExecutableLayout* executable_layout, ExecutableCachingModeBitfield mode,
-      const ExecutableSpec& spec) override;
+      iree_const_byte_span_t executable_data) override;
 
  private:
   ref_ptr<VkDeviceHandle> logical_device_;
diff --git a/iree/hal/vulkan/pipeline_executable.cc b/iree/hal/vulkan/pipeline_executable.cc
index b954f24..13ff390 100644
--- a/iree/hal/vulkan/pipeline_executable.cc
+++ b/iree/hal/vulkan/pipeline_executable.cc
@@ -128,13 +128,12 @@
 StatusOr<ref_ptr<PipelineExecutable>> PipelineExecutable::Create(
     ref_ptr<VkDeviceHandle> logical_device, VkPipelineCache pipeline_cache,
     PipelineExecutableLayout* executable_layout,
-    ExecutableCachingModeBitfield mode, const ExecutableSpec& spec) {
+    ExecutableCachingModeBitfield mode,
+    iree_const_byte_span_t executable_data) {
   IREE_TRACE_SCOPE0("PipelineExecutable::Create");
   const auto& syms = logical_device->syms();
 
   // Verify and fetch the executable flatbuffer wrapper.
-  iree_const_byte_span_t executable_data = iree_make_const_byte_span(
-      spec.executable_data.data(), spec.executable_data.size());
   IREE_RETURN_IF_ERROR(
       iree_hal_spirv_executable_flatbuffer_verify(executable_data));
   iree_SpirVExecutableDef_table_t executable_def =
diff --git a/iree/hal/vulkan/pipeline_executable.h b/iree/hal/vulkan/pipeline_executable.h
index 6715937..c9bfe72 100644
--- a/iree/hal/vulkan/pipeline_executable.h
+++ b/iree/hal/vulkan/pipeline_executable.h
@@ -26,7 +26,6 @@
 #include "iree/hal/executable.h"
 #include "iree/hal/executable_cache.h"
 #include "iree/hal/executable_layout.h"
-#include "iree/hal/executable_spec.h"
 #include "iree/hal/vulkan/handle_util.h"
 #include "iree/hal/vulkan/native_descriptor_set.h"
 #include "iree/hal/vulkan/pipeline_executable_layout.h"
@@ -40,7 +39,8 @@
   static StatusOr<ref_ptr<PipelineExecutable>> Create(
       ref_ptr<VkDeviceHandle> logical_device, VkPipelineCache pipeline_cache,
       PipelineExecutableLayout* executable_layout,
-      ExecutableCachingModeBitfield mode, const ExecutableSpec& spec);
+      ExecutableCachingModeBitfield mode,
+      iree_const_byte_span_t executable_data);
 
   PipelineExecutable(ref_ptr<VkDeviceHandle> logical_device,
                      absl::InlinedVector<VkPipeline, 1> pipelines);
@@ -50,8 +50,6 @@
     return logical_device_->syms();
   }
 
-  bool supports_debugging() const override { return false; }
-
   StatusOr<VkPipeline> GetPipelineForEntryPoint(int entry_ordinal) const;
 
  private:
diff --git a/iree/hal/vulkan/vma_allocator.cc b/iree/hal/vulkan/vma_allocator.cc
index bbdaa43..e3d996f 100644
--- a/iree/hal/vulkan/vma_allocator.cc
+++ b/iree/hal/vulkan/vma_allocator.cc
@@ -214,23 +214,6 @@
                           allocation_size, /*flags=*/0);
 }
 
-StatusOr<ref_ptr<Buffer>> VmaAllocator::AllocateConstant(
-    BufferUsageBitfield buffer_usage, ref_ptr<Buffer> source_buffer) {
-  IREE_TRACE_SCOPE0("VmaAllocator::AllocateConstant");
-  // TODO(benvanik): import memory to avoid the copy.
-  IREE_ASSIGN_OR_RETURN(
-      auto buffer,
-      AllocateInternal(MemoryType::kDeviceLocal | MemoryType::kHostVisible,
-                       buffer_usage,
-                       MemoryAccess::kRead | MemoryAccess::kDiscardWrite,
-                       source_buffer->byte_length(),
-                       /*flags=*/0));
-  IREE_RETURN_IF_ERROR(
-      buffer->CopyData(0, source_buffer.get(), 0, kWholeBuffer));
-  buffer->set_allowed_access(MemoryAccess::kRead);
-  return buffer;
-}
-
 StatusOr<ref_ptr<Buffer>> VmaAllocator::WrapMutable(
     MemoryTypeBitfield memory_type, MemoryAccessBitfield allowed_access,
     BufferUsageBitfield buffer_usage, void* data, size_t data_length) {
diff --git a/iree/hal/vulkan/vma_allocator.h b/iree/hal/vulkan/vma_allocator.h
index b48cbd8..732d423 100644
--- a/iree/hal/vulkan/vma_allocator.h
+++ b/iree/hal/vulkan/vma_allocator.h
@@ -89,9 +89,6 @@
                                      BufferUsageBitfield buffer_usage,
                                      size_t allocation_size) override;
 
-  StatusOr<ref_ptr<Buffer>> AllocateConstant(
-      BufferUsageBitfield buffer_usage, ref_ptr<Buffer> source_buffer) override;
-
   StatusOr<ref_ptr<Buffer>> WrapMutable(MemoryTypeBitfield memory_type,
                                         MemoryAccessBitfield allowed_access,
                                         BufferUsageBitfield buffer_usage,
diff --git a/iree/samples/custom_modules/custom_modules_test.cc b/iree/samples/custom_modules/custom_modules_test.cc
index beef630..e33abe6 100644
--- a/iree/samples/custom_modules/custom_modules_test.cc
+++ b/iree/samples/custom_modules/custom_modules_test.cc
@@ -53,6 +53,7 @@
         hal_driver, iree_allocator_system(), &hal_device));
     IREE_CHECK_OK(iree_hal_module_create(hal_device, iree_allocator_system(),
                                          &hal_module_));
+    hal_allocator_ = iree_hal_device_allocator(hal_device);
     iree_hal_device_release(hal_device);
     iree_hal_driver_release(hal_driver);
 
@@ -100,6 +101,7 @@
   iree_vm_module_t* bytecode_module_ = nullptr;
   iree_vm_module_t* native_module_ = nullptr;
   iree_vm_module_t* hal_module_ = nullptr;
+  iree_hal_allocator_t* hal_allocator_ = nullptr;
 };
 
 TEST_F(CustomModulesTest, ReverseAndPrint) {
@@ -145,12 +147,12 @@
   static float kBufferContents[2 * 4] = {0.0f, 1.0f, 2.0f, 3.0f,
                                          4.0f, 5.0f, 6.0f, 7.0f};
   iree_hal_buffer_t* buffer = nullptr;
-  IREE_ASSERT_OK(iree_hal_heap_buffer_allocate_copy(
-      IREE_HAL_MEMORY_TYPE_HOST_LOCAL, IREE_HAL_BUFFER_USAGE_ALL,
-      IREE_HAL_MEMORY_ACCESS_ALL,
+  IREE_ASSERT_OK(iree_hal_allocator_wrap_buffer(
+      hal_allocator_, IREE_HAL_MEMORY_TYPE_HOST_LOCAL,
+      IREE_HAL_MEMORY_ACCESS_ALL, IREE_HAL_BUFFER_USAGE_ALL,
       iree_byte_span_t{reinterpret_cast<uint8_t*>(kBufferContents),
                        sizeof(kBufferContents)},
-      iree_allocator_system(), iree_allocator_system(), &buffer));
+      &buffer));
 
   // Pass in the tensor as an expanded HAL buffer.
   iree::vm::ref<iree_vm_list_t> inputs;
@@ -185,12 +187,12 @@
   static float kBufferContents[2 * 4] = {0.0f, 1.0f, 2.0f, 3.0f,
                                          4.0f, 5.0f, 6.0f, 7.0f};
   iree_hal_buffer_t* buffer = nullptr;
-  IREE_ASSERT_OK(iree_hal_heap_buffer_allocate_copy(
-      IREE_HAL_MEMORY_TYPE_HOST_LOCAL, IREE_HAL_BUFFER_USAGE_ALL,
-      IREE_HAL_MEMORY_ACCESS_ALL,
+  IREE_ASSERT_OK(iree_hal_allocator_wrap_buffer(
+      hal_allocator_, IREE_HAL_MEMORY_TYPE_HOST_LOCAL,
+      IREE_HAL_MEMORY_ACCESS_ALL, IREE_HAL_BUFFER_USAGE_ALL,
       iree_byte_span_t{reinterpret_cast<uint8_t*>(kBufferContents),
                        sizeof(kBufferContents)},
-      iree_allocator_system(), iree_allocator_system(), &buffer));
+      &buffer));
 
   // Pass in the tensor as an expanded HAL buffer.
   iree::vm::ref<iree_vm_list_t> inputs;