diff --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td --- a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td +++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td @@ -693,6 +693,68 @@ let hasVerifier = 1; } +//===----------------------------------------------------------------------===// +// ExtractMetadataOp +//===----------------------------------------------------------------------===// + +def MemRef_ExtractMetadataOp : MemRef_Op<"extract_metadata", + SameVariadicResultSize + ]> { + let summary = "Late binds a base buffer/offset/strides"; + let description = [{ + Queries a base buffer, offset and strides. This op is intended to be used + late in the pipeline, allowing additional layers of transformations and + foldings to be added as lowering progresses from higher-level dialect to + lower level dialects such as the LLVM dialect. + + Its main use case is to lift the logic of ops that manipulate metadata from + the LLVM dialect and to make lowering more progressive. This brings the + following benefits: + - foldings and canonicalizations can happen at a higher level in MLIR: + before this op existed, lowering to LLVM would create large amounts of + LLVMIR. Even when LLVM does a good job at folding the low-level IR from + a performance perspective, it is unnecessarily opaque and inefficient to + send unkempt IR to LLVM. This part could be solved by replicating LLVM + foldings and canonicalizations in the LLVM dialect but this would still + not solve the next problems. + - not all users of MLIR want to lower to LLVM and the information to e.g. + lower to library calls (e.g. libxsmm) or to SPIR-V is plainly not + available. + + This operation can be viewed as the natural complement to the + `memref.reinterpret_cast` op. + + Example: + + ``` + %base, %offset, %sizes, %strides = extract_metadata %memref + : memref<10x?xf32> + + // After folding, the type of %m2 can be memref<10x?xf32> and further + // folded to %memref. + %m2 = memref.reinterpret_cast %base to + offset: [%offset], + sizes: [%sizes#0, %sizes#1], + strides: [%strides#0, %strides#1] + : memref to memref + ``` + }]; + + let arguments = (ins + AnyStridedMemRef:$source + ); + let results = (outs + AnyStridedMemRefOfRank<0>:$base_buffer, + Index:$offset, + Variadic:$sizes, + Variadic:$strides + ); + + let assemblyFormat = [{ + $source `:` type($source) `->` type(results) attr-dict + }]; +} + //===----------------------------------------------------------------------===// // GenericAtomicRMWOp //===----------------------------------------------------------------------===//