GetElementPointer can return a different type than the type of the base pointer in MLIR, but this is not allowed in LLVM IR

Hello.
I get the following error when I try to translate MLIR code (which seems valid) in the LLVM dialect to LLVM IR:

       <<Function return type does not match operand type of return inst!
           ret { half*, half*, i64, [4 x i64], [4 x i64] } %4, !dbg !35
          { half*, half*, i64, [2 x i64], [2 x i64] }
          Failed to emit LLVM IR>>

It seems the reason is the fact the following GetElementPointer returns a different type (!llvm.ptr<struct<(ptr<f16>, ptr<f16>, i64, array<2 x i64>, array<2 x i64>)>>) than the type of the base pointer (!llvm.ptr<struct<(ptr<f16>, ptr<f16>, i64, array<4 x i64>, array<4 x i64>)>>):

       llvm.func @GenericReshape1(%arg0: !llvm.ptr<struct<(ptr<f16>, ptr<f16>, i64, array<4 x i64>, array<4 x i64>)>>) -> !llvm.struct<(ptr<f16>, ptr<f16>, i64, array<2 x i64>, array<2 x i64>)> {
          %1 = llvm.mlir.constant(1 : i64) : i64
          %2 = llvm.getelementptr %arg0[%1] : (!llvm.ptr<struct<(ptr<f16>, ptr<f16>, i64, array<4 x i64>, array<4 x i64>)>>, i64) -> !llvm.ptr<struct<(ptr<f16>, ptr<f16>, i64, array<2 x i64>, array<2 x i64>)>> // The return type is actually !llvm.ptr<struct<(ptr<f16>, ptr<f16>, i64, array<4 x i64>, array<4 x i64>)>>
          %3 = llvm.load %2 : !llvm.ptr<struct<(ptr<f16>, ptr<f16>, i64, array<2 x i64>, array<2 x i64>)>> // The type of %2 is actually !llvm.ptr<struct<(ptr<f16>, ptr<f16>, i64, array<4 x i64>, array<4 x i64>)>>
          ...
          ...
          llvm.return %3 : !llvm.struct<(ptr<f16>, ptr<f16>, i64, array<2 x i64>, array<2 x i64>)> // The type of %3 is actually !llvm.struct<(ptr<f16>, ptr<f16>, i64, array<4 x i64>, array<4 x i64>)>. Hence the error, since the return type of the function is  !llvm.struct<(ptr<f16>, ptr<f16>, i64, array<2 x i64>, array<2 x i64>)>.

Note that these types struct<(ptr<f16>, ptr<f16>, i64, array<2 x i64>, array<2 x i64> and struct<(ptr<f16>, ptr<f16>, i64, array<4 x i64>, array<4 x i64> are the equivalent types of memref<1x1000xf16>, respectively memref<1x1x1x1000xf16>. This equivalence is basically described at LLVM IR Target - MLIR.

Is there a way to avoid this error and to still be able to create the GetElementPointer with a different type than the type of the base pointer (as described above) in MLIR LLVM dialect code and to be able to properly translate it to LLVM IR?
Maybe we can instruct the type system of LLVM IR to be less constrained?

Thank you very much,
Alex

Looks like the GEP in the LLVM Dialect is incorrect and our verifier is just not catching this?

Hi, Mehdi. Yes, the GEP is actually invalid, the reason being that the struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> has a different sizeof than the struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>. But I was trying to use it like that since I was thinking (only) it works for index 1.
Thank you,
Alex

Indeed. There are plenty of insufficiently tight verifiers in the LLVM dialect dating back to the times where we only have one LLVM dialect type that held the textual representation of the corresponding LLVM IR types.