Remove memory side effect from hal.interface.binding.subspan (#12494)
Enables CSE + DCE on duplicate/unused interface bindings as a followup
to #12471. This removes the test for interface bindings in
RemoveDeadMemAllocs as it is no longer marked as an alloc.
benchmarks: x86_64, cuda
diff --git a/compiler/src/iree/compiler/Codegen/Common/test/remove_dead_allocs.mlir b/compiler/src/iree/compiler/Codegen/Common/test/remove_dead_allocs.mlir
index 50040b1..146d3d0 100644
--- a/compiler/src/iree/compiler/Codegen/Common/test/remove_dead_allocs.mlir
+++ b/compiler/src/iree/compiler/Codegen/Common/test/remove_dead_allocs.mlir
@@ -16,13 +16,3 @@
// CHECK-LABEL: func.func @alloc_keep
// CHECK-NEXT: %[[ALLOC:.+]] = memref.alloc
// CHECK-NEXT: return %[[ALLOC]]
-
-// -----
-
-func.func @cleanup_only_assume_alignment_uses() {
- %0 = hal.interface.binding.subspan set(0) binding(0) type(storage_buffer) : memref<42xf32>
- memref.assume_alignment %0, 64 : memref<42xf32>
- return
-}
-// CHECK-LABEL: func.func @cleanup_only_assume_alignment_uses()
-// CHECK-NEXT: return
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/test/transform_dialect_promote_operands.mlir b/compiler/src/iree/compiler/Codegen/LLVMGPU/test/transform_dialect_promote_operands.mlir
index 2657759..f5372f9 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/test/transform_dialect_promote_operands.mlir
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/test/transform_dialect_promote_operands.mlir
@@ -6,7 +6,6 @@
%c0 = arith.constant 0 : index
%0 = hal.interface.binding.subspan set(0) binding(0) type(storage_buffer) alignment(64) offset(%c0) : !flow.dispatch.tensor<readonly:tensor<250x500xf32>>
%1 = hal.interface.binding.subspan set(0) binding(1) type(storage_buffer) alignment(64) offset(%c0) : !flow.dispatch.tensor<readonly:tensor<500x1020xf32>>
- %2 = hal.interface.binding.subspan set(0) binding(2) type(storage_buffer) alignment(64) offset(%c0) : !flow.dispatch.tensor<readwrite:tensor<250x1020xf32>>
%3 = flow.dispatch.tensor.load %0, offsets = [0, 0], sizes = [250, 500], strides = [1, 1] : !flow.dispatch.tensor<readonly:tensor<250x500xf32>> -> tensor<250x500xf32>
%4 = flow.dispatch.tensor.load %1, offsets = [0, 0], sizes = [500, 1020], strides = [1, 1] : !flow.dispatch.tensor<readonly:tensor<500x1020xf32>> -> tensor<500x1020xf32>
@@ -16,15 +15,14 @@
// CHECK: %[[CST:.+]] = arith.constant 0.000000e+00 : f32
// CHECK: %[[D0:.+]] = hal.interface.binding.subspan set(0) binding(0) type(storage_buffer) alignment(64)
// CHECK: %[[D1:.+]] = hal.interface.binding.subspan set(0) binding(1) type(storage_buffer) alignment(64)
- // CHECK: %[[D2:.+]] = hal.interface.binding.subspan set(0) binding(2) type(storage_buffer) alignment(64)
- // CHECK: %[[D3:.+]] = flow.dispatch.tensor.load %[[D0]], offsets = [0, 0], sizes = [250, 500]
- // CHECK: %[[D4:.+]] = flow.dispatch.tensor.load %[[D1]], offsets = [0, 0], sizes = [500, 1020]
- // CHECK: %[[D5:.+]] = tensor.empty() : tensor<250x1020xf32>
- // CHECK-NEXT: %[[D6:.+]] = linalg.fill ins(%[[CST]] : f32) outs(%[[D5]] : tensor<250x1020xf32>) -> tensor<250x1020xf32>
- // CHECK-NEXT: %[[D7:.+]] = bufferization.alloc_tensor() copy(%[[D3]]) {bufferization.escape = [false]} : tensor<250x500xf32>
- // CHECK-NEXT: %[[D8:.+]] = bufferization.alloc_tensor() copy(%[[D4]]) {bufferization.escape = [false]} : tensor<500x1020xf32>
- // CHECK-NEXT: %[[D9:.+]] = linalg.matmul ins(%[[D7]], %[[D8]] : tensor<250x500xf32>, tensor<500x1020xf32>)
- // CHECK-SAME: outs(%[[D6]] : tensor<250x1020xf32>) -> tensor<250x1020xf32>
+ // CHECK: %[[D2:.+]] = flow.dispatch.tensor.load %[[D0]], offsets = [0, 0], sizes = [250, 500]
+ // CHECK: %[[D3:.+]] = flow.dispatch.tensor.load %[[D1]], offsets = [0, 0], sizes = [500, 1020]
+ // CHECK: %[[D4:.+]] = tensor.empty() : tensor<250x1020xf32>
+ // CHECK-NEXT: %[[D5:.+]] = linalg.fill ins(%[[CST]] : f32) outs(%[[D4]] : tensor<250x1020xf32>) -> tensor<250x1020xf32>
+ // CHECK-NEXT: %[[D6:.+]] = bufferization.alloc_tensor() copy(%[[D2]]) {bufferization.escape = [false]} : tensor<250x500xf32>
+ // CHECK-NEXT: %[[D7:.+]] = bufferization.alloc_tensor() copy(%[[D3]]) {bufferization.escape = [false]} : tensor<500x1020xf32>
+ // CHECK-NEXT: %[[D8:.+]] = linalg.matmul ins(%[[D6]], %[[D7]] : tensor<250x500xf32>, tensor<500x1020xf32>)
+ // CHECK-SAME: outs(%[[D5]] : tensor<250x1020xf32>) -> tensor<250x1020xf32>
%6 = linalg.matmul ins(%3, %4 : tensor<250x500xf32>, tensor<500x1020xf32>) outs(%5 : tensor<250x1020xf32>) -> tensor<250x1020xf32>
return %6: tensor<250x1020xf32>
}
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/test/emulate_i64.mlir b/compiler/src/iree/compiler/Codegen/SPIRV/test/emulate_i64.mlir
index 82253c8..a2b7338 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/test/emulate_i64.mlir
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/test/emulate_i64.mlir
@@ -37,7 +37,6 @@
// Check that without the Int64 capability emulation produces expected i32 ops.
//
// CHECK-LABEL: func.func @buffer_types
-// CHECK: [[REF_I32:%.+]] = hal.interface.binding.subspan set(0) binding(0) type(storage_buffer) : memref<8xi32, #spirv.storage_class<StorageBuffer>>
// CHECK: [[REF_I64_0:%.+]] = hal.interface.binding.subspan set(0) binding(1) type(storage_buffer) : memref<8xvector<2xi32>, #spirv.storage_class<StorageBuffer>>
// CHECK: [[REF_I64_1:%.+]] = hal.interface.binding.subspan set(0) binding(2) type(storage_buffer) : memref<8xvector<2xi32>, #spirv.storage_class<StorageBuffer>>
// CHECK: [[VI64:%.+]] = memref.load [[REF_I64_0]][{{%.+}}] : memref<8xvector<2xi32>, #spirv.storage_class<StorageBuffer>>
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td
index 45247ff..7e2aa7a 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td
@@ -2316,9 +2316,8 @@
}];
}
-def HAL_InterfaceBindingSubspanOp : HAL_Op<"interface.binding.subspan", [
+def HAL_InterfaceBindingSubspanOp : HAL_PureOp<"interface.binding.subspan", [
AttrSizedOperandSegments,
- MemoryEffects<[MemAlloc]>,
Util_ShapeAwareOp,
]> {
let summary = [{returns an alias to a subspan of interface binding data}];
@@ -2342,7 +2341,7 @@
OptionalAttr<HAL_DescriptorFlagsAttr>:$descriptor_flags
);
let results = (outs
- Res<AnyType, "", [MemAlloc]>:$result
+ AnyType:$result
);
let assemblyFormat = [{
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/test/interface_ops.mlir b/compiler/src/iree/compiler/Dialect/HAL/IR/test/interface_ops.mlir
index 99a3e6b..9874be5 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/test/interface_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/test/interface_ops.mlir
@@ -1,4 +1,5 @@
// RUN: iree-opt --split-input-file --verify-diagnostics %s | FileCheck %s
+// RUN: iree-opt --split-input-file -cse --verify-diagnostics %s | FileCheck %s --check-prefix=CSE
// CHECK-LABEL: @interface_workgroup_info
func.func @interface_workgroup_info() {
@@ -29,6 +30,23 @@
// -----
+// CSE-LABEL: @interface_subspan_cse
+func.func @interface_subspan_cse() {
+ %c0 = arith.constant 0 : index
+
+// CSE: %[[BIND:.+]] = hal.interface.binding.subspan set(0) binding(2) type(storage_buffer) alignment(64) offset({{.+}}) : !flow.dispatch.tensor<readwrite:tensor<2x32x16384xf32>
+ %0 = hal.interface.binding.subspan set(0) binding(2) type(storage_buffer) alignment(64) offset(%c0) : !flow.dispatch.tensor<readwrite:tensor<2x32x16384xf32>>
+ %1 = hal.interface.binding.subspan set(0) binding(2) type(storage_buffer) alignment(64) offset(%c0) : !flow.dispatch.tensor<readwrite:tensor<2x32x16384xf32>>
+
+// CSE-NEXT: %[[LOAD:.+]] = flow.dispatch.tensor.load %[[BIND]]
+ %2 = flow.dispatch.tensor.load %1, offsets = [0, 0, 0], sizes = [2, 32, 16384], strides = [1, 1, 1] : !flow.dispatch.tensor<readwrite:tensor<2x32x16384xf32>> -> tensor<2x32x16384xf32>
+// CSE-NEXT: flow.dispatch.tensor.store %[[LOAD]], %[[BIND]]
+ flow.dispatch.tensor.store %2, %0, offsets = [0, 0, 0], sizes = [2, 32, 16384], strides = [1, 1, 1] : tensor<2x32x16384xf32> -> !flow.dispatch.tensor<readwrite:tensor<2x32x16384xf32>>
+ return
+}
+
+// -----
+
func.func @interface_io_subspan_wrong_dynamic_dim(%dim: index) {
%c8 = arith.constant 8 : index