Integrate LLVM to llvm/llvm-project@75b7809248cc (#24609)

Adapted region successors's parent() to constructing from
op.getOperation() and from isParent() to isOperation() due to LLVM
upstream change 6e6c296f2014 [mlir] Use explicit op targets for region
successors (#203552)

Adapting to removal of emitc::ApplyOp, using emitc::AddressOfOp or
emitc::SubscriptOp + emitc::LoadOp instead ba7be6262c71 [mlir][emitc]
Remove deprecated apply op (#203712)

These fixes have been assisted by Claude Code and have been manually
reviewed.

Updated torch-mlir submodule as well due to LLVM changes.

Signed-off-by: Stefan Schuermans <schuermans@roofline.ai>
diff --git a/compiler/src/iree/compiler/API/api_exports.c b/compiler/src/iree/compiler/API/api_exports.c
index 31a69d2..7542886 100644
--- a/compiler/src/iree/compiler/API/api_exports.c
+++ b/compiler/src/iree/compiler/API/api_exports.c
@@ -711,6 +711,7 @@
 extern void mlirLinalgInferContractionDimensions();
 extern void mlirLinalgInferContractionDimensionsFromMaps();
 extern void mlirLinalgInferConvolutionDimensions();
+extern void mlirLinalgInferConvolutionDimensionsFromMaps();
 extern void mlirLinalgIsAContractionOp();
 extern void mlirLinalgIsAConvolutionOp();
 extern void mlirLlvmRawFdOStreamCreate();
@@ -1887,6 +1888,7 @@
   x += (uintptr_t)&mlirLinalgInferContractionDimensions;
   x += (uintptr_t)&mlirLinalgInferContractionDimensionsFromMaps;
   x += (uintptr_t)&mlirLinalgInferConvolutionDimensions;
+  x += (uintptr_t)&mlirLinalgInferConvolutionDimensionsFromMaps;
   x += (uintptr_t)&mlirLinalgIsAContractionOp;
   x += (uintptr_t)&mlirLinalgIsAConvolutionOp;
   x += (uintptr_t)&mlirLlvmRawFdOStreamCreate;
diff --git a/compiler/src/iree/compiler/API/api_exports.def b/compiler/src/iree/compiler/API/api_exports.def
index c62f008..eb7fa77 100644
--- a/compiler/src/iree/compiler/API/api_exports.def
+++ b/compiler/src/iree/compiler/API/api_exports.def
@@ -701,6 +701,7 @@
   mlirLinalgInferContractionDimensions
   mlirLinalgInferContractionDimensionsFromMaps
   mlirLinalgInferConvolutionDimensions
+  mlirLinalgInferConvolutionDimensionsFromMaps
   mlirLinalgIsAContractionOp
   mlirLinalgIsAConvolutionOp
   mlirLlvmRawFdOStreamCreate
diff --git a/compiler/src/iree/compiler/API/api_exports.ld b/compiler/src/iree/compiler/API/api_exports.ld
index 902f3c9..d879b7c 100644
--- a/compiler/src/iree/compiler/API/api_exports.ld
+++ b/compiler/src/iree/compiler/API/api_exports.ld
@@ -702,6 +702,7 @@
     mlirLinalgInferContractionDimensions;
     mlirLinalgInferContractionDimensionsFromMaps;
     mlirLinalgInferConvolutionDimensions;
+    mlirLinalgInferConvolutionDimensionsFromMaps;
     mlirLinalgIsAContractionOp;
     mlirLinalgIsAConvolutionOp;
     mlirLlvmRawFdOStreamCreate;
diff --git a/compiler/src/iree/compiler/API/api_exports.macos.lst b/compiler/src/iree/compiler/API/api_exports.macos.lst
index fc7d0fa..b65bd5c 100644
--- a/compiler/src/iree/compiler/API/api_exports.macos.lst
+++ b/compiler/src/iree/compiler/API/api_exports.macos.lst
@@ -700,6 +700,7 @@
 _mlirLinalgInferContractionDimensions
 _mlirLinalgInferContractionDimensionsFromMaps
 _mlirLinalgInferConvolutionDimensions
+_mlirLinalgInferConvolutionDimensionsFromMaps
 _mlirLinalgIsAContractionOp
 _mlirLinalgIsAConvolutionOp
 _mlirLlvmRawFdOStreamCreate
diff --git a/compiler/src/iree/compiler/Codegen/Dialect/PCF/IR/PCFOps.cpp b/compiler/src/iree/compiler/Codegen/Dialect/PCF/IR/PCFOps.cpp
index 57de579..9bf9d62 100644
--- a/compiler/src/iree/compiler/Codegen/Dialect/PCF/IR/PCFOps.cpp
+++ b/compiler/src/iree/compiler/Codegen/Dialect/PCF/IR/PCFOps.cpp
@@ -656,7 +656,7 @@
 }
 
 ValueRange LoopOp::getSuccessorInputs(RegionSuccessor successor) {
-  return successor.isParent() ? getOperation()->getResults() : ValueRange();
+  return successor.isOperation() ? getOperation()->getResults() : ValueRange();
 }
 
 void LoopOp::getSuccessorRegions(RegionBranchPoint point,
@@ -668,7 +668,7 @@
   }
 
   // Otherwise, the region branches back to the parent operation.
-  regions.push_back(RegionSuccessor::parent());
+  regions.push_back(RegionSuccessor(getOperation()));
 }
 
 SmallVector<int64_t> LoopOp::getInitTiedResultIndices() {
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
index 566c1ba..91aec1e 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
@@ -1023,7 +1023,7 @@
 }
 
 ValueRange DeviceMemoizeOp::getSuccessorInputs(RegionSuccessor successor) {
-  return successor.isParent() ? getOperation()->getResults() : ValueRange();
+  return successor.isOperation() ? getOperation()->getResults() : ValueRange();
 }
 
 void DeviceMemoizeOp::getSuccessorRegions(
@@ -1032,7 +1032,7 @@
   // return the correct RegionSuccessor purely based on the index being None or
   // 0.
   if (!point.isParent()) {
-    regions.push_back(RegionSuccessor::parent());
+    regions.push_back(RegionSuccessor(getOperation()));
   } else {
     regions.push_back(RegionSuccessor(&getBody()));
   }
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
index 4848f58..9901fc8 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
@@ -3524,8 +3524,8 @@
 }
 
 ValueRange AsyncExecuteOp::getSuccessorInputs(RegionSuccessor successor) {
-  return successor.isParent() ? ValueRange(getResults())
-                              : ValueRange(getBodyRegion().getArguments());
+  return successor.isOperation() ? ValueRange(getResults())
+                                 : ValueRange(getBodyRegion().getArguments());
 }
 
 void AsyncExecuteOp::getSuccessorRegions(
@@ -3534,7 +3534,7 @@
   // return the correct RegionSuccessor purely based on the index being None or
   // 0.
   if (!point.isParent()) {
-    regions.push_back(RegionSuccessor::parent());
+    regions.push_back(RegionSuccessor(getOperation()));
   } else {
     regions.push_back(RegionSuccessor(&getBody()));
   }
@@ -3686,8 +3686,8 @@
 }
 
 ValueRange AsyncConcurrentOp::getSuccessorInputs(RegionSuccessor successor) {
-  return successor.isParent() ? ValueRange(getResults())
-                              : ValueRange(getBodyRegion().getArguments());
+  return successor.isOperation() ? ValueRange(getResults())
+                                 : ValueRange(getBodyRegion().getArguments());
 }
 
 void AsyncConcurrentOp::getSuccessorRegions(
@@ -3696,7 +3696,7 @@
   // return the correct RegionSuccessor purely based on the index being None or
   // 0.
   if (!point.isParent()) {
-    regions.push_back(RegionSuccessor::parent());
+    regions.push_back(RegionSuccessor(getOperation()));
   } else {
     regions.push_back(RegionSuccessor(&getBody()));
   }
@@ -4740,8 +4740,8 @@
 }
 
 ValueRange CmdExecuteOp::getSuccessorInputs(RegionSuccessor successor) {
-  return successor.isParent() ? ValueRange()
-                              : ValueRange(getBodyRegion().getArguments());
+  return successor.isOperation() ? ValueRange()
+                                 : ValueRange(getBodyRegion().getArguments());
 }
 
 void CmdExecuteOp::getSuccessorRegions(
@@ -4750,7 +4750,7 @@
   // return the correct RegionSuccessor purely based on the index being None or
   // 0.
   if (!point.isParent()) {
-    regions.push_back(RegionSuccessor::parent());
+    regions.push_back(RegionSuccessor(getOperation()));
   } else {
     regions.push_back(RegionSuccessor(&getBody()));
   }
@@ -4817,7 +4817,7 @@
 }
 
 ValueRange CmdSerialOp::getSuccessorInputs(RegionSuccessor successor) {
-  return successor.isParent() ? getOperation()->getResults() : ValueRange();
+  return successor.isOperation() ? getOperation()->getResults() : ValueRange();
 }
 
 void CmdSerialOp::getSuccessorRegions(
@@ -4826,7 +4826,7 @@
   // return the correct RegionSuccessor purely based on the index being None or
   // 0.
   if (!point.isParent()) {
-    regions.push_back(RegionSuccessor::parent());
+    regions.push_back(RegionSuccessor(getOperation()));
   } else {
     regions.push_back(RegionSuccessor(&getBody()));
   }
@@ -4847,7 +4847,7 @@
 }
 
 ValueRange CmdConcurrentOp::getSuccessorInputs(RegionSuccessor successor) {
-  return successor.isParent() ? getOperation()->getResults() : ValueRange();
+  return successor.isOperation() ? getOperation()->getResults() : ValueRange();
 }
 
 void CmdConcurrentOp::getSuccessorRegions(
@@ -4856,7 +4856,7 @@
   // return the correct RegionSuccessor purely based on the index being None or
   // 0.
   if (!point.isParent()) {
-    regions.push_back(RegionSuccessor::parent());
+    regions.push_back(RegionSuccessor(getOperation()));
   } else {
     regions.push_back(RegionSuccessor(&getBody()));
   }
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideAsyncCopies.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideAsyncCopies.cpp
index e9160f0..7148dd7 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideAsyncCopies.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideAsyncCopies.cpp
@@ -86,7 +86,7 @@
     SmallVector<RegionSuccessor, 2> successors;
     op.getSuccessorRegions(*current, successors);
     for (auto &successor : successors) {
-      if (successor.isParent()) {
+      if (successor.isOperation()) {
         continue;
       }
       Region *target = successor.getSuccessor();
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideTimepoints.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideTimepoints.cpp
index 0478e4e..a867ffe 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideTimepoints.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideTimepoints.cpp
@@ -1489,7 +1489,7 @@
           for (auto successor : successors) {
             // Only handle yields to parent (region -> parent op results).
             // Yields to other regions would require different analysis.
-            if (!successor.isParent()) {
+            if (!successor.isOperation()) {
               continue;
             }
 
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
index a4af37a..b206f27 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
@@ -1176,7 +1176,7 @@
       auto terminatorOp =
           cast<RegionBranchTerminatorOpInterface>(block.getTerminator());
       value = terminatorOp.getSuccessorOperands(
-          RegionSuccessor::parent())[resultIndex];
+          RegionSuccessor(regionOp.getOperation()))[resultIndex];
     } else if (auto tiedOp =
                    dyn_cast<IREE::Util::TiedOpInterface>(definingOp)) {
       // If the producer is tied then try to get the operand.
diff --git a/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp b/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp
index 5b348cc..9c52400 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp
@@ -623,7 +623,8 @@
   return walkReturnOps(parentOp, [&](Operation *returnOp) {
     if (auto terminatorOp =
             dyn_cast<RegionBranchTerminatorOpInterface>(returnOp)) {
-      return fn(terminatorOp.getSuccessorOperands(RegionSuccessor::parent()));
+      return fn(terminatorOp.getSuccessorOperands(
+          RegionSuccessor(terminatorOp->getParentOp())));
     } else {
       return fn(returnOp->getOperands());
     }
@@ -664,7 +665,7 @@
       for (auto &entrySuccessor : entrySuccessors) {
         // Skip parent-exit successors — they represent the region being
         // skipped entirely, so no values flow into the entry block.
-        if (entrySuccessor.isParent()) {
+        if (entrySuccessor.isOperation()) {
           continue;
         }
         if (fn(regionOp->getBlock(),
@@ -1014,7 +1015,7 @@
       // the body entirely). The parent-exit path maps operands to op results,
       // but the body path already covers this connection statically
       // (init_arg → block_arg → yield → result).
-      if (entrySuccessor.isParent()) {
+      if (entrySuccessor.isOperation()) {
         continue;
       }
       auto successorInputs = regionOp.getSuccessorInputs(entrySuccessor);
diff --git a/compiler/src/iree/compiler/Dialect/Util/Analysis/Position.cpp b/compiler/src/iree/compiler/Dialect/Util/Analysis/Position.cpp
index ddaf97d..9b598b7 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Analysis/Position.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Analysis/Position.cpp
@@ -86,7 +86,7 @@
     SmallVector<RegionSuccessor> successors;
     regionOp.getSuccessorRegions(region, successors);
     for (auto &successor : successors) {
-      if (successor.isParent()) {
+      if (successor.isOperation()) {
         return llvm::to_vector(
             getPositions(regionOp.getSuccessorInputs(successor)));
       }
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
index a4bc38f..91039a1 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
@@ -99,15 +99,12 @@
 TypedValue<emitc::PointerType>
 addressOf(OpBuilder builder, Location location,
           TypedValue<emitc::LValueType> operand) {
-  auto ctx = builder.getContext();
-
-  auto result = emitc::ApplyOp::create(
+  auto result = emitc::AddressOfOp::create(
                     builder,
                     /*location=*/location,
                     /*result=*/
                     emitc::PointerType::get(operand.getType().getValueType()),
-                    /*applicableOperator=*/StringAttr::get(ctx, "&"),
-                    /*operand=*/operand)
+                    /*reference=*/operand)
                     .getResult();
 
   return cast<TypedValue<emitc::PointerType>>(result);
@@ -115,16 +112,20 @@
 
 Value contentsOf(OpBuilder builder, Location location, Value operand) {
   auto ctx = builder.getContext();
+  assert(isa<emitc::PointerType>(operand.getType()));
 
-  Type type = operand.getType();
-  assert(isa<emitc::PointerType>(type));
-
-  return emitc::ApplyOp::create(
-             builder,
-             /*location=*/location,
-             /*result=*/cast<emitc::PointerType>(type).getPointee(),
-             /*applicableOperator=*/StringAttr::get(ctx, "*"),
-             /*operand=*/operand)
+  // Dereference the pointer as `ptr[0]`, which is equivalent to `*ptr`. We use
+  // subscript + load rather than emitc.dereference because the latter produces
+  // an lvalue that cannot be emitted when declaring variables at the top of a
+  // function (the mode used for vm-c output).
+  Type indexType = emitc::OpaqueType::get(ctx, "iree_host_size_t");
+  Value indexValue =
+      emitc::LiteralOp::create(builder, location, indexType, "0");
+  TypedValue<emitc::LValueType> subscript = emitc::SubscriptOp::create(
+      builder, location, cast<TypedValue<emitc::PointerType>>(operand),
+      indexValue);
+  return emitc::LoadOp::create(builder, location,
+                               subscript.getType().getValueType(), subscript)
       .getResult();
 }
 
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir
index 057cd14..2f5b307 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir
@@ -6,7 +6,7 @@
     // CHECK: %[[SIZE:.+]] = "emitc.constant"() <{value = 128 : i64}> : () -> i64
     // CHECK-DAG: %[[ALIGNMENT:.+]] = "emitc.constant"() <{value = 32 : i32}> : () -> i32
     // CHECK-DAG: %[[BUFFER_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"NULL">}> : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>>
-    // CHECK-DAG: %[[BUFFER_PTR:.+]] = apply "&"(%[[BUFFER_LVAL]]) : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>>) -> !emitc.ptr<!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>>
+    // CHECK-DAG: %[[BUFFER_PTR:.+]] = address_of %[[BUFFER_LVAL]] : !emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>>
     // CHECK-DAG: %[[STATE_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"struct my_module_state_t">>>
     // CHECK-DAG: assign %arg2 : !emitc.ptr<!emitc.opaque<"struct my_module_state_t">> to %[[STATE_LVAL]] : <!emitc.ptr<!emitc.opaque<"struct my_module_state_t">>>
     // CHECK-DAG: %[[ALLOCATOR_LVAL:.+]] = "emitc.member_of_ptr"(%[[STATE_LVAL]]) <{member = "allocator"}> : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"struct my_module_state_t">>>) -> !emitc.lvalue<!emitc.opaque<"iree_allocator_t">>
@@ -35,13 +35,15 @@
     // CHECK-DAG: %[[ALIGNMENT:.+]] = "emitc.constant"() <{value = 64 : i32}> : () -> i32
 
     // CHECK: %[[BUFFER_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"NULL">}> : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>>
-    // CHECK-DAG: %[[BUFFER_PTR:.+]] = apply "&"(%[[BUFFER_LVAL]]) : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>>) -> !emitc.ptr<!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>>
+    // CHECK-DAG: %[[BUFFER_PTR:.+]] = address_of %[[BUFFER_LVAL]] : !emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>>
     // CHECK-DAG: %[[STATE_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"struct my_module_state_t">>>
     // CHECK-DAG: assign %arg2 : !emitc.ptr<!emitc.opaque<"struct my_module_state_t">> to %[[STATE_LVAL]] : <!emitc.ptr<!emitc.opaque<"struct my_module_state_t">>>
     // CHECK-DAG: %[[ALLOCATOR_LVAL:.+]] = "emitc.member_of_ptr"(%[[STATE_LVAL]]) <{member = "allocator"}> : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"struct my_module_state_t">>>) -> !emitc.lvalue<!emitc.opaque<"iree_allocator_t">>
     // CHECK-DAG: %[[ALLOCATOR:.+]] = load %[[ALLOCATOR_LVAL]] : <!emitc.opaque<"iree_allocator_t">>
     // CHECK-DAG: %[[BUFFER_ACCESS:.+]] = "emitc.constant"() <{value = #emitc.opaque<"IREE_VM_BUFFER_ACCESS_MUTABLE | IREE_VM_BUFFER_ACCESS_ORIGIN_GUEST">}> : () -> !emitc.opaque<"iree_vm_buffer_access_t">
-    // CHECK-DAG: %[[BUFFER_REF2:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK-DAG: %[[BUFFER_REF2_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK-DAG: %[[BUFFER_REF2_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF2_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-DAG: %[[BUFFER_REF2:.+]] = load %[[BUFFER_REF2_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-DAG: %[[BUFFER_PTR2:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF2]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "iree_vm_buffer_clone"(%[[BUFFER_ACCESS]], %[[BUFFER_PTR2]], %[[C0]], %[[C32]], %[[ALIGNMENT]], %[[ALLOCATOR]], %[[BUFFER_PTR]]) : (!emitc.opaque<"iree_vm_buffer_access_t">, !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, i64, i32, !emitc.opaque<"iree_allocator_t">, !emitc.ptr<!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>>) -> !emitc.opaque<"iree_status_t">
@@ -58,7 +60,9 @@
 // CHECK-LABEL: emitc.func private @my_module_buffer_length
 vm.module @my_module {
   vm.func @buffer_length(%buf : !vm.buffer) {
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[LENGTH:.+]] = call_opaque "iree_vm_buffer_length"(%[[BUFFER_PTR]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>) -> i64
@@ -76,14 +80,18 @@
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
     // CHECK: %[[C16:.+]] = "emitc.constant"() <{value = 16 : i64}> : () -> i64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
-    // CHECK: %[[BUFFER_REF2:.+]] = apply "*"(%arg4) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF2_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF2_LVAL:.+]] = subscript %arg4[%[[BUFFER_REF2_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF2:.+]] = load %[[BUFFER_REF2_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR2:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF2]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[RESULT:.+]] = "emitc.variable"() <{value = 0 : i32}> : () -> !emitc.lvalue<i32>
-    // CHECK-NEXT: %[[RESULT_PTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+    // CHECK-NEXT: %[[RESULT_PTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<i32>
     // CHECK-NEXT: %[[STATUS:.+]] = call_opaque "vm_buffer_compare"(%[[BUFFER_PTR]], %[[C0]], %[[BUFFER_PTR2]], %[[C16]], %[[C16]], %[[RESULT_PTR]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, i64, !emitc.ptr<i32>) -> !emitc.opaque<"iree_status_t">
     %c0 = vm.const.i64 0
     %c16 = vm.const.i64 16
@@ -100,10 +108,14 @@
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
     // CHECK: %[[C16:.+]] = "emitc.constant"() <{value = 16 : i64}> : () -> i64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
-    // CHECK: %[[BUFFER_REF2:.+]] = apply "*"(%arg4) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF2_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF2_LVAL:.+]] = subscript %arg4[%[[BUFFER_REF2_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF2:.+]] = load %[[BUFFER_REF2_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR2:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF2]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "iree_vm_buffer_copy_bytes"(%[[BUFFER_PTR]], %[[C0]], %[[BUFFER_PTR2]], %[[C16]], %[[C16]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, i64) -> !emitc.opaque<"iree_status_t">
@@ -123,7 +135,9 @@
     // CHECK: %[[C16:.+]] = "emitc.constant"() <{value = 16 : i64}> : () -> i64
     // CHECK: %[[C102:.+]] = "emitc.constant"() <{value = 102 : i32}> : () -> i32
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "vm_buffer_fill_i8"(%[[BUFFER_PTR]], %[[C0]], %[[C16]], %[[C102]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, i64, i32) -> !emitc.opaque<"iree_status_t">
@@ -162,11 +176,13 @@
   vm.func @buffer_load_i8s(%buf : !vm.buffer) {
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[RESULT:.+]] = "emitc.variable"() <{value = 0 : i32}> : () -> !emitc.lvalue<i32>
-    // CHECK-NEXT: %[[RESULT_PTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+    // CHECK-NEXT: %[[RESULT_PTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<i32>
     // CHECK-NEXT: %[[STATUS:.+]] = call_opaque "vm_buffer_load_i8s"(%[[BUFFER_PTR]], %[[C0]], %[[RESULT_PTR]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, !emitc.ptr<i32>) -> !emitc.opaque<"iree_status_t">
 
     %c0 = vm.const.i64 0
@@ -215,7 +231,9 @@
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
     // CHECK: %[[C102:.+]] = "emitc.constant"() <{value = 102 : i32}> : () -> i32
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "vm_buffer_store_i8"(%[[BUFFER_PTR]], %[[C0]], %[[C102]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, i32) -> !emitc.opaque<"iree_status_t">
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_f32.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_f32.mlir
index bced695..e271d8f 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_f32.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_f32.mlir
@@ -7,7 +7,9 @@
     // CHECK: %[[C16:.+]] = "emitc.constant"() <{value = 16 : i64}> : () -> i64
     // CHECK: %[[C102:.+]] = "emitc.constant"() <{value = 1.020000e+02 : f32}> : () -> f32
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "vm_buffer_fill_f32"(%[[BUFFER_PTR]], %[[C0]], %[[C16]], %[[C102]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, i64, f32) -> !emitc.opaque<"iree_status_t">
@@ -26,11 +28,13 @@
   vm.func @buffer_load_f32(%buf : !vm.buffer) {
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[RESULT:.+]] = "emitc.variable"() <{value = 0.000000e+00 : f32}> : () -> !emitc.lvalue<f32>
-    // CHECK-NEXT: %[[RESULT_PTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<f32>) -> !emitc.ptr<f32>
+    // CHECK-NEXT: %[[RESULT_PTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<f32>
     // CHECK-NEXT: %[[STATUS:.+]] = call_opaque "vm_buffer_load_f32"(%[[BUFFER_PTR]], %[[C0]], %[[RESULT_PTR]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, !emitc.ptr<f32>) -> !emitc.opaque<"iree_status_t">
 
     %c0 = vm.const.i64 0
@@ -47,7 +51,9 @@
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
     // CHECK: %[[C102:.+]] = "emitc.constant"() <{value = 1.020000e+02 : f32}> : () -> f32
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "vm_buffer_store_f32"(%[[BUFFER_PTR]], %[[C0]], %[[C102]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, f32) -> !emitc.opaque<"iree_status_t">
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_f64.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_f64.mlir
index 0951d41..f5f53bb 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_f64.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_f64.mlir
@@ -7,7 +7,9 @@
     // CHECK: %[[C16:.+]] = "emitc.constant"() <{value = 16 : i64}> : () -> i64
     // CHECK: %[[C102:.+]] = "emitc.constant"() <{value = 1.020000e+02 : f64}> : () -> f64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "vm_buffer_fill_f64"(%[[BUFFER_PTR]], %[[C0]], %[[C16]], %[[C102]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, i64, f64) -> !emitc.opaque<"iree_status_t">
@@ -26,11 +28,13 @@
   vm.func @buffer_load_f64(%buf : !vm.buffer) {
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[RESULT:.+]] = "emitc.variable"() <{value = 0.000000e+00 : f64}> : () -> !emitc.lvalue<f64>
-    // CHECK-NEXT: %[[RESULT_PTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<f64>) -> !emitc.ptr<f64>
+    // CHECK-NEXT: %[[RESULT_PTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<f64>
     // CHECK-NEXT: %[[STATUS:.+]] = call_opaque "vm_buffer_load_f64"(%[[BUFFER_PTR]], %[[C0]], %[[RESULT_PTR]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, !emitc.ptr<f64>) -> !emitc.opaque<"iree_status_t">
 
     %c0 = vm.const.i64 0
@@ -47,7 +51,9 @@
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
     // CHECK: %[[C102:.+]] = "emitc.constant"() <{value = 1.020000e+02 : f64}> : () -> f64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "vm_buffer_store_f64"(%[[BUFFER_PTR]], %[[C0]], %[[C102]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, f64) -> !emitc.opaque<"iree_status_t">
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_i64.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_i64.mlir
index d7194d4..5105f82 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_i64.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops_i64.mlir
@@ -7,7 +7,9 @@
     // CHECK: %[[C16:.+]] = "emitc.constant"() <{value = 16 : i64}> : () -> i64
     // CHECK: %[[C102:.+]] = "emitc.constant"() <{value = 102 : i64}> : () -> i64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "vm_buffer_fill_i64"(%[[BUFFER_PTR]], %[[C0]], %[[C16]], %[[C102]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, i64, i64) -> !emitc.opaque<"iree_status_t">
@@ -26,11 +28,13 @@
   vm.func @buffer_load_i64(%buf : !vm.buffer) {
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[RESULT:.+]] = "emitc.variable"() <{value = 0 : i64}> : () -> !emitc.lvalue<i64>
-    // CHECK-NEXT: %[[RESULT_PTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<i64>) -> !emitc.ptr<i64>
+    // CHECK-NEXT: %[[RESULT_PTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<i64>
     // CHECK-NEXT: %[[STATUS:.+]] = call_opaque "vm_buffer_load_i64"(%[[BUFFER_PTR]], %[[C0]], %[[RESULT_PTR]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, !emitc.ptr<i64>) -> !emitc.opaque<"iree_status_t">
 
     %c0 = vm.const.i64 0
@@ -47,7 +51,9 @@
     // CHECK: %[[C0:.+]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
     // CHECK: %[[C102:.+]] = "emitc.constant"() <{value = 102 : i64}> : () -> i64
 
-    // CHECK: %[[BUFFER_REF:.+]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[BUFFER_REF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[BUFFER_REF_LVAL:.+]] = subscript %arg3[%[[BUFFER_REF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[BUFFER_REF:.+]] = load %[[BUFFER_REF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[BUFFER_PTR:.+]] = call_opaque "iree_vm_buffer_deref"(%[[BUFFER_REF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>
 
     // CHECK: %[[STATUS:.+]] = call_opaque "vm_buffer_store_i64"(%[[BUFFER_PTR]], %[[C0]], %[[C102]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_buffer_t">>, i64, i64) -> !emitc.opaque<"iree_status_t">
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/const_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/const_ops.mlir
index 30cc866..bf07a67 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/const_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/const_ops.mlir
@@ -31,7 +31,7 @@
   // CHECK-LABEL: emitc.func private @my_module_const_ref_zero
   vm.func @const_ref_zero() {
     // CHECK: %[[REF:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
-    // CHECK-NEXT: %[[REFPTR:.+]] = apply "&"(%[[REF]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[REFPTR:.+]] = address_of %[[REF]] : !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[SIZE:.+]] = call_opaque "sizeof"() <{args = [!emitc.opaque<"iree_vm_ref_t">]}> : () -> !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: call_opaque "memset"(%[[REFPTR]], %[[SIZE]]) <{args = [0 : index, 0 : ui32, 1 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> ()
     // CHECK-NEXT: call_opaque "iree_vm_ref_release"(%[[REFPTR]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> ()
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/control_flow_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/control_flow_ops.mlir
index 75abd38..7799af1 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/control_flow_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/control_flow_ops.mlir
@@ -73,11 +73,11 @@
     // CHECK-NEXT: %[[IMPORTS:.+]] = load %[[IMPORTS_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>
     // CHECK-NEXT: %[[IMPORT_INDEX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: %[[IMPORT_SUBSCRIPT:.+]] = subscript %[[IMPORTS]][%[[IMPORT_INDEX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
-    // CHECK-NEXT: %[[IMPORT:.+]] = apply "&"(%[[IMPORT_SUBSCRIPT]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_function_t">>
+    // CHECK-NEXT: %[[IMPORT:.+]] = address_of %[[IMPORT_SUBSCRIPT]] : !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
 
     // Create a variable for the function result.
     // CHECK-NEXT: %[[RESULT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
-    // CHECK-NEXT: %[[RESPTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+    // CHECK-NEXT: %[[RESPTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<i32>
 
     // Call the function created by the vm.import conversion.
     // CHECK-NEXT: %{{.+}} = call @my_module_call_[[IMPORTFN]](%arg0, %[[IMPORT]], %arg3, %[[RESPTR]])
@@ -102,11 +102,11 @@
     // CHECK-NEXT: %[[IMPORTS:.+]] = load %[[IMPORTS_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>
     // CHECK-NEXT: %[[IMPORT_INDEX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: %[[IMPORT_SUBSCRIPT:.+]] = subscript %[[IMPORTS]][%[[IMPORT_INDEX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
-    // CHECK-NEXT: %[[IMPORT:.+]] = apply "&"(%[[IMPORT_SUBSCRIPT]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_function_t">>
+    // CHECK-NEXT: %[[IMPORT:.+]] = address_of %[[IMPORT_SUBSCRIPT]] : !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
 
     // Create a variable for the function result.
     // CHECK-NEXT: %[[RESULT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
-    // CHECK-NEXT: %[[RESPTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+    // CHECK-NEXT: %[[RESPTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<i32>
 
     // Call the function created by the vm.import conversion.
     // CHECK-NEXT: %{{.+}} = call @my_module_call_[[IMPORTFN:[^\(]+]](%arg0, %[[IMPORT]], %arg3, %[[RESPTR]])
@@ -133,7 +133,7 @@
 
     // Create a variable for the result.
     // CHECK-NEXT: %[[RESULT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
-    // CHECK-NEXT: %[[RESPTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+    // CHECK-NEXT: %[[RESPTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<i32>
 
     // Call the function created by the vm.import conversion.
     // CHECK-NEXT: %{{.+}} = call @my_module_internal_fn(%arg0, %arg1, %arg2, %arg3, %[[RESPTR]])
@@ -162,14 +162,14 @@
     // CHECK-NEXT: %[[IMPORTS:.+]] = load %[[IMPORTS_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>
     // CHECK-NEXT: %[[IMPORT_INDEX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: %[[IMPORT_SUBSCRIPT:.+]] = subscript %[[IMPORTS]][%[[IMPORT_INDEX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
-    // CHECK-NEXT: %[[IMPORT:.+]] = apply "&"(%[[IMPORT_SUBSCRIPT]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_function_t">>
+    // CHECK-NEXT: %[[IMPORT:.+]] = address_of %[[IMPORT_SUBSCRIPT]] : !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
 
     // This holds the number of variadic arguments.
     // CHECK-NEXT: %[[NARGS:.+]] = "emitc.constant"() <{value = 2 : i32}> : () -> i32
 
     // Create a variable for the result.
     // CHECK-NEXT: %[[RESULT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
-    // CHECK-NEXT: %[[RESPTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+    // CHECK-NEXT: %[[RESPTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<i32>
 
     // Call the function created by the vm.import conversion.
     // CHECK-NEXT: %{{.+}} = call @my_module_call_[[VARIADICFN]](%arg0, %[[IMPORT]], %[[NARGS]], %arg3, %arg4, %[[RESPTR]])
@@ -198,14 +198,14 @@
     // CHECK-NEXT: %[[IMPORTS:.+]] = load %[[IMPORTS_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>
     // CHECK-NEXT: %[[IMPORT_INDEX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: %[[IMPORT_SUBSCRIPT:.+]] = subscript %[[IMPORTS]][%[[IMPORT_INDEX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
-    // CHECK-NEXT: %[[IMPORT:.+]] = apply "&"(%[[IMPORT_SUBSCRIPT]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_function_t">>
+    // CHECK-NEXT: %[[IMPORT:.+]] = address_of %[[IMPORT_SUBSCRIPT]] : !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
 
     // This holds the number of variadic arguments.
     // CHECK-NEXT: %[[NARGS:.+]] = "emitc.constant"() <{value = 0 : i32}> : () -> i32
 
     // Create a variable for the result.
     // CHECK-NEXT: %[[RESULT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
-    // CHECK-NEXT: %[[RESPTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+    // CHECK-NEXT: %[[RESPTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<i32>
 
     // Call the function created by the vm.import conversion.
     // CHECK-NEXT: %{{.+}} = call @my_module_call_[[VARIADICFN]](%arg0, %[[IMPORT]], %[[NARGS]], %[[RESPTR]])
@@ -392,7 +392,9 @@
 
   // Create a struct for the arguments and results.
   // CHECK: %[[ARGSTRUCT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_call_t">>
-  // CHECK-NEXT: %[[ARGSTRUCTFN:.+]] = apply "*"(%arg1) : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.opaque<"iree_vm_function_t">
+  // CHECK-NEXT: %[[ARGSTRUCTFN_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+  // CHECK-NEXT: %[[ARGSTRUCTFN_LVAL:.+]] = subscript %arg1[%[[ARGSTRUCTFN_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
+  // CHECK-NEXT: %[[ARGSTRUCTFN:.+]] = load %[[ARGSTRUCTFN_LVAL]] : <!emitc.opaque<"iree_vm_function_t">>
   // CHECK-NEXT: %[[ARGSTRUCTFN_MEMBER:.+]] = "emitc.member"(%[[ARGSTRUCT]]) <{member = "function"}> : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_call_t">>) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
   // CHECK-NEXT: assign %[[ARGSTRUCTFN]] : !emitc.opaque<"iree_vm_function_t"> to %[[ARGSTRUCTFN_MEMBER]] : <!emitc.opaque<"iree_vm_function_t">>
 
@@ -482,7 +484,9 @@
 
   // Create a struct for the arguments and results.
   // CHECK: %[[ARGSTRUCT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_call_t">>
-  // CHECK-NEXT: %[[ARGSTRUCTFN:.+]] = apply "*"(%arg1) : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.opaque<"iree_vm_function_t">
+  // CHECK-NEXT: %[[ARGSTRUCTFN_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+  // CHECK-NEXT: %[[ARGSTRUCTFN_LVAL:.+]] = subscript %arg1[%[[ARGSTRUCTFN_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
+  // CHECK-NEXT: %[[ARGSTRUCTFN:.+]] = load %[[ARGSTRUCTFN_LVAL]] : <!emitc.opaque<"iree_vm_function_t">>
   // CHECK-NEXT: %[[ARGSTRUCTFN_MEMBER:.+]] = "emitc.member"(%[[ARGSTRUCT]]) <{member = "function"}> : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_call_t">>) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
   // CHECK-NEXT: assign %[[ARGSTRUCTFN]] : !emitc.opaque<"iree_vm_function_t"> to %[[ARGSTRUCTFN_MEMBER]] : <!emitc.opaque<"iree_vm_function_t">>
 
@@ -514,7 +518,7 @@
   // CHECK-NEXT: %[[A1_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
   // CHECK-NEXT: assign %arg2 : i32 to %[[A1_LVAL]] : <i32>
   // CHECK-NEXT: %[[A1SIZE:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
-  // CHECK-NEXT: %[[A1PTR:.+]] = apply "&"(%[[A1_LVAL]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+  // CHECK-NEXT: %[[A1PTR:.+]] = address_of %[[A1_LVAL]] : !emitc.lvalue<i32>
   // CHECK-NEXT: call_opaque "memcpy"(%[[ARGSPTR]], %[[A1PTR]], %[[A1SIZE]])
   // CHECK-NEXT: %[[ARGHOSTSIZE2:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
   // CHECK-NEXT: %[[A1ADDR:.+]] = add %[[ARGSPTR]], %[[ARGHOSTSIZE2]]
@@ -522,7 +526,7 @@
   // CHECK-NEXT: %[[A2_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
   // CHECK-NEXT: assign %arg3 : i32 to %[[A2_LVAL]] : <i32>
   // CHECK-NEXT: %[[A1SIZE:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
-  // CHECK-NEXT: %[[A2PTR:.+]] = apply "&"(%[[A2_LVAL]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+  // CHECK-NEXT: %[[A2PTR:.+]] = address_of %[[A2_LVAL]] : !emitc.lvalue<i32>
   // CHECK-NEXT: call_opaque "memcpy"(%[[A1ADDR]], %[[A2PTR]], %[[A1SIZE]])
   // CHECK-NEXT: %[[A1SIZE2:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
   // CHECK-NEXT: %[[A2ADDR:.+]] = add %[[A1ADDR]], %[[A1SIZE2]]
@@ -530,7 +534,7 @@
   // CHECK-NEXT: %[[A3_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
   // CHECK-NEXT: assign %arg4 : i32 to %[[A3_LVAL]] : <i32>
   // CHECK-NEXT: %[[A2SIZE:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
-  // CHECK-NEXT: %[[A3PTR:.+]] = apply "&"(%[[A3_LVAL]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+  // CHECK-NEXT: %[[A3PTR:.+]] = address_of %[[A3_LVAL]] : !emitc.lvalue<i32>
   // CHECK-NEXT: call_opaque "memcpy"(%[[A2ADDR]], %[[A3PTR]], %[[A2SIZE]])
   // CHECK-NEXT: %[[A2SIZE2:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
   // CHECK-NEXT: %[[A3ADDR:.+]] = add %[[A2ADDR]], %[[A2SIZE2]]
@@ -538,7 +542,7 @@
   // CHECK-NEXT: %[[A4_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
   // CHECK-NEXT: assign %arg5 : i32 to %[[A4_LVAL]] : <i32>
   // CHECK-NEXT: %[[A3SIZE:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
-  // CHECK-NEXT: %[[A4PTR:.+]] = apply "&"(%[[A4_LVAL]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+  // CHECK-NEXT: %[[A4PTR:.+]] = address_of %[[A4_LVAL]] : !emitc.lvalue<i32>
   // CHECK-NEXT: call_opaque "memcpy"(%[[A3ADDR]], %[[A4PTR]], %[[A3SIZE:.+]])
 
   // Create the call to the imported function.
@@ -596,7 +600,9 @@
 
   // Create a struct for the arguments and results.
   // CHECK: %[[ARGSTRUCT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_call_t">>
-  // CHECK-NEXT: %[[ARGSTRUCTFN:.+]] = apply "*"(%arg1) : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.opaque<"iree_vm_function_t">
+  // CHECK-NEXT: %[[ARGSTRUCTFN_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+  // CHECK-NEXT: %[[ARGSTRUCTFN_LVAL:.+]] = subscript %arg1[%[[ARGSTRUCTFN_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
+  // CHECK-NEXT: %[[ARGSTRUCTFN:.+]] = load %[[ARGSTRUCTFN_LVAL]] : <!emitc.opaque<"iree_vm_function_t">>
   // CHECK-NEXT: %[[ARGSTRUCTFN_MEMBER:.+]] = "emitc.member"(%[[ARGSTRUCT]]) <{member = "function"}> : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_call_t">>) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
   // CHECK-NEXT: assign %[[ARGSTRUCTFN]] : !emitc.opaque<"iree_vm_function_t"> to %[[ARGSTRUCTFN_MEMBER]] : <!emitc.opaque<"iree_vm_function_t">>
 
@@ -628,7 +634,7 @@
   // CHECK-NEXT: %[[A1_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
   // CHECK-NEXT: assign %arg2 : i32 to %[[A1_LVAL]] : <i32>
   // CHECK-NEXT: %[[A1SIZE:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
-  // CHECK-NEXT: %[[A1PTR:.+]] = apply "&"(%[[A1_LVAL]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+  // CHECK-NEXT: %[[A1PTR:.+]] = address_of %[[A1_LVAL]] : !emitc.lvalue<i32>
   // CHECK-NEXT: call_opaque "memcpy"(%[[ARGSPTR]], %[[A1PTR]], %[[A1SIZE]])
   // CHECK-NEXT: %[[ARGHOSTSIZE2:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
   // CHECK-NEXT: %[[A1ADDR:.+]] = add %[[ARGSPTR]], %[[ARGHOSTSIZE2]]
@@ -636,7 +642,7 @@
   // CHECK-NEXT: %[[A2_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
   // CHECK-NEXT: assign %arg3 : i32 to %[[A2_LVAL]] : <i32>
   // CHECK-NEXT: %[[A1SIZE:.+]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.opaque<"iree_host_size_t">
-  // CHECK-NEXT: %[[A2PTR:.+]] = apply "&"(%[[A2_LVAL]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+  // CHECK-NEXT: %[[A2PTR:.+]] = address_of %[[A2_LVAL]] : !emitc.lvalue<i32>
   // CHECK-NEXT: call_opaque "memcpy"(%[[A1ADDR]], %[[A2PTR]], %[[A1SIZE]])
 
   // Create the call to the imported function.
@@ -695,7 +701,9 @@
 
   // Create a struct for the arguments and results.
   // CHECK: %[[ARGSTRUCT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_call_t">>
-  // CHECK-NEXT: %[[ARGSTRUCTFN:.+]] = apply "*"(%arg1) : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.opaque<"iree_vm_function_t">
+  // CHECK-NEXT: %[[ARGSTRUCTFN_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+  // CHECK-NEXT: %[[ARGSTRUCTFN_LVAL:.+]] = subscript %arg1[%[[ARGSTRUCTFN_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
+  // CHECK-NEXT: %[[ARGSTRUCTFN:.+]] = load %[[ARGSTRUCTFN_LVAL]] : <!emitc.opaque<"iree_vm_function_t">>
   // CHECK-NEXT: %[[ARGSTRUCTFN_MEMBER:.+]] = "emitc.member"(%[[ARGSTRUCT]]) <{member = "function"}> : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_call_t">>) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
   // CHECK-NEXT: assign %[[ARGSTRUCTFN]] : !emitc.opaque<"iree_vm_function_t"> to %[[ARGSTRUCTFN_MEMBER]] : <!emitc.opaque<"iree_vm_function_t">>
 
@@ -797,7 +805,7 @@
 
   // Unpack the result pointer from the struct.
   // CHECK-NEXT: %[[RESULT_LVAL:.+]] = "emitc.member_of_ptr"(%[[RESULTS_LVAL]]) <{member = "res0"}> : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"struct my_module_fn_result_t">>>) -> !emitc.lvalue<i32>
-  // CHECK-NEXT: %[[RES:.+]] = apply "&"(%[[RESULT_LVAL]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+  // CHECK-NEXT: %[[RES:.+]] = address_of %[[RESULT_LVAL]] : !emitc.lvalue<i32>
 
   // Call the internal function.
   // CHECK-NEXT: %{{.+}} = call @my_module_fn(%arg0, %[[MODULECASTED]], %[[MODSTATECASTED]], %[[ARG]], %[[RES]])
@@ -826,7 +834,7 @@
 
     // Create duplicate ref for
     // CHECK-NEXT: %[[REF:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
-    // CHECK-NEXT: %[[REFPTR:.+]] = apply "&"(%[[REF]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[REFPTR:.+]] = address_of %[[REF]] : !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[REFSIZE:.+]] = call_opaque "sizeof"() <{args = [!emitc.opaque<"iree_vm_ref_t">]}> : () -> !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: call_opaque "memset"(%[[REFPTR]], %[[REFSIZE]]) <{args = [0 : index, 0 : ui32, 1 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> ()
     // CHECK-NEXT: call_opaque "iree_vm_ref_move"(%arg4, %[[REFPTR]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> ()
@@ -854,7 +862,7 @@
     // CHECK-NEXT: %[[IMPORTS:.+]] = load %[[IMPORTS_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>
     // CHECK-NEXT: %[[IMPORT_INDEX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: %[[IMPORT_SUBSCRIPT:.+]] = subscript %[[IMPORTS]][%[[IMPORT_INDEX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
-    // CHECK-NEXT: %[[IMPORT:.+]] = apply "&"(%[[IMPORT_SUBSCRIPT]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_function_t">>
+    // CHECK-NEXT: %[[IMPORT:.+]] = address_of %[[IMPORT_SUBSCRIPT]] : !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
     // CHECK-NEXT: %[[IMPORT_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>
     // CHECK-NEXT: assign %[[IMPORT]] : !emitc.ptr<!emitc.opaque<"iree_vm_function_t">> to %[[IMPORT_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>
     // CHECK-NEXT: %[[MODULE_LVAL:.+]] = "emitc.member_of_ptr"(%[[IMPORT_LVAL]]) <{member = "module"}> : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>) -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_module_t">>>
@@ -883,11 +891,11 @@
     // CHECK-NEXT: %[[IMPORTS:.+]] = load %[[IMPORTS_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>
     // CHECK-NEXT: %[[IMPORT_INDEX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: %[[IMPORT_SUBSCRIPT:.+]] = subscript %[[IMPORTS]][%[[IMPORT_INDEX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
-    // CHECK-NEXT: %[[IMPORT:.+]] = apply "&"(%[[IMPORT_SUBSCRIPT]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_function_t">>
+    // CHECK-NEXT: %[[IMPORT:.+]] = address_of %[[IMPORT_SUBSCRIPT]] : !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
 
     // Create result variable.
     // CHECK-NEXT: %[[RESULT:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
-    // CHECK-NEXT: %[[RESPTR:.+]] = apply "&"(%[[RESULT]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+    // CHECK-NEXT: %[[RESPTR:.+]] = address_of %[[RESULT]] : !emitc.lvalue<i32>
 
     // Call the import.
     // CHECK-NEXT: %{{.+}} = call @my_module_call_[[YIELDABLEFN]](%arg0, %[[IMPORT]], %arg3, %[[RESPTR]])
@@ -922,18 +930,18 @@
     // CHECK-NEXT: %[[IMPORTS:.+]] = load %[[IMPORTS_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>>
     // CHECK-NEXT: %[[IMPORT_INDEX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: %[[IMPORT_SUBSCRIPT:.+]] = subscript %[[IMPORTS]][%[[IMPORT_INDEX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_function_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
-    // CHECK-NEXT: %[[IMPORT:.+]] = apply "&"(%[[IMPORT_SUBSCRIPT]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_function_t">>
+    // CHECK-NEXT: %[[IMPORT:.+]] = address_of %[[IMPORT_SUBSCRIPT]] : !emitc.lvalue<!emitc.opaque<"iree_vm_function_t">>
 
     // Allocate ref variable for argument.
     // CHECK-NEXT: %[[ARGREF:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
-    // CHECK-NEXT: %[[ARGREFPTR:.+]] = apply "&"(%[[ARGREF]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[ARGREFPTR:.+]] = address_of %[[ARGREF]] : !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[ARGREFSIZE:.+]] = call_opaque "sizeof"() <{args = [!emitc.opaque<"iree_vm_ref_t">]}> : () -> !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: call_opaque "memset"(%[[ARGREFPTR]], %[[ARGREFSIZE]]) <{args = [0 : index, 0 : ui32, 1 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> ()
     // CHECK-NEXT: call_opaque "iree_vm_ref_assign"(%arg3, %[[ARGREFPTR]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> ()
 
     // Allocate ref variable for result.
     // CHECK-NEXT: %[[RESREF:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
-    // CHECK-NEXT: %[[RESREFPTR:.+]] = apply "&"(%[[RESREF]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[RESREFPTR:.+]] = address_of %[[RESREF]] : !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[RESREFSIZE:.+]] = call_opaque "sizeof"() <{args = [!emitc.opaque<"iree_vm_ref_t">]}> : () -> !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: call_opaque "memset"(%[[RESREFPTR]], %[[RESREFSIZE]]) <{args = [0 : index, 0 : ui32, 1 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> ()
 
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/global_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/global_ops.mlir
index 750ca73..9b643ff 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/global_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/global_ops.mlir
@@ -45,7 +45,7 @@
     // CHECK-NEXT: %[[REFS:.+]] = load %[[REFS_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>>
     // CHECK: %[[REF_INDEX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: %[[REF:.+]] = subscript %[[REFS]][%[[REF_INDEX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
-    // CHECK-NEXT: %[[REF_0:.+]] = apply "&"(%[[REF]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[REF_0:.+]] = address_of %[[REF]] : !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
     // CHECK: %[[C:.+]] = call_opaque "iree_vm_type_def_as_ref"(%{{.+}}) : (!emitc.opaque<"iree_vm_type_def_t">) -> !emitc.opaque<"iree_vm_ref_type_t">
     // CHECK: %{{.+}} = call_opaque "iree_vm_ref_retain_or_move_checked"(%[[REF_0]], %[[C]], %arg3) <{args = [false, 0 : index, 1 : index, 2 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_vm_ref_type_t">, !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_status_t">
     %0 = vm.global.load.ref @g0 : !vm.buffer
@@ -66,7 +66,7 @@
     // CHECK-NEXT: %[[REFS:.+]] = load %[[REFS_LVAL]] : <!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>>
     // CHECK: %[[REF_INDEX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
     // CHECK-NEXT: %[[REF:.+]] = subscript %[[REFS]][%[[REF_INDEX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
-    // CHECK-NEXT: %[[REF_0:.+]] = apply "&"(%[[REF]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[REF_0:.+]] = address_of %[[REF]] : !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
     // CHECK: %[[C:.+]] = call_opaque "iree_vm_type_def_as_ref"(%{{.+}}) : (!emitc.opaque<"iree_vm_type_def_t">) -> !emitc.opaque<"iree_vm_ref_type_t">
     // CHECK: %{{.+}} = call_opaque "iree_vm_ref_retain_or_move_checked"(%arg3, %[[C]], %[[REF_0]]) <{args = [false, 0 : index, 1 : index, 2 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_vm_ref_type_t">, !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_status_t">
     vm.global.store.ref %arg0, @g0_mut : !vm.buffer
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/list_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/list_ops.mlir
index 0c19a95..711d4e0 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/list_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/list_ops.mlir
@@ -4,7 +4,7 @@
   // CHECK-LABEL: emitc.func private @my_module_list_alloc
   vm.func @list_alloc(%arg0: i32) -> !vm.list<i32> {
     // CHECK: %[[LIST_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"NULL">}> : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>>
-    // CHECK: %[[LIST_PTR:.+]] = apply "&"(%3) : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>>) -> !emitc.ptr<!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>>
+    // CHECK: %[[LIST_PTR:.+]] = address_of %3 : !emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>>
     // CHECK-DAG: %[[STATE_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"struct my_module_state_t">>>
     // CHECK-DAG: assign %arg2 : !emitc.ptr<!emitc.opaque<"struct my_module_state_t">> to %[[STATE_LVAL]] : <!emitc.ptr<!emitc.opaque<"struct my_module_state_t">>>
     // CHECK-DAG: %[[ALLOCATOR_LVAL:.+]] = "emitc.member_of_ptr"(%[[STATE_LVAL]]) <{member = "allocator"}> : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"struct my_module_state_t">>>) -> !emitc.lvalue<!emitc.opaque<"iree_allocator_t">>
@@ -27,7 +27,9 @@
 vm.module @my_module {
   // CHECK-LABEL: emitc.func private @my_module_list_reserve
   vm.func @list_reserve(%arg0: !vm.list<i32>, %arg1: i32) {
-    // CHECK: %[[LIST_DEREF:.*]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[LIST_DEREF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[LIST_DEREF_LVAL:.*]] = subscript %arg3[%[[LIST_DEREF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[LIST_DEREF:.*]] = load %[[LIST_DEREF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[LIST:.*]] = call_opaque "iree_vm_list_deref"(%[[LIST_DEREF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
     // CHECK: %{{.+}} = call_opaque "iree_vm_list_reserve"(%[[LIST]], %arg4) : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32) -> !emitc.opaque<"iree_status_t">
     vm.list.reserve %arg0, %arg1 : (!vm.list<i32>, i32)
@@ -40,7 +42,9 @@
 vm.module @my_module {
   // CHECK-LABEL: emitc.func private @my_module_list_resize
   vm.func @list_resize(%arg0: !vm.list<i32>, %arg1: i32) {
-    // CHECK: %[[LIST_DEREF:.*]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[LIST_DEREF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[LIST_DEREF_LVAL:.*]] = subscript %arg3[%[[LIST_DEREF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[LIST_DEREF:.*]] = load %[[LIST_DEREF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[LIST:.*]] = call_opaque "iree_vm_list_deref"(%[[LIST_DEREF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
     // CHECK: %{{.+}} = call_opaque "iree_vm_list_resize"(%[[LIST]], %arg4) : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32) -> !emitc.opaque<"iree_status_t">
     vm.list.resize %arg0, %arg1 : (!vm.list<i32>, i32)
@@ -53,7 +57,9 @@
 vm.module @my_module {
   // CHECK-LABEL: emitc.func private @my_module_list_size
   vm.func @list_size(%arg0: !vm.list<i32>) -> i32 {
-    // CHECK: %[[LIST_DEREF:.*]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[LIST_DEREF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[LIST_DEREF_LVAL:.*]] = subscript %arg3[%[[LIST_DEREF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[LIST_DEREF:.*]] = load %[[LIST_DEREF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[LIST:.*]] = call_opaque "iree_vm_list_deref"(%[[LIST_DEREF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
     // CHECK: %{{.+}} = call_opaque "iree_vm_list_size"(%[[LIST]]) : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>) -> i32
     %0 = vm.list.size %arg0 : (!vm.list<i32>) -> i32
@@ -67,10 +73,12 @@
   // CHECK-LABEL: emitc.func private @my_module_list_get_i32
   vm.func @list_get_i32(%arg0: !vm.list<i32>, %arg1: i32) -> i32 {
     // CHECK-NEXT: %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>
-    // CHECK-NEXT: %1 = apply "&"(%0) : (!emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>
-    // CHECK-NEXT: %2 = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
-    // CHECK-NEXT: %3 = call_opaque "iree_vm_list_deref"(%2) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
-    // CHECK: %{{.+}} = call_opaque "iree_vm_list_get_value_as"(%3, %arg4, %1) <{args = [0 : index, 1 : index, #emitc.opaque<"IREE_VM_VALUE_TYPE_I32">, 2 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.opaque<"iree_status_t">
+    // CHECK-NEXT: %1 = address_of %0 : !emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>
+    // CHECK-NEXT: %2 = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK-NEXT: %3 = subscript %arg3[%2] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %4 = load %3 : <!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %5 = call_opaque "iree_vm_list_deref"(%4) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
+    // CHECK: %{{.+}} = call_opaque "iree_vm_list_get_value_as"(%5, %arg4, %1) <{args = [0 : index, 1 : index, #emitc.opaque<"IREE_VM_VALUE_TYPE_I32">, 2 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.opaque<"iree_status_t">
     %0 = vm.list.get.i32 %arg0, %arg1 : (!vm.list<i32>, i32) -> i32
     vm.return %0 : i32
   }
@@ -81,7 +89,9 @@
 vm.module @my_module {
   // CHECK-LABEL: emitc.func private @my_module_list_get_ref
   vm.func @list_get_ref(%arg0: !vm.list<!vm.ref<?>>, %arg1: i32) -> !vm.buffer {
-    // CHECK: %[[LIST_DEREF:.*]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[LIST_DEREF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[LIST_DEREF_LVAL:.*]] = subscript %arg3[%[[LIST_DEREF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[LIST_DEREF:.*]] = load %[[LIST_DEREF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[LIST:.*]] = call_opaque "iree_vm_list_deref"(%[[LIST_DEREF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
     // CHECK: %{{.+}} = call_opaque "iree_vm_list_get_ref_retain"(%[[LIST]], %arg4, %arg5) : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_status_t">
     // CHECK: %[[REF_LVAL:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>>
@@ -112,10 +122,12 @@
     // CHECK-NEXT: %0 = call_opaque "iree_vm_value_make_i32"(%arg5) : (i32) -> !emitc.opaque<"iree_vm_value_t">
     // CHECK-NEXT: %1 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>
     // CHECK-NEXT: assign %0 : !emitc.opaque<"iree_vm_value_t"> to %1 : <!emitc.opaque<"iree_vm_value_t">>
-    // CHECK-NEXT: %2 = apply "&"(%1) : (!emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>
-    // CHECK-NEXT: %3 = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
-    // CHECK-NEXT: %4 = call_opaque "iree_vm_list_deref"(%3) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
-    // CHECK: %{{.+}} = call_opaque "iree_vm_list_set_value"(%4, %arg4, %2) : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.opaque<"iree_status_t">
+    // CHECK-NEXT: %2 = address_of %1 : !emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>
+    // CHECK-NEXT: %3 = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK-NEXT: %4 = subscript %arg3[%3] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %5 = load %4 : <!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %6 = call_opaque "iree_vm_list_deref"(%5) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
+    // CHECK: %{{.+}} = call_opaque "iree_vm_list_set_value"(%6, %arg4, %2) : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.opaque<"iree_status_t">
     vm.list.set.i32 %arg0, %arg1, %arg2 : (!vm.list<i32>, i32, i32)
     vm.return
   }
@@ -126,7 +138,9 @@
 vm.module @my_module {
   // CHECK-LABEL: emitc.func private @my_module_list_set_ref
   vm.func @list_set_ref(%arg0: !vm.list<!vm.ref<?>>, %arg1: i32, %arg2: !vm.buffer) {
-    // CHECK: %[[LIST_DEREF:.*]] = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
+    // CHECK: %[[LIST_DEREF_IDX:.+]] = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK: %[[LIST_DEREF_LVAL:.*]] = subscript %arg3[%[[LIST_DEREF_IDX]]] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %[[LIST_DEREF:.*]] = load %[[LIST_DEREF_LVAL]] : <!emitc.opaque<"iree_vm_ref_t">>
     // CHECK-NEXT: %[[LIST:.*]] = call_opaque "iree_vm_list_deref"(%[[LIST_DEREF]]) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
     // CHECK: %{{.+}} = call_opaque "iree_vm_list_set_ref_retain"(%[[LIST]], %arg4, %arg5) : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_status_t">
     vm.list.set.ref %arg0, %arg1, %arg2 : (!vm.list<!vm.ref<?>>, i32, !vm.buffer)
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/list_ops_i64.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/list_ops_i64.mlir
index fb0d6ac..3728e8e 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/list_ops_i64.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/list_ops_i64.mlir
@@ -4,10 +4,12 @@
   // CHECK-LABEL: emitc.func private @my_module_list_get_i64
   vm.func @list_get_i64(%arg0: !vm.list<i64>, %arg1: i32) -> i64 {
     // CHECK-NEXT: %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>
-    // CHECK-NEXT: %1 = apply "&"(%0) : (!emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>
-    // CHECK-NEXT: %2 = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
-    // CHECK-NEXT: %3 = call_opaque "iree_vm_list_deref"(%2) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
-    // CHECK: %{{.+}} = call_opaque "iree_vm_list_get_value_as"(%3, %arg4, %1) <{args = [0 : index, 1 : index, #emitc.opaque<"IREE_VM_VALUE_TYPE_I64">, 2 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.opaque<"iree_status_t">
+    // CHECK-NEXT: %1 = address_of %0 : !emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>
+    // CHECK-NEXT: %2 = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK-NEXT: %3 = subscript %arg3[%2] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %4 = load %3 : <!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %5 = call_opaque "iree_vm_list_deref"(%4) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
+    // CHECK: %{{.+}} = call_opaque "iree_vm_list_get_value_as"(%5, %arg4, %1) <{args = [0 : index, 1 : index, #emitc.opaque<"IREE_VM_VALUE_TYPE_I64">, 2 : index]}> : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.opaque<"iree_status_t">
     %0 = vm.list.get.i64 %arg0, %arg1 : (!vm.list<i64>, i32) -> i64
     vm.return %0 : i64
   }
@@ -21,10 +23,12 @@
     // CHECK-NEXT: %0 = call_opaque "iree_vm_value_make_i64"(%arg5) : (i64) -> !emitc.opaque<"iree_vm_value_t">
     // CHECK-NEXT: %1 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>
     // CHECK-NEXT: assign %0 : !emitc.opaque<"iree_vm_value_t"> to %1 : <!emitc.opaque<"iree_vm_value_t">>
-    // CHECK-NEXT: %2 = apply "&"(%1) : (!emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>
-    // CHECK-NEXT: %3 = apply "*"(%arg3) : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.opaque<"iree_vm_ref_t">
-    // CHECK-NEXT: %4 = call_opaque "iree_vm_list_deref"(%3) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
-    // CHECK: %{{.+}} = call_opaque "iree_vm_list_set_value"(%4, %arg4, %2) : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.opaque<"iree_status_t">
+    // CHECK-NEXT: %2 = address_of %1 : !emitc.lvalue<!emitc.opaque<"iree_vm_value_t">>
+    // CHECK-NEXT: %3 = literal "0" : !emitc.opaque<"iree_host_size_t">
+    // CHECK-NEXT: %4 = subscript %arg3[%3] : (!emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>, !emitc.opaque<"iree_host_size_t">) -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %5 = load %4 : <!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK-NEXT: %6 = call_opaque "iree_vm_list_deref"(%5) : (!emitc.opaque<"iree_vm_ref_t">) -> !emitc.ptr<!emitc.opaque<"iree_vm_list_t">>
+    // CHECK: %{{.+}} = call_opaque "iree_vm_list_set_value"(%6, %arg4, %2) : (!emitc.ptr<!emitc.opaque<"iree_vm_list_t">>, i32, !emitc.ptr<!emitc.opaque<"iree_vm_value_t">>) -> !emitc.opaque<"iree_status_t">
     vm.list.set.i64 %arg0, %arg1, %arg2 : (!vm.list<i64>, i32, i64)
     vm.return
   }
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/type_conversion.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/type_conversion.mlir
index dfbf6b6..c6842fe 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/type_conversion.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/type_conversion.mlir
@@ -4,7 +4,7 @@
   // CHECK-LABEL: emitc.func private @my_module_list_alloc
   vm.func @list_alloc(%arg0: i32) {
     // CHECK: %[[REF:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
-    // CHECK: %[[REFPTR:.+]] = apply "&"(%[[REF]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK: %[[REFPTR:.+]] = address_of %[[REF]] : !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
     %list = vm.list.alloc %arg0 : (i32) -> !vm.list<i32>
     %list_dno = util.optimization_barrier %list : !vm.list<i32>
     // CHECK: util.optimization_barrier %[[REFPTR]] : !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
@@ -15,7 +15,7 @@
   vm.func @list_size(%arg0: i32) {
     %list = vm.list.alloc %arg0 : (i32) -> !vm.list<i32>
     // CHECK: %[[REF:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
-    // CHECK: %[[REFPTR:.+]] = apply "&"(%[[REF]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK: %[[REFPTR:.+]] = address_of %[[REF]] : !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
     %size = vm.list.size %list : (!vm.list<i32>) -> i32
     // CHECK: %[[SIZE:.+]] = call_opaque "iree_vm_list_size"(%{{.+}})
     %size_dno = util.optimization_barrier %size : i32
@@ -32,7 +32,7 @@
   vm.export @ref
   vm.func @ref(%arg0: i32) {
     // CHECK: %[[REF:.+]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
-    // CHECK: %[[REFPTR:.+]] = apply "&"(%[[REF]]) : (!emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>) -> !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
+    // CHECK: %[[REFPTR:.+]] = address_of %[[REF]] : !emitc.lvalue<!emitc.opaque<"iree_vm_ref_t">>
     %buffer = vm.const.ref.rodata @byte_buffer : !vm.buffer
     %buffer_dno = util.optimization_barrier %buffer : !vm.buffer
     // CHECK: util.optimization_barrier %[[REFPTR]] : !emitc.ptr<!emitc.opaque<"iree_vm_ref_t">>
diff --git a/third_party/llvm-project b/third_party/llvm-project
index 8292a05..75b7809 160000
--- a/third_party/llvm-project
+++ b/third_party/llvm-project
@@ -1 +1 @@
-Subproject commit 8292a057931882ed2b1e9abdcb5c1512a7e7babf
+Subproject commit 75b7809248cca443085c1c3fb572ae38add4c500
diff --git a/third_party/torch-mlir b/third_party/torch-mlir
index 44b938e..091bb8d 160000
--- a/third_party/torch-mlir
+++ b/third_party/torch-mlir
@@ -1 +1 @@
-Subproject commit 44b938e7baaed081e17383fbbb9a34ec702f4270
+Subproject commit 091bb8d3221457d25c079bed9750c5b6927f39bc