bufferization.to_tensor that was explicitly marked illegal
- Dominant language
- C++
- Stars
- 3.9k
- Forks
- 1k
- Avg merge
- 4d 16h
- Merged PRs (30d)
- 47
Description
### What happened?
```
pre_hal_conversion.mlir:80:10: error: failed to legalize operation 'bufferization.to_tensor' that was explicitly marked illegal
%6 = bufferization.to_tensor %alloc restrict writable : memref<1024xf32>
^
pre_hal_conversion.mlir:80:10: note: see current operation: %15 = "bufferization.to_tensor"(%8) <{restrict, writable}> : (memref<1024xf32>) -> tensor<1024xf32>
```
I'm getting the above error message and don't know how to resolve it. I found exactly which compiler pass that causes the error (ConvertToHalPass or --iree-hal-conversion command). I'm running on llvm-cpu backend (x86_64).
### Steps to reproduce your issue
1. Run "../iree-build/tools/iree-opt --iree-hal-conversion pre_hal_conversion.mlir"
2. pre_hal_conversion.mlir is included below.
pre_hal_conversion.mlir
```
#executable_target_embedded_elf_x86_64_ = #hal.executable.target<"llvm-cpu", "embedded-elf-x86_64", {cpu = "generic", cpu_features = "", data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", native_vector_size = 16 : i64, target_triple = "x86_64-unknown-unknown-eabi-elf"}>
#pipeline_layout = #hal.pipeline.layout, <1, storage_buffer, ReadOnly>, <2, storage_buffer>]>]>
#translation = #iree_codegen.translation_info
#device_target_local = #hal.device.target<"local", [#executable_target_embedded_elf_x86_64_]>
module attributes {hal.device.targets = [#device_target_local]} {
hal.executable private @add_kernel_dispatch_0 {
hal.executable.variant public @embedded_elf_x86_64 target(#executable_target_embedded_elf_x86_64_) {
hal.executable.export public @add_kernel_dispatch_0_elementwise_1024_f32 ordinal(0) layout(#pipeline_layout) attributes {hal.interface.bindings = [#hal.interface.binding<0, 0>, #hal.interface.binding<0, 1>, #hal.interface.binding<0, 2>]} {
^bb0(%arg0: !hal.device):
%c1 = arith.constant 1 : index
hal.return %c1, %c1, %c1 : index, index, index
}
builtin.module attributes {llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-unknown-eabi-elf"} {
llvm.func @add_kernel_dispatch_0_elementwise_1024_f32(%arg0: !llvm.ptr {llvm.align = 16 : i64, llvm.noalias}, %arg1: !llvm.ptr {llvm.align = 16 : i64, llvm.noalias}, %arg2: !llvm.ptr {llvm.align = 16 : i64, llvm.noalias}) -> i32 attributes {translation_info = #translation} {
%0 = llvm.mlir.constant(0 : i32) : i32
%1 = llvm.mlir.constant(63 : index) : i64
%2 = llvm.mlir.constant(4 : index) : i64
%3 = llvm.mlir.constant(1024 : index) : i64
%4 = llvm.mlir.constant(0 : index) : i64
%5 = llvm.load %arg1 : !llvm.ptr -> !llvm.struct<"iree_hal_executable_dispatch_state_v0_t", (i32, i32, i16, i16, i32, i32, i16, i8, i8, ptr, ptr, ptr)>
%6 = llvm.extractvalue %5[10] : !llvm.struct<"iree_hal_executable_dispatch_state_v0_t", (i32, i32, i16, i16, i32, i32, i16, i8, i8, ptr, ptr, ptr)>
%7 = llvm.load %6 : !llvm.ptr -> !llvm.ptr
%8 = llvm.ptrtoint %7 : !llvm.ptr to i64
%9 = llvm.and %8, %1 : i64
%10 = llvm.icmp "eq" %9, %4 : i64
"llvm.intr.assume"(%10) : (i1) -> ()
%11 = llvm.load %arg1 : !llvm.ptr -> !llvm.struct<"iree_hal_executable_dispatch_state_v0_t", (i32, i32, i16, i16, i32, i32, i16, i8, i8, ptr, ptr, ptr)>
%12 = llvm.extractvalue %11[10] : !llvm.struct<"iree_hal_executable_dispatch_state_v0_t", (i32, i32, i16, i16, i32, i32, i16, i8, i8, ptr, ptr, ptr)>
%13 = llvm.getelementptr %12[1] : (!llvm.ptr) -> !llvm.ptr, !llvm.ptr
%14 = llvm.load %13 : !llvm.ptr -> !llvm.ptr
%15 = llvm.ptrtoint %14 : !llvm.ptr to i64
%16 = llvm.and %15, %1 : i64
%17 = llvm.icmp "eq" %16, %4 : i64
"llvm.intr.assume"(%17) : (i1) -> ()
%18 = llvm.load %arg1 : !llvm.ptr -> !llvm.struct<"iree_hal_executable_dispatch_state_v0_t", (i32, i32, i16, i16, i32, i32, i16, i8, i8, ptr, ptr, ptr)>
%19 = llvm.extractvalue %18[10] : !llvm.struct<"iree_hal_executable_dispatch_state_v0_t", (i32, i32, i16, i16, i32, i32, i16, i8, i8, ptr, ptr, ptr)>
%20 = llvm.getelementptr %19[2] : (!llvm.ptr) -> !llvm.ptr, !llvm.ptr
%21 = llvm.load %20 : !llvm.ptr -> !llvm.ptr
%22 = llvm.ptrtoint %21 : !llvm.ptr to i64
%23 = llvm.and %22, %1 : i64
%24 = llvm.icmp "eq" %23, %4 : i64
"llvm.intr.assume"(%24) : (i1) -> ()
llvm.br ^bb1(%4 : i64)
^bb1(%25: i64): // 2 preds: ^bb0, ^bb2
%26 = llvm.icmp "slt" %25, %3 : i64
llvm.cond_br %26, ^bb2, ^bb3
^bb2: // pred: ^bb1
%27 = llvm.getelementptr %7[%25] : (!llvm.ptr, i64) -> !llvm.ptr, f32
%28 = llvm.load %27 {alignment = 4 : i64} : !llvm.ptr -> vector<4xf32>
%29 = llvm.getelementptr %14[%25] : (!llvm.ptr, i64) -> !llvm.ptr, f32
%30 = llvm.load %29 {alignment = 4 : i64} : !llvm.ptr -> vector<4xf32>
%31 = llvm.fadd %28, %30 {fastmathFlags = #llvm.fastmath} : vector<4xf32>
%32 = llvm.getelementptr %21[%25] : (!llvm.ptr, i64) -> !llvm.ptr, f32
llvm.store %31, %32 {alignment = 4 : i64} : vector<4xf32>, !llvm.ptr
%33 = llvm.add %25, %2 : i64
llvm.br ^bb1(%33 : i64)
^bb3: // pred: ^bb1
llvm.return %0 : i32
}
}
}
}
util.func public @add_kernel(%arg0: memref<*xf32> {tt.divisibility = 16 : i32}, %arg1: memref<*xf32> {tt.divisibility = 16 : i32}, %arg2: memref<*xf32> {tt.divisibility = 16 : i32}, %arg3: i32 {tt.divisibility = 16 : i32}, %arg4: i32, %arg5: i32, %arg6: i32, %arg7: i32, %arg8: i32, %arg9: i32) attributes {iree.abi.stub, iree.reflection = {iree.abi.declaration = "sync func @add_kernel(%input0: memref<*xf32> {tt.divisibility = 16 : i32}, %input1: memref<*xf32> {tt.divisibility = 16 : i32}, %input2: memref<*xf32> {tt.divisibility = 16 : i32}, %input3: i32 {tt.divisibility = 16 : i32}, %input4: i32, %input5: i32, %input6: i32, %input7: i32, %input8: i32, %input9: i32) -> ()"}} {
%c4 = arith.constant 4 : index
%c4096 = arith.constant 4096 : index
%c0 = arith.constant 0 : index
%c1024 = arith.constant 1024 : index
%c1024_i32 = arith.constant 1024 : i32
%0 = arith.muli %arg7, %c1024_i32 : i32
%1 = arith.index_cast %0 : i32 to index
%reinterpret_cast = memref.reinterpret_cast %arg0 to offset: [%1], sizes: [1024], strides: [1] : memref<*xf32> to memref<1024xf32, strided<[1], offset: ?>>
%alloc = memref.alloc() : memref<1024xf32>
%2 = arith.addi %1, %c1024 : index
%3 = arith.index_cast %arg3 : i32 to index
%4 = arith.minsi %2, %3 : index
%5 = arith.subi %4, %1 : index
%subview = memref.subview %reinterpret_cast[0] [%5] [1] : memref<1024xf32, strided<[1], offset: ?>> to memref>
%subview_0 = memref.subview %alloc[0] [%5] [1] : memref<1024xf32> to memref>
memref.copy %subview, %subview_0 : memref> to memref>
%6 = bufferization.to_tensor %alloc restrict writable : memref<1024xf32>
%7 = stream.tensor.import %6 : tensor<1024xf32> -> tensor<1024xf32> in !stream.resource{%c4096}
%reinterpret_cast_1 = memref.reinterpret_cast %arg1 to offset: [%1], sizes: [1024], strides: [1] : memref<*xf32> to memref<1024xf32, strided<[1], offset: ?>>
%alloc_2 = memref.alloc() : memref<1024xf32>
%subview_3 = memref.subview %reinterpret_cast_1[0] [%5] [1] : memref<1024xf32, strided<[1], offset: ?>> to memref>
%subview_4 = memref.subview %alloc_2[0] [%5] [1] : memref<1024xf32> to memref>
memref.copy %subview_3, %subview_4 : memref> to memref>
%8 = bufferization.to_tensor %alloc_2 restrict writable : memref<1024xf32>
%9 = stream.tensor.import %8 : tensor<1024xf32> -> tensor<1024xf32> in !stream.resource{%c4096}
%reinterpret_cast_5 = memref.reinterpret_cast %arg2 to offset: [%1], sizes: [1024], strides: [1] : memref<*xf32> to memref<1024xf32, strided<[1], offset: ?>>
%10 = arith.muli %5, %c4 : index
%result, %result_timepoint = stream.resource.alloca uninitialized : !stream.resource{%10} => !stream.timepoint
%result_6, %result_timepoint_7 = stream.resource.alloca uninitialized : !stream.resource{%c4096} => !stream.timepoint
%11 = stream.timepoint.join max(%result_timepoint, %result_timepoint_7) => !stream.timepoint
%12 = stream.cmd.execute await(%11) => with(%7 as %arg10: !stream.resource{%c4096}, %9 as %arg11: !stream.resource{%c4096}, %result as %arg12: !stream.resource{%10}, %result_6 as %arg13: !stream.resource{%c4096}) {
stream.cmd.dispatch @add_kernel_dispatch_0::@embedded_elf_x86_64::@add_kernel_dispatch_0_elementwise_1024_f32 {
ro %arg10[%c0 for %c4096] : !stream.resource{%c4096},
ro %arg11[%c0 for %c4096] : !stream.resource{%c4096},
wo %arg13[%c0 for %c4096] : !stream.resource{%c4096}
}
stream.cmd.copy %arg13[%c0], %arg12[%c0], %10 : !stream.resource{%c4096} -> !stream.resource{%10}
} => !stream.timepoint
%13 = stream.resource.dealloca await(%12) => %result_6 : !stream.resource{%c4096} => !stream.timepoint
%subview_8 = memref.subview %reinterpret_cast_5[0] [%5] [1] : memref<1024xf32, strided<[1], offset: ?>> to memref>
%14 = stream.timepoint.await %13 => %result : !stream.resource{%10}
%15 = stream.tensor.export %14 : tensor{%5} in !stream.resource{%10} -> tensor
bufferization.materialize_in_destination %15 in writable %subview_8 : (tensor, memref>) -> ()
util.return
}
}
```
Additionally, running:
1. "iree-compile --iree-hal-target-backends=llvm-cpu file.mlir" produces the same issue.
2. file.mlir is included below.
file.mlir
```
#map = affine_map<(d0) -> (d0)>
module {
func.func @add_kernel(%arg0: memref<*xf32> {tt.divisibility = 16 : i32}, %arg1: memref<*xf32> {tt.divisibility = 16 : i32}, %arg2: memref<*xf32> {tt.divisibility = 16 : i32}, %arg3: i32 {tt.divisibility = 16 : i32}, %arg4: i32, %arg5: i32, %arg6: i32, %arg7: i32, %arg8: i32, %arg9: i32) {
%c1024 = arith.constant 1024 : index
%c1024_i32 = arith.constant 1024 : i32
%0 = arith.muli %arg7, %c1024_i32 : i32
%1 = arith.index_cast %0 : i32 to index
%reinterpret_cast = memref.reinterpret_cast %arg0 to offset: [%1], sizes: [1024], strides: [1] : memref<*xf32> to memref<1024xf32, strided<[1], offset: ?>>
%alloc = memref.alloc() : memref<1024xf32>
%2 = arith.index_cast %0 : i32 to index
%3 = arith.addi %2, %c1024 : index
%4 = arith.index_cast %arg3 : i32 to index
%5 = arith.minsi %3, %4 : index
%6 = arith.subi %5, %2 : index
%subview = memref.subview %reinterpret_cast[0] [%6] [1] : memref<1024xf32, strided<[1], offset: ?>> to memref>
%subview_0 = memref.subview %alloc[0] [%6] [1] : memref<1024xf32> to memref>
memref.copy %subview, %subview_0 : memref> to memref>
%7 = bufferization.to_tensor %alloc restrict writable : memref<1024xf32>
%8 = arith.index_cast %0 : i32 to index
%reinterpret_cast_1 = memref.reinterpret_cast %arg1 to offset: [%8], sizes: [1024], strides: [1] : memref<*xf32> to memref<1024xf32, strided<[1], offset: ?>>
%alloc_2 = memref.alloc() : memref<1024xf32>
%9 = arith.index_cast %0 : i32 to index
%10 = arith.addi %9, %c1024 : index
%11 = arith.index_cast %arg3 : i32 to index
%12 = arith.minsi %10, %11 : index
%13 = arith.subi %12, %9 : index
%subview_3 = memref.subview %reinterpret_cast_1[0] [%13] [1] : memref<1024xf32, strided<[1], offset: ?>> to memref>
%subview_4 = memref.subview %alloc_2[0] [%13] [1] : memref<1024xf32> to memref>
memref.copy %subview_3, %subview_4 : memref> to memref>
%14 = bufferization.to_tensor %alloc_2 restrict writable : memref<1024xf32>
%15 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel"]} ins(%7, %14 : tensor<1024xf32>, tensor<1024xf32>) outs(%7 : tensor<1024xf32>) {
^bb0(%in: f32, %in_7: f32, %out: f32):
%22 = arith.addf %in, %in_7 : f32
linalg.yield %22 : f32
} -> tensor<1024xf32>
%16 = arith.index_cast %0 : i32 to index
%reinterpret_cast_5 = memref.reinterpret_cast %arg2 to offset: [%16], sizes: [1024], strides: [1] : memref<*xf32> to memref<1024xf32, strided<[1], offset: ?>>
%17 = arith.index_cast %0 : i32 to index
%18 = arith.addi %17, %c1024 : index
%19 = arith.index_cast %arg3 : i32 to index
%20 = arith.minsi %18, %19 : index
%21 = arith.subi %20, %17 : index
%extracted_slice = tensor.extract_slice %15[0] [%21] [1] : tensor<1024xf32> to tensor
%subview_6 = memref.subview %reinterpret_cast_5[0] [%21] [1] : memref<1024xf32, strided<[1], offset: ?>> to memref>
bufferization.materialize_in_destination %extracted_slice in writable %subview_6 : (tensor, memref>) -> ()
return
}
}
```
### What component(s) does this issue relate to?
MLIR, Compiler
### Version information
_No response_
### Additional context
_No response_
Contributor guide
Research direction
Reproduce with pre_hal_conversion.mlir using iree-opt --iree-hal-conversion and with file.mlir using iree-compile --iree-hal-target-backends=llvm-cpu. Start at ConvertToHalPass and the reported bufferization.to_tensor operations; done means the reproducer no longer fails legalization on the llvm-cpu backend.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100