Adding lit tests for stream->HAL conversion.
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/test/shape_ops.mlir b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/test/shape_ops.mlir
index e1fdd71..42fc714 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/test/shape_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/test/shape_ops.mlir
@@ -1,7 +1,25 @@
 // RUN: iree-opt --split-input-file --iree-hal-conversion %s | FileCheck %s
 
-// TODO(#7277): add new streams->hal conversion tests.
-// CHECK: @todo
-func.func @todo() {
-  return
+// CHECK-LABEL: @tensorDim
+// CHECK-SAME: (%[[ARG0:.+]]: !hal.buffer_view)
+func.func @tensorDim(%arg0: tensor<4x?xf32>) -> index {
+  %c1 = arith.constant 1 : index
+  // CHECK: %[[DIM:.+]] = hal.buffer_view.dim<%[[ARG0]] : !hal.buffer_view>[1] : index
+  %dim = tensor.dim %arg0, %c1 : tensor<4x?xf32>
+  return %dim : index
+}
+
+// -----
+
+// NOTE: we only support ranked tensors, and hal.buffer_view.rank will fold
+// immediately to the static value. We check here that the folding happened.
+
+// CHECK: @tensorRank
+// CHECK-SAME: (%[[ARG0:.+]]: !hal.buffer_view)
+func.func @tensorRank(%arg0: tensor<4x?xf32>) -> index {
+  // CHECK-NOT: hal.buffer_view.rank
+  // CHECK: %[[RANK:.+]] = arith.constant 2
+  %rank = tensor.rank %arg0 : tensor<4x?xf32>
+  // CHECK: return %[[RANK]]
+  return %rank : index
 }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/test/structural_ops.mlir b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/test/structural_ops.mlir
index e1fdd71..5b5307e 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/test/structural_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/test/structural_ops.mlir
@@ -1,7 +1,80 @@
 // RUN: iree-opt --split-input-file --iree-hal-conversion %s | FileCheck %s
 
-// TODO(#7277): add new streams->hal conversion tests.
-// CHECK: @todo
-func.func @todo() {
-  return
+// These patterns are not doing anything HAL-specific and instead just allowing
+// for the ops to update their types during dialect conversions. These should be
+// moved to a general utility location or really become something upstream that
+// can be reused.
+
+// CHECK-LABEL: @funcOp
+// CHECK-SAME: (%[[ARG0:.+]]: !hal.buffer_view) -> !hal.buffer_view
+func.func @funcOp(%arg0: tensor<4x2xf32>) -> tensor<4x2xf32> {
+  // CHECK: return %[[ARG0]] : !hal.buffer_view
+  return %arg0 : tensor<4x2xf32>
+}
+
+// -----
+
+// CHECK-LABEL: @callOp
+// CHECK-SAME: (%[[ARG0:.+]]: !hal.buffer_view) -> !hal.buffer_view
+func.func @callOp(%arg0: tensor<4x2xf32>) -> tensor<4x2xf32> {
+  // CHECK: %[[RET0:.+]] = call @extern(%[[ARG0]]) : (!hal.buffer_view) -> !hal.buffer_view
+  %ret0 = call @extern(%arg0) : (tensor<4x2xf32>) -> tensor<4x2xf32>
+  // CHECK: return %[[RET0]] : !hal.buffer_view
+  return %ret0 : tensor<4x2xf32>
+}
+// CHECK: func.func private @extern(!hal.buffer_view) -> !hal.buffer_view
+func.func private @extern(tensor<4x2xf32>) -> tensor<4x2xf32>
+
+// -----
+
+// CHECK-LABEL: @brOp
+// CHECK-SAME: (%[[ARG0:.+]]: !hal.buffer_view) -> !hal.buffer_view
+func.func @brOp(%arg0: tensor<4x2xf32>) -> tensor<4x2xf32> {
+  // CHECK: cf.br ^bb1(%[[ARG0]] : !hal.buffer_view)
+  cf.br ^bb1(%arg0 : tensor<4x2xf32>)
+// CHECK: ^bb1(%[[BB1_ARG0:.+]]: !hal.buffer_view):
+^bb1(%bb1_arg0: tensor<4x2xf32>):
+  // CHECK: return %[[BB1_ARG0]] : !hal.buffer_view
+  return %bb1_arg0 : tensor<4x2xf32>
+}
+
+// -----
+
+// CHECK-LABEL: @condBrOp
+// CHECK-SAME: (%[[COND:.+]]: i1, %[[ARG0:.+]]: !hal.buffer_view, %[[ARG1:.+]]: !hal.buffer_view) -> !hal.buffer_view
+func.func @condBrOp(%cond: i1, %arg0: tensor<4x2xf32>, %arg1: tensor<4x2xf32>) -> tensor<4x2xf32> {
+  // CHECK: cf.cond_br %[[COND]], ^bb1(%[[ARG0]] : !hal.buffer_view), ^bb1(%[[ARG1]] : !hal.buffer_view)
+  cf.cond_br %cond, ^bb1(%arg0 : tensor<4x2xf32>), ^bb1(%arg1 : tensor<4x2xf32>)
+// CHECK: ^bb1(%[[BB1_ARG0:.+]]: !hal.buffer_view):
+^bb1(%bb1_arg0 : tensor<4x2xf32>):
+  // CHECK: return %[[BB1_ARG0]] : !hal.buffer_view
+  return %bb1_arg0 : tensor<4x2xf32>
+}
+
+// -----
+
+// CHECK-LABEL: @selectOp
+// CHECK-SAME: (%[[COND:.+]]: i1, %[[ARG0:.+]]: !hal.buffer_view, %[[ARG1:.+]]: !hal.buffer_view) -> !hal.buffer_view
+func.func @selectOp(%cond: i1, %arg0: tensor<4x2xf32>, %arg1: tensor<4x2xf32>) -> tensor<4x2xf32> {
+  // CHECK: %[[RET0:.+]] = arith.select %[[COND]], %[[ARG0]], %[[ARG1]] : !hal.buffer_view
+  %ret0 = arith.select %cond, %arg0, %arg1 : tensor<4x2xf32>
+  // CHECK: return %[[RET0]] : !hal.buffer_view
+  return %ret0 : tensor<4x2xf32>
+}
+
+// -----
+
+// CHECK-LABEL: @ifOp
+// CHECK-SAME: (%[[COND:.+]]: i1, %[[ARG0:.+]]: !hal.buffer_view, %[[ARG1:.+]]: !hal.buffer_view) -> !hal.buffer_view
+func.func @ifOp(%cond: i1, %arg0: tensor<4x2xf32>, %arg1: tensor<4x2xf32>) -> tensor<4x2xf32> {
+  // CHECK: %[[RET0:.+]] = scf.if %[[COND]] -> (!hal.buffer_view)
+  %ret0 = scf.if %cond -> (tensor<4x2xf32>) {
+    // CHECK: scf.yield %[[ARG0]] : !hal.buffer_view
+    scf.yield %arg0 : tensor<4x2xf32>
+  } else {
+    // CHECK: scf.yield %[[ARG1]] : !hal.buffer_view
+    scf.yield %arg1 : tensor<4x2xf32>
+  }
+  // CHECK: return %[[RET0]] : !hal.buffer_view
+  return %ret0 : tensor<4x2xf32>
 }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/ConvertStreamToHAL.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/ConvertStreamToHAL.cpp
index 1e2ab8b..220afd1 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/ConvertStreamToHAL.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/ConvertStreamToHAL.cpp
@@ -392,10 +392,8 @@
   LogicalResult matchAndRewrite(
       IREE::Stream::ResourceStoreOp storeOp, OpAdaptor adaptor,
       ConversionPatternRewriter &rewriter) const override {
-    rewriter.create<IREE::HAL::BufferStoreOp>(storeOp.getLoc(), adaptor.value(),
-                                              adaptor.target(),
-                                              adaptor.target_offset());
-    rewriter.replaceOp(storeOp, adaptor.target());
+    rewriter.replaceOpWithNewOp<IREE::HAL::BufferStoreOp>(
+        storeOp, adaptor.value(), adaptor.target(), adaptor.target_offset());
     return success();
   }
 };
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/cmd_ops.mlir b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/cmd_ops.mlir
index e1fdd71..05ad1bc 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/cmd_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/cmd_ops.mlir
@@ -1,7 +1,189 @@
 // RUN: iree-opt --split-input-file --iree-hal-conversion %s | FileCheck %s
 
-// TODO(#7277): add new streams->hal conversion tests.
-// CHECK: @todo
-func.func @todo() {
-  return
+// Today all memory control operations are ignored and we're just left with
+// the normal sequential execution barriers.
+
+// CHECK-LABEL: @cmdMemoryControl
+func.func @cmdMemoryControl(%arg0: !stream.resource<transient>, %arg1: index) -> !stream.timepoint {
+  %c0 = arith.constant 0 : index
+  %c128 = arith.constant 128 : index
+  // CHECK: %[[CMD:.+]] = hal.command_buffer.create
+  // CHECK-NEXT: hal.command_buffer.begin<%[[CMD]]
+  %0 = stream.cmd.execute with(%arg0 as %arg2: !stream.resource<transient>{%arg1}) {
+    // CHECK-NEXT: hal.command_buffer.execution_barrier<%[[CMD]]
+    stream.cmd.flush %arg2[%c0 for %c128] : !stream.resource<transient>{%arg1}
+    // CHECK-NEXT: hal.command_buffer.execution_barrier<%[[CMD]]
+    stream.cmd.invalidate %arg2[%c0 for %c128] : !stream.resource<transient>{%arg1}
+    // CHECK-NEXT: hal.command_buffer.execution_barrier<%[[CMD]]
+    stream.cmd.discard %arg2[%c0 for %c128] : !stream.resource<transient>{%arg1}
+  } => !stream.timepoint
+  // CHECK-NEXT: hal.command_buffer.end<%[[CMD]]
+  // CHECK-NEXT: hal.ex.submit_and_wait
+  return %0 : !stream.timepoint
+}
+
+// -----
+
+// CHECK-LABEL: @cmdFill
+func.func @cmdFill(%arg0: !stream.resource<transient>, %arg1: index) -> !stream.timepoint {
+  %c0 = arith.constant 0 : index
+  %c128 = arith.constant 128 : index
+  %c255_i32 = arith.constant 255 : i32
+  // CHECK: %[[CMD:.+]] = hal.command_buffer.create
+  // CHECK-NEXT: hal.command_buffer.begin<%[[CMD]]
+  %0 = stream.cmd.execute with(%arg0 as %arg2: !stream.resource<transient>{%arg1}) {
+    // CHECK-NEXT: hal.command_buffer.fill_buffer<%[[CMD]] : !hal.command_buffer>
+    // CHECK-SAME: target(%arg0 : !hal.buffer)[%c0, %c128]
+    // CHECK-SAME: pattern(%c255_i32 : i32)
+    stream.cmd.fill %c255_i32, %arg2[%c0 for %c128] : i32 -> !stream.resource<transient>{%arg1}
+    // CHECK-NEXT: hal.command_buffer.execution_barrier<%[[CMD]]
+  } => !stream.timepoint
+  // CHECK-NEXT: hal.command_buffer.end<%[[CMD]]
+  // CHECK-NEXT: hal.ex.submit_and_wait
+  return %0 : !stream.timepoint
+}
+
+// -----
+
+// CHECK-LABEL: @cmdCopy
+func.func @cmdCopy(%arg0: !stream.resource<transient>, %arg1: index, %arg2: !stream.resource<staging>, %arg3: index) -> !stream.timepoint {
+  %c0 = arith.constant 0 : index
+  %c128 = arith.constant 128 : index
+  // CHECK: %[[CMD:.+]] = hal.command_buffer.create
+  // CHECK-NEXT: hal.command_buffer.begin<%[[CMD]]
+  %0 = stream.cmd.execute with(%arg0 as %arg4: !stream.resource<transient>{%arg1}, %arg2 as %arg5: !stream.resource<staging>{%arg3}) {
+    // CHECK-NEXT: hal.command_buffer.copy_buffer<%[[CMD]] : !hal.command_buffer>
+    // CHECK-SAME: source(%arg0 : !hal.buffer)[%c0]
+    // CHECK-SAME: target(%arg2 : !hal.buffer)[%c0]
+    // CHECK-SAME: length(%c128)
+    stream.cmd.copy %arg4[%c0], %arg5[%c0], %c128 : !stream.resource<transient>{%arg1} -> !stream.resource<staging>{%arg3}
+    // CHECK-NEXT: hal.command_buffer.execution_barrier<%[[CMD]]
+  } => !stream.timepoint
+  // CHECK-NEXT: hal.command_buffer.end<%[[CMD]]
+  // CHECK-NEXT: hal.ex.submit_and_wait
+  return %0 : !stream.timepoint
+}
+
+// -----
+
+// NOTE: we don't currently do anything smart with the DAG because we aren't
+// actually partitioning for that yet. This causes us to insert more barriers
+// than we actually need and guard a lot more work than we otherwise would need
+// to.
+
+// CHECK-LABEL: @cmdExecute
+func.func @cmdExecute(%arg0: !stream.resource<transient>, %arg1: index, %arg2: !stream.resource<staging>, %arg3: index, %arg4: !stream.timepoint) -> !stream.timepoint {
+  %c0 = arith.constant 0 : index
+  %c128 = arith.constant 128 : index
+  // CHECK: %[[CMD:.+]] = hal.command_buffer.create
+  // CHECK-NEXT: hal.command_buffer.begin<%[[CMD]]
+  %0 = stream.cmd.execute await(%arg4) => with(%arg0 as %arg5: !stream.resource<transient>{%arg1}, %arg2 as %arg6: !stream.resource<staging>{%arg3}) {
+    stream.cmd.concurrent {
+      // CHECK-NEXT: hal.command_buffer.copy_buffer<%[[CMD]]
+      stream.cmd.copy %arg5[%c0], %arg6[%c0], %c128 : !stream.resource<transient>{%arg1} -> !stream.resource<staging>{%arg3}
+      // CHECK-NEXT: hal.command_buffer.copy_buffer<%[[CMD]]
+      stream.cmd.copy %arg5[%c0], %arg6[%c0], %c128 : !stream.resource<transient>{%arg1} -> !stream.resource<staging>{%arg3}
+      stream.cmd.serial {
+        // CHECK-NEXT: hal.command_buffer.copy_buffer<%[[CMD]]
+        // CHECK-NEXT: hal.command_buffer.execution_barrier<%[[CMD]]
+        stream.cmd.copy %arg5[%c0], %arg6[%c0], %c128 : !stream.resource<transient>{%arg1} -> !stream.resource<staging>{%arg3}
+        // CHECK-NEXT: hal.command_buffer.copy_buffer<%[[CMD]]
+        // CHECK-NEXT: hal.command_buffer.execution_barrier<%[[CMD]]
+        stream.cmd.copy %arg5[%c0], %arg6[%c0], %c128 : !stream.resource<transient>{%arg1} -> !stream.resource<staging>{%arg3}
+      }
+      // CHECK-NEXT: hal.command_buffer.copy_buffer<%[[CMD]]
+      stream.cmd.copy %arg5[%c0], %arg6[%c0], %c128 : !stream.resource<transient>{%arg1} -> !stream.resource<staging>{%arg3}
+      // CHECK-NEXT: hal.command_buffer.execution_barrier<%[[CMD]]
+    }
+  } => !stream.timepoint
+  // CHECK-NEXT: hal.command_buffer.end<%[[CMD]]
+  // CHECK-NEXT: hal.ex.submit_and_wait
+  return %0 : !stream.timepoint
+}
+
+// -----
+
+#executable_target_embedded_elf_x86_64_ = #hal.executable.target<"llvm", "embedded-elf-x86_64">
+#device_target_cpu = #hal.device.target<"cpu", {
+  executable_targets = [#executable_target_embedded_elf_x86_64_]
+}>
+#executable_layout = #hal.executable.layout<push_constants = 0, sets = [
+  #hal.descriptor_set.layout<0, bindings = [
+    #hal.descriptor_set.binding<4, storage_buffer>
+  ]>,
+  #hal.descriptor_set.layout<1, bindings = [
+    #hal.descriptor_set.binding<5, storage_buffer>
+  ]>
+]>
+hal.executable private @ex {
+  hal.executable.variant public @embedded_elf_x86_64, target = #executable_target_embedded_elf_x86_64_ {
+    hal.executable.export public @dispatch ordinal(0) layout(#executable_layout) {
+      translation_info = #iree_codegen.translation_info<CPUDefault workload_per_wg = [4]>
+    } {
+    ^bb0(%device: !hal.device, %arg0: index, %arg1: index, %arg2: index):  // no predecessors
+      %c1 = arith.constant 1 : index
+      %0 = affine.apply affine_map<()[s0] -> (s0 ceildiv 4)>()[%arg0]
+      hal.return %0, %c1, %c1 : index, index, index
+    }
+    builtin.module {
+      // Opaque at this point (in some target-specific dialects).
+    }
+  }
+}
+
+// CHECK-LABEL: @cmdDispatch
+func.func @cmdDispatch(%arg0: !stream.resource<transient>, %arg1: index, %arg2: !stream.resource<external>, %arg3: index) -> !stream.timepoint {
+  %c0 = arith.constant 0 : index
+  %c1 = arith.constant 1 : index
+  %c2 = arith.constant 2 : index
+  %c3 = arith.constant 3 : index
+  %c4_i32 = arith.constant 4 : i32
+  %c5_i32 = arith.constant 5 : i32
+  %c128 = arith.constant 128 : index
+  // CHECK: %[[CMD:.+]] = hal.command_buffer.create
+  // CHECK-NEXT: hal.command_buffer.begin<%[[CMD]]
+  %0 = stream.cmd.execute with(%arg0 as %arg4: !stream.resource<transient>{%arg1}, %arg2 as %arg5: !stream.resource<external>{%arg3}) {
+    // Switch for each executable variant:
+    // CHECK: hal.device.switch
+    // CHECK-NEXT: #hal.device.match.executable.format<"embedded-elf-x86_64">
+
+    // Cache queries:
+    //  CHECK-DAG:   %[[LAYOUT:.+]] = hal.executable_layout.lookup {{.+}} layout(#executable_layout)
+
+    // Push constants:
+    //  CHECK-DAG:   hal.command_buffer.push_constants<%[[CMD]]
+    // CHECK-SAME:       layout(%[[LAYOUT]] : !hal.executable_layout)
+    // CHECK-SAME:       offset(0)
+    // CHECK-SAME:       values([%c4_i32, %c5_i32]) : i32, i32
+
+    // Descriptor sets:
+    //  CHECK-DAG:   hal.command_buffer.push_descriptor_set<%[[CMD]]
+    // CHECK-SAME:       layout(%[[LAYOUT]] : !hal.executable_layout)[%c0
+    // CHECK-NEXT:     %c4 = (%arg0 : !hal.buffer)[%c0, %c128]
+    //  CHECK-DAG:   hal.command_buffer.push_descriptor_set<%[[CMD]]
+    // CHECK-SAME:       layout(%[[LAYOUT]] : !hal.executable_layout)[%c1
+    // CHECK-NEXT:     %c5 = (%arg2 : !hal.buffer)[%c0, %c128]
+
+    // Inlined workgroup count calculation:
+    // CHECK: %[[YZ:.+]] = arith.constant 1 : index
+    // CHECK-NEXT: %[[X:.+]] = affine.apply #map()[%c1]
+
+    // Dispatch:
+    // CHECK: hal.command_buffer.dispatch.symbol<%[[CMD]]
+    // CHECK-SAME: target(@ex::@embedded_elf_x86_64::@dispatch)
+    // CHECK-SAME: workgroups([%[[X]], %[[YZ]], %[[YZ]]])
+    stream.cmd.dispatch @ex::@dispatch[%c1, %c2, %c3](%c4_i32, %c5_i32 : i32, i32) {
+      ro %arg4[%c0 for %c128] : !stream.resource<transient>{%arg1},
+      wo %arg5[%c0 for %c128] : !stream.resource<external>{%arg3}
+    } attributes {
+      hal.interface.bindings = [
+        #hal.interface.binding<0, 4>,
+        #hal.interface.binding<1, 5>
+      ]
+    }
+    // CHECK: hal.command_buffer.execution_barrier<%[[CMD]]
+  } => !stream.timepoint
+  // CHECK-NEXT: hal.command_buffer.end<%[[CMD]]
+  // CHECK-NEXT: hal.ex.submit_and_wait
+  return %0 : !stream.timepoint
 }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/resource_ops.mlir b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/resource_ops.mlir
index e1fdd71..cf5a6bd 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/resource_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/resource_ops.mlir
@@ -1,7 +1,146 @@
 // RUN: iree-opt --split-input-file --iree-hal-conversion %s | FileCheck %s
 
-// TODO(#7277): add new streams->hal conversion tests.
-// CHECK: @todo
-func.func @todo() {
+// CHECK-LABEL: @resourceAlloc
+func.func @resourceAlloc(%arg0: index, %arg1: index) -> (!stream.resource<transient>, !stream.resource<transient>) {
+  // CHECK: %[[RET0:.+]] = hal.allocator.allocate
+  // CHECK-SAME: type("DeviceVisible|DeviceLocal")
+  // CHECK-SAME: usage("{{.+}}Transfer{{.+}}Dispatch{{.+}}")
+  // CHECK-SAME: : !hal.buffer{%arg0}
+  // CHECK-NEXT: %[[RET1:.+]] = hal.allocator.allocate
+  // CHECK-SAME: type("DeviceVisible|DeviceLocal")
+  // CHECK-SAME: usage("{{.+}}Transfer{{.+}}Dispatch{{.+}}")
+  // CHECK-SAME: : !hal.buffer{%arg1}
+  %0:2 = stream.resource.alloc uninitialized : !stream.resource<transient>{%arg0}, !stream.resource<transient>{%arg1}
+  // CHECK: return %[[RET0]], %[[RET1]]
+  return %0#0, %0#1 : !stream.resource<transient>, !stream.resource<transient>
+}
+
+// -----
+
+// TODO(#9572): implement stream ordered allocations.
+
+// CHECK-LABEL: @resourceAlloca
+func.func @resourceAlloca(%arg0: index, %await_timepoint: !stream.timepoint) -> (!stream.resource<staging>, !stream.timepoint) {
+  // CHECK: %[[RET0:.+]] = hal.allocator.allocate
+  // CHECK-SAME: type("DeviceVisible|DeviceLocal")
+  // CHECK-SAME: usage("{{.+}}Transfer{{.+}}Dispatch{{.+}}")
+  // CHECK-SAME: : !hal.buffer{%arg0}
+  %0:2 = stream.resource.alloca uninitialized : !stream.resource<staging>{%arg0} => !stream.timepoint
+  // CHECK: %[[IMMEDIATE:.+]] = arith.constant 0 : index
+  // CHECK: return %[[RET0]], %[[IMMEDIATE]]
+  return %0#0, %0#1 : !stream.resource<staging>, !stream.timepoint
+}
+
+// -----
+
+// TODO(#9572): implement stream ordered allocations.
+
+// CHECK-LABEL: @resourceAllocaAwait
+func.func @resourceAllocaAwait(%arg0: index, %await_timepoint: !stream.timepoint) -> (!stream.resource<staging>, !stream.timepoint) {
+  // CHECK: %[[RET0:.+]] = hal.allocator.allocate
+  // CHECK-SAME: type("DeviceVisible|DeviceLocal")
+  // CHECK-SAME: usage("{{.+}}Transfer{{.+}}Dispatch{{.+}}")
+  // CHECK-SAME: : !hal.buffer{%arg0}
+  %0:2 = stream.resource.alloca uninitialized await(%await_timepoint) => !stream.resource<staging>{%arg0} => !stream.timepoint
+  // CHECK: %[[IMMEDIATE:.+]] = arith.constant 0 : index
+  // CHECK: return %[[RET0]], %[[IMMEDIATE]]
+  return %0#0, %0#1 : !stream.resource<staging>, !stream.timepoint
+}
+
+// -----
+
+// TODO(#9572): implement stream ordered allocations.
+
+// CHECK-LABEL: @resourceDealloca
+func.func @resourceDealloca(%arg0: index, %arg1: !stream.resource<staging>, %arg2: !stream.timepoint) -> !stream.timepoint {
+  %0 = stream.resource.dealloca %arg1 : !stream.resource<staging>{%arg0} => !stream.timepoint
+  // CHECK: %[[IMMEDIATE:.+]] = arith.constant 0 : index
+  // CHECK: return %[[IMMEDIATE]]
+  return %0 : !stream.timepoint
+}
+
+// -----
+
+// TODO(#9572): implement stream ordered allocations.
+
+// CHECK-LABEL: @resourceDeallocaAwait
+func.func @resourceDeallocaAwait(%arg0: index, %arg1: !stream.resource<staging>, %arg2: !stream.timepoint) -> !stream.timepoint {
+  %0 = stream.resource.dealloca await(%arg2) => %arg1 : !stream.resource<staging>{%arg0} => !stream.timepoint
+  // CHECK: %[[IMMEDIATE:.+]] = arith.constant 0 : index
+  // CHECK: return %[[IMMEDIATE]]
+  return %0 : !stream.timepoint
+}
+
+// -----
+
+// CHECK-LABEL: @resourceSize
+func.func @resourceSize(%arg0: !stream.resource<transient>) -> index {
+  // CHECK: %[[SIZE:.+]] = hal.buffer.length<%arg0 : !hal.buffer> : index
+  %0 = stream.resource.size %arg0 : !stream.resource<transient>
+  // CHECK: return %[[SIZE]]
+  return %0 : index
+}
+
+// -----
+
+// CHECK-LABEL: @resourceMap
+func.func @resourceMap(%arg0: !util.byte_buffer) -> !stream.resource<staging> {
+  %c0 = arith.constant 0 : index
+  %c128 = arith.constant 128 : index
+  // CHECK: %[[MAPPING:.+]] = hal.allocator.map
+  // CHECK-SAME: source(%arg0 : !util.byte_buffer)[%c0, %c128]
+  // CHECK-SAME: type("HostVisible|HostCoherent|HostLocal|DeviceVisible")
+  // CHECK-SAME: usage("{{.+}}Transfer{{.+}}Mapping{{.+}}") : !hal.buffer
+  %mapping = stream.resource.map %arg0[%c0] : !util.byte_buffer -> !stream.resource<staging>{%c128}
+  // CHECK: return %[[MAPPING]]
+  return %mapping : !stream.resource<staging>
+}
+
+// -----
+
+// CHECK-LABEL: @resourceTryMap
+func.func @resourceTryMap(%arg0: !util.byte_buffer) -> (i1, !stream.resource<constant>) {
+  %c0 = arith.constant 0 : index
+  %c128 = arith.constant 128 : index
+  // CHECK: %[[DID_MAP:.+]], %[[MAPPING:.+]] = hal.allocator.try_map
+  // CHECK-SAME: source(%arg0 : !util.byte_buffer)[%c0, %c128]
+  // CHECK-SAME: type("DeviceVisible|DeviceLocal")
+  // CHECK-SAME: usage("{{.+}}Transfer{{.+}}Dispatch{{.+}}SharingImmutable") : i1, !hal.
+  %did_map, %mapping = stream.resource.try_map %arg0[%c0] : !util.byte_buffer -> i1, !stream.resource<constant>{%c128}
+  // CHECK: return %[[DID_MAP]], %[[MAPPING]]
+  return %did_map, %mapping : i1, !stream.resource<constant>
+}
+
+// -----
+
+// CHECK-LABEL: @resourceLoad
+func.func @resourceLoad(%arg0: !stream.resource<staging>, %arg1: index) -> i32 {
+  %c4 = arith.constant 4 : index
+  // CHECK: %[[RET0:.+]] = hal.buffer.load<%arg0 : !hal.buffer>[%c4] : i32
+  %0 = stream.resource.load %arg0[%c4] : !stream.resource<staging>{%arg1} -> i32
+  // CHECK: return %[[RET0]]
+  return %0 : i32
+}
+
+// -----
+
+// CHECK-LABEL: @resourceStore
+func.func @resourceStore(%arg0: !stream.resource<staging>, %arg1: index) {
+  %c4 = arith.constant 4 : index
+  %c123_i32 = arith.constant 123 : i32
+  // CHECK: hal.buffer.store<%arg0 : !hal.buffer>[%c4] value(%c123_i32 : i32)
+  stream.resource.store %c123_i32, %arg0[%c4] : i32 -> !stream.resource<staging>{%arg1}
   return
 }
+
+// -----
+
+// CHECK-LABEL: @resourceSubview
+func.func @resourceSubview(%arg0: !stream.resource<transient>, %arg1: index) -> !stream.resource<transient> {
+  %c128 = arith.constant 128 : index
+  %c256 = arith.constant 256 : index
+  // CHECK: %[[RET0:.+]] = hal.buffer.subspan<%arg0 : !hal.buffer>[%c128, %c256] : !hal.buffer
+  %0 = stream.resource.subview %arg0[%c128] : !stream.resource<transient>{%arg1} -> !stream.resource<transient>{%c256}
+  // CHECK: return %[[RET0]]
+  return %0 : !stream.resource<transient>
+}
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/timepoint_ops.mlir b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/timepoint_ops.mlir
index e1fdd71..38e9722 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/timepoint_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/timepoint_ops.mlir
@@ -1,7 +1,71 @@
 // RUN: iree-opt --split-input-file --iree-hal-conversion %s | FileCheck %s
 
-// TODO(#7277): add new streams->hal conversion tests.
-// CHECK: @todo
-func.func @todo() {
-  return
+// TODO(#1285): implement timepoint lowering into HAL semaphores.
+// For now all timepoints turn into ints and are mostly ignored.
+
+// CHECK-LABEL: @rwTimepoint
+// CHECK-SAME: = 0 : index
+util.global private mutable @rwTimepoint = #stream.timepoint<immediate>
+// CHECK: func.func @globalTimepoint(%arg0: index) -> index
+func.func @globalTimepoint(%arg0: !stream.timepoint) -> !stream.timepoint {
+  // CHECK: util.global.store %arg0, @rwTimepoint
+  util.global.store %arg0, @rwTimepoint : !stream.timepoint
+  // CHECK: %[[VALUE:.+]] = util.global.load @rwTimepoint
+  %value = util.global.load @rwTimepoint : !stream.timepoint
+  // CHECK: return %[[VALUE]]
+  return %value : !stream.timepoint
+}
+
+// -----
+
+// CHECK-LABEL: @timepointImmediate
+func.func @timepointImmediate() -> !stream.timepoint {
+  // CHECK: %[[TIMEPOINT:.+]] = arith.constant 0
+  %0 = stream.timepoint.immediate => !stream.timepoint
+  // CHECK: return %[[TIMEPOINT]]
+  return %0 : !stream.timepoint
+}
+
+// -----
+
+// CHECK-LABEL: @timepointImport
+func.func @timepointImport(%arg0: !hal.semaphore, %arg1: index) -> !stream.timepoint {
+  // CHECK: %[[WAIT_OK:.+]] = hal.semaphore.await<%arg0 : !hal.semaphore> until(%arg1) : i32
+  // CHECK: util.status.check_ok %[[WAIT_OK]]
+  // CHECK: %[[TIMEPOINT:.+]] = arith.constant 0
+  %0 = stream.timepoint.import %arg0, %arg1 : (!hal.semaphore, index) => !stream.timepoint
+  // CHECK: return %[[TIMEPOINT]]
+  return %0 : !stream.timepoint
+}
+
+// -----
+
+// CHECK-LABEL: @timepointExport
+func.func @timepointExport(%arg0: !stream.timepoint) -> (!hal.semaphore, index) {
+  // CHECK: %[[TIMEPOINT:.+]] = arith.constant 0
+  // CHECK: %[[SEMAPHORE:.+]] = hal.semaphore.create device(%device : !hal.device) initial(%c0) : !hal.semaphore
+  %0:2 = stream.timepoint.export %arg0 => (!hal.semaphore, index)
+  // CHECK: return %[[SEMAPHORE]], %[[TIMEPOINT]]
+  return %0#0, %0#1 : !hal.semaphore, index
+}
+
+// -----
+
+// CHECK-LABEL: @timepointJoin
+func.func @timepointJoin(%arg0: !stream.timepoint, %arg1: !stream.timepoint) -> !stream.timepoint {
+  // CHECK: %[[TIMEPOINT:.+]] = arith.constant 0
+  %0 = stream.timepoint.join max(%arg0, %arg1) => !stream.timepoint
+  // CHECK: return %[[TIMEPOINT]]
+  return %0 : !stream.timepoint
+}
+
+// -----
+
+// CHECK-LABEL: @timepointAwait
+func.func @timepointAwait(%arg0: !stream.timepoint, %arg1: !stream.resource<staging>, %arg2: !stream.resource<*>) -> (!stream.resource<staging>, !stream.resource<*>) {
+  %c100 = arith.constant 100 : index
+  %c200 = arith.constant 200 : index
+  %0:2 = stream.timepoint.await %arg0 => %arg1, %arg2 : !stream.resource<staging>{%c100}, !stream.resource<*>{%c200}
+  // CHECK: return %arg1, %arg2
+  return %0#0, %0#1 : !stream.resource<staging>, !stream.resource<*>
 }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/transfer_ops.mlir b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/transfer_ops.mlir
index e1fdd71..046dfc0 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/transfer_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/test/transfer_ops.mlir
@@ -1,7 +1,64 @@
 // RUN: iree-opt --split-input-file --iree-hal-conversion %s | FileCheck %s
 
-// TODO(#7277): add new streams->hal conversion tests.
-// CHECK: @todo
-func.func @todo() {
-  return
+// CHECK-LABEL: @tensorImportBuffer
+func.func @tensorImportBuffer(%arg0: !hal.buffer, %arg1: index) -> !stream.resource<external> {
+  %c20 = arith.constant 20 : index
+  // CHECK-DAG: %[[ALLOCATOR:.+]] = hal.device.allocator
+  // CHECK: hal.buffer.assert<%arg0 : !hal.buffer>
+  // CHECK-SAME: message("tensor")
+  // CHECK-SAME: allocator(%[[ALLOCATOR]] : !hal.allocator)
+  // CHECK-SAME: minimum_length(%c20)
+  // CHECK-SAME: type(DeviceVisible)
+  // CHECK-SAME: usage("Transfer{{.+}}Dispatch{{.+}}")
+  %0 = stream.tensor.import %arg0 : !hal.buffer -> tensor<?x5xf32>{%arg1} in !stream.resource<external>{%c20}
+  // CHECK: return %arg0
+  return %0 : !stream.resource<external>
+}
+
+// -----
+
+// NOTE: buffer view metadata assertions via hal.buffer_view.assert are added
+// when lowering into the stream dialect; here we only care about the storage
+// buffer itself.
+
+// CHECK-LABEL: @tensorImportBufferView
+func.func @tensorImportBufferView(%arg0: !hal.buffer_view, %arg1: index) -> !stream.resource<external> {
+  %c20 = arith.constant 20 : index
+  // CHECK-DAG: %[[BUFFER:.+]] = hal.buffer_view.buffer<%arg0 : !hal.buffer_view> : !hal.buffer
+  // CHECK-DAG: %[[ALLOCATOR:.+]] = hal.device.allocator
+  // CHECK: hal.buffer.assert<%[[BUFFER]] : !hal.buffer>
+  // CHECK-SAME: message("tensor")
+  // CHECK-SAME: allocator(%[[ALLOCATOR]] : !hal.allocator)
+  // CHECK-SAME: minimum_length(%c20)
+  // CHECK-SAME: type(DeviceVisible)
+  // CHECK-SAME: usage("Transfer{{.+}}Dispatch{{.+}}")
+  %0 = stream.tensor.import %arg0 : !hal.buffer_view -> tensor<?x5xf32>{%arg1} in !stream.resource<external>{%c20}
+  // CHECK: return %[[BUFFER]]
+  return %0 : !stream.resource<external>
+}
+
+// -----
+
+// CHECK-LABEL: @tensorExportBuffer
+func.func @tensorExportBuffer(%arg0: !stream.resource<external>, %arg1: index) -> !hal.buffer {
+  %c200 = arith.constant 200 : index
+  %0 = stream.tensor.export %arg0 : tensor<?x1x10xf32>{%arg1} in !stream.resource<external>{%c200} -> !hal.buffer
+  // CHECK: return %arg0 : !hal.buffer
+  return %0 : !hal.buffer
+}
+
+// -----
+
+// CHECK-LABEL: @tensorExportBufferView
+func.func @tensorExportBufferView(%arg0: !stream.resource<external>, %arg1: index) -> !hal.buffer_view {
+  %c200 = arith.constant 200 : index
+  // CHECK: %[[VIEW:.+]] = hal.buffer_view.create
+  // CHECK-SAME: buffer(%arg0 : !hal.buffer)
+  // CHECK-SAME: shape([%arg1, %c1, %c10])
+  // CHECK-SAME: type(%c553648160_i32)
+  // CHECK-SAME: encoding(%c1_i32)
+  // CHECK-SAME: : !hal.buffer_view
+  %0 = stream.tensor.export %arg0 : tensor<?x1x10xf32>{%arg1} in !stream.resource<external>{%c200} -> !hal.buffer_view
+  // CHECK: return %[[VIEW]]
+  return %0 : !hal.buffer_view
 }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/UtilToHAL/test/global_ops.mlir b/compiler/src/iree/compiler/Dialect/HAL/Conversion/UtilToHAL/test/global_ops.mlir
index e1fdd71..60354de 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/UtilToHAL/test/global_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/UtilToHAL/test/global_ops.mlir
@@ -1,7 +1,19 @@
 // RUN: iree-opt --split-input-file --iree-hal-conversion %s | FileCheck %s
 
-// TODO(#7277): add new streams->hal conversion tests.
-// CHECK: @todo
-func.func @todo() {
-  return
+// NOTE: timepoints are tested in StreamToHAL/test/timepoint_ops.mlir because
+// their usage is more tied to the ops loading/storing the globals. This file
+// just tests the generic !stream.* type globals.
+
+// CHECK-: util.global private mutable @resource : !hal.buffer
+util.global private mutable @resource : !stream.resource<variable>
+
+// CHECK-LABEL: @resourceGlobals
+// CHECK-SAME: (%[[ARG0:.+]]: !hal.buffer) -> !hal.buffer
+func.func private @resourceGlobals(%arg0: !stream.resource<variable>) -> !stream.resource<variable> {
+  // CHECK: util.global.store %[[ARG0]], @resource : !hal.buffer
+  util.global.store %arg0, @resource : !stream.resource<variable>
+  // CHECK: %[[VALUE:.+]] = util.global.load @resource : !hal.buffer
+  %value = util.global.load @resource : !stream.resource<variable>
+  // CHECK: return %[[VALUE]]
+  return %value : !stream.resource<variable>
 }