Some questions about memref.subview

Now I’m using memref.subview, but I have a problem . I have spent a lot of time on it, but so the problem is still not solved.I hope someone can help me.Thanks!

  • Why does the MemRefType of memref.subview created by c++ have strided?
    you can see following code.The following code works fine.
%input0 = memref.get_global @input2 : memref<3x3x3xi8> 
%subInput0 = memref.subview %input0[0, 0, 0][1, 3, 3][1, 1, 1] : memref<3x3x3xi8> to memref<3x3xi8>

But the subview I created using c++ would look like this.The type of the result is memref<3x3xi8, strided<[3, 1]>>.At first I set the type of the result to memref<3x3xi8>,but it will report an error. Then I set the type of the result to memref<3x3xi8, strided<[3, 1]>>,It will still report an error.

error: expected result type to be 'memref<1x3x3xi8, strided<[9, 3, 1], offset: 9>>' or a rank-reduced version. (mismatch of result layout)
  %0 = "memref.get_global"() {name = @input2} : () -> memref<3x3x3xi8>
  %1 = "memref.get_global"() {name = @input2} : () -> memref<3x3x3xi8>
  %2 = "memref.alloc"() {operand_segment_sizes = array<i32: 0, 0>} : () -> memref<3x3x3xi8>
  %3 = "memref.subview"(%0) {operand_segment_sizes = array<i32: 1, 0, 0, 0>, static_offsets = array<i64: 0, 0, 0>, static_sizes = array<i64: 1, 3, 3>, static_strides = array<i64: 1, 1, 1>} : (memref<3x3x3xi8>) -> memref<3x3xi8, strided<[3, 1]>>
  %4 = "memref.subview"(%0) {operand_segment_sizes = array<i32: 1, 0, 0, 0>, static_offsets = array<i64: 1, 0, 0>, static_sizes = array<i64: 1, 3, 3>, static_strides = array<i64: 1, 1, 1>} : (memref<3x3x3xi8>) -> memref<3x3xi8, strided<[3, 1]>>
  %5 = "memref.subview"(%0) {operand_segment_sizes = array<i32: 1, 0, 0, 0>, static_offsets = array<i64: 2, 0, 0>, static_sizes = array<i64: 1, 3, 3>, static_strides = array<i64: 1, 1, 1>} : (memref<3x3x3xi8>) -> memref<3x3xi8, strided<[3, 1]>>

You can see that directly making the result of type memref<3x3xi8> does not work in c++.

  • How to solve this problem?
    I’ve spent a lot of time working on this problem, but still can’t fix it.I don’t know where I should start to solve the problem now.I hope someone can point out where I’m wrong.I really need your help.Thanks!

This is a rank-reduced subview. There is an implicit assumption that not specifying any strides/offsets implies row-major strides and offset. So memref<3x3xi8> is same as memref<3x3xi8, strided<[3, 1], offset = 0>. Since the offsets are all zero in the base of %input0 and %subInput0 are the same, so offsets

It’d be easier if you also post the c++ snippet you are using (I also find the memref API a bit confusing, and I am supposed to actually know this stuff, so I empathize with your plight here)

%3 = "memref.subview"(%0) {operand_segment_sizes = array<i32: 1, 0, 0, 0>, static_offsets = array<i64: 0, 0, 0>, static_sizes = array<i64: 1, 3, 3>, static_strides = array<i64: 1, 1, 1>} : (memref<3x3x3xi8>) -> memref<3x3xi8, strided<[3, 1]>>

IIUC, this is offsets = [0, 0, 0], sizes = [1, 3, 3], strides = [1, 1, 1]. Using memref<3x3xi8, strided<[3, 1], offset = 0>> should be legal (maybe the verifier expects the offset to be explicitly specified as 0 and does not accept implicit 0 semantics. That’d be good to fix probably.

 %4 = "memref.subview"(%0) {operand_segment_sizes = array<i32: 1, 0, 0, 0>, static_offsets = array<i64: 1, 0, 0>, static_sizes = array<i64: 1, 3, 3>, static_strides = array<i64: 1, 1, 1>} : (memref<3x3x3xi8>) -> memref<3x3xi8, strided<[3, 1]>>

This is offsets = [1, 0, 0], sizes = [1, 3, 3], strides = [1, 1, 1]. Here the memref type should be memref<3x3xi8, strided<[3, 1], offset = 9>> . Essentially both %0 and %4 have the same base pointer, but %4 starts at a different offset.

Same logic extends to

%5 = "memref.subview"(%0) {operand_segment_sizes = array<i32: 1, 0, 0, 0>, static_offsets = array<i64: 2, 0, 0>, static_sizes = array<i64: 1, 3, 3>, static_strides = array<i64: 1, 1, 1>} : (memref<3x3x3xi8>) -> memref<3x3xi8, strided<[3, 1]>>

Here the memref type would be memref<3x3xi8, strided<[3, 1], offset = 18>>.

The error you are seeing is on the second memref.subview IIUC. Hope that helps.

1 Like

Thank you very much for your answer.But there is a point I did not understand, why the first MemRefType offset is 0, the second is 9, the third is 18, I can probably guess how to calculate. The offset is relative to the source memrey (in this case 3x3x3xi8), why does the MemReyType after the subview retain this value(0, 9, 18)? I think the offset value should be independent of the source memref.

I am not sure I have the right words to answer this question. The best I can explain it is that memref and memref.subview treat memory in a way that is different from having a raw pointer. So when you take a memref.subview it is NOT meant to be a GEP-like instruction which does pointer arithmetic. Instead it is taking a “subview” into a region of memory, and the type carries the information needed to index into this region of an memory that is viewed as an N-dimensional object.

Thanks!I think I understand what you’re saying.