Skip to content

Commit

Permalink
[MLIR] Create memref dialect and move several dialect-specific ops fr…
Browse files Browse the repository at this point in the history
…om std.

Create the memref dialect and move several dialect-specific ops without
dependencies to other ops from std dialect to this dialect.

Moved ops:
AllocOp -> MemRef_AllocOp
AllocaOp -> MemRef_AllocaOp
DeallocOp -> MemRef_DeallocOp
MemRefCastOp -> MemRef_CastOp
GetGlobalMemRefOp -> MemRef_GetGlobalOp
GlobalMemRefOp -> MemRef_GlobalOp
PrefetchOp -> MemRef_PrefetchOp
ReshapeOp -> MemRef_ReshapeOp
StoreOp -> MemRef_StoreOp
TransposeOp -> MemRef_TransposeOp
ViewOp -> MemRef_ViewOp

The roadmap to split the memref dialect from std is discussed here:
https://llvm.discourse.group/t/rfc-split-the-memref-dialect-from-std/2667

Differential Revision: https://reviews.llvm.org/D96425
  • Loading branch information
dfki-jugr committed Feb 18, 2021
1 parent d876214 commit 8aa6c37
Show file tree
Hide file tree
Showing 194 changed files with 4,210 additions and 3,854 deletions.
10 changes: 5 additions & 5 deletions mlir/docs/BufferDeallocationInternals.md
Expand Up @@ -779,8 +779,8 @@ the deallocation of the source value.
## Known Limitations

BufferDeallocation introduces additional copies using allocations from the
std” dialect (“std.alloc”). Analogous, all deallocations use the “std”
dialect-free operation “std.dealloc”. The actual copy process is realized using
“linalg.copy”. Furthermore, buffers are essentially immutable after their
creation in a block. Another limitations are known in the case using
unstructered control flow.
memref” dialect (“memref.alloc”). Analogous, all deallocations use the
“memref” dialect-free operation “memref.dealloc”. The actual copy process is
realized using “linalg.copy”. Furthermore, buffers are essentially immutable
after their creation in a block. Another limitations are known in the case
using unstructered control flow.
10 changes: 5 additions & 5 deletions mlir/docs/Dialects/Linalg.md
Expand Up @@ -406,9 +406,9 @@ into a form that will resemble:
#map0 = affine_map<(d0, d1)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2)>
func @example(%arg0: memref<?x?xf32>, %arg1: memref<?x?xf32>, %arg2: memref<?x?xf32>) {
%0 = memref_cast %arg0 : memref<?x?xf32> to memref<?x?xf32, #map0>
%1 = memref_cast %arg1 : memref<?x?xf32> to memref<?x?xf32, #map0>
%2 = memref_cast %arg2 : memref<?x?xf32> to memref<?x?xf32, #map0>
%0 = memref.cast %arg0 : memref<?x?xf32> to memref<?x?xf32, #map0>
%1 = memref.cast %arg1 : memref<?x?xf32> to memref<?x?xf32, #map0>
%2 = memref.cast %arg2 : memref<?x?xf32> to memref<?x?xf32, #map0>
call @pointwise_add(%0, %1, %2) : (memref<?x?xf32, #map0>, memref<?x?xf32, #map0>, memref<?x?xf32, #map0>) -> ()
return
}
Expand Down Expand Up @@ -518,9 +518,9 @@ A set of ops that manipulate metadata but do not move memory. These ops take
generally alias the operand `view`. At the moment the existing ops are:

```
* `std.view`,
* `memref.view`,
* `std.subview`,
* `std.transpose`.
* `memref.transpose`.
* `linalg.range`,
* `linalg.slice`,
* `linalg.reshape`,
Expand Down
2 changes: 1 addition & 1 deletion mlir/docs/Traits.md
Expand Up @@ -211,7 +211,7 @@ are nested inside of other operations that themselves have this trait.
This trait is carried by region holding operations that define a new scope for
automatic allocation. Such allocations are automatically freed when control is
transferred back from the regions of such operations. As an example, allocations
performed by [`std.alloca`](Dialects/Standard.md#stdalloca-allocaop) are
performed by [`memref.alloca`](Dialects/Standard.md#stdalloca-allocaop) are
automatically freed when control leaves the region of its closest surrounding op
that has the trait AutomaticAllocationScope.

Expand Down
12 changes: 7 additions & 5 deletions mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp
Expand Up @@ -16,6 +16,7 @@
#include "toy/Passes.h"

#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
Expand All @@ -36,15 +37,15 @@ static MemRefType convertTensorToMemRef(TensorType type) {
/// Insert an allocation and deallocation for the given MemRefType.
static Value insertAllocAndDealloc(MemRefType type, Location loc,
PatternRewriter &rewriter) {
auto alloc = rewriter.create<AllocOp>(loc, type);
auto alloc = rewriter.create<memref::AllocOp>(loc, type);

// Make sure to allocate at the beginning of the block.
auto *parentBlock = alloc->getBlock();
alloc->moveBefore(&parentBlock->front());

// Make sure to deallocate this alloc at the end of the block. This is fine
// as toy functions have no control flow.
auto dealloc = rewriter.create<DeallocOp>(loc, alloc);
auto dealloc = rewriter.create<memref::DeallocOp>(loc, alloc);
dealloc->moveBefore(&parentBlock->back());
return alloc;
}
Expand Down Expand Up @@ -152,8 +153,8 @@ struct ConstantOpLowering : public OpRewritePattern<toy::ConstantOp> {

if (!valueShape.empty()) {
for (auto i : llvm::seq<int64_t>(
0, *std::max_element(valueShape.begin(), valueShape.end())))
constantIndices.push_back(rewriter.create<ConstantIndexOp>(loc, i));
0, *std::max_element(valueShape.begin(), valueShape.end())))
constantIndices.push_back(rewriter.create<ConstantIndexOp>(loc, i));
} else {
// This is the case of a tensor of rank 0.
constantIndices.push_back(rewriter.create<ConstantIndexOp>(loc, 0));
Expand Down Expand Up @@ -284,7 +285,8 @@ void ToyToAffineLoweringPass::runOnFunction() {
// We define the specific operations, or dialects, that are legal targets for
// this lowering. In our case, we are lowering to a combination of the
// `Affine` and `Standard` dialects.
target.addLegalDialect<AffineDialect, StandardOpsDialect>();
target.addLegalDialect<AffineDialect, memref::MemRefDialect,
StandardOpsDialect>();

// We also define the Toy dialect as Illegal so that the conversion will fail
// if any of these operations are *not* converted. Given that we actually want
Expand Down
12 changes: 7 additions & 5 deletions mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp
Expand Up @@ -16,6 +16,7 @@
#include "toy/Passes.h"

#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
Expand All @@ -36,15 +37,15 @@ static MemRefType convertTensorToMemRef(TensorType type) {
/// Insert an allocation and deallocation for the given MemRefType.
static Value insertAllocAndDealloc(MemRefType type, Location loc,
PatternRewriter &rewriter) {
auto alloc = rewriter.create<AllocOp>(loc, type);
auto alloc = rewriter.create<memref::AllocOp>(loc, type);

// Make sure to allocate at the beginning of the block.
auto *parentBlock = alloc->getBlock();
alloc->moveBefore(&parentBlock->front());

// Make sure to deallocate this alloc at the end of the block. This is fine
// as toy functions have no control flow.
auto dealloc = rewriter.create<DeallocOp>(loc, alloc);
auto dealloc = rewriter.create<memref::DeallocOp>(loc, alloc);
dealloc->moveBefore(&parentBlock->back());
return alloc;
}
Expand Down Expand Up @@ -152,8 +153,8 @@ struct ConstantOpLowering : public OpRewritePattern<toy::ConstantOp> {

if (!valueShape.empty()) {
for (auto i : llvm::seq<int64_t>(
0, *std::max_element(valueShape.begin(), valueShape.end())))
constantIndices.push_back(rewriter.create<ConstantIndexOp>(loc, i));
0, *std::max_element(valueShape.begin(), valueShape.end())))
constantIndices.push_back(rewriter.create<ConstantIndexOp>(loc, i));
} else {
// This is the case of a tensor of rank 0.
constantIndices.push_back(rewriter.create<ConstantIndexOp>(loc, 0));
Expand Down Expand Up @@ -283,7 +284,8 @@ void ToyToAffineLoweringPass::runOnFunction() {
// We define the specific operations, or dialects, that are legal targets for
// this lowering. In our case, we are lowering to a combination of the
// `Affine` and `Standard` dialects.
target.addLegalDialect<AffineDialect, StandardOpsDialect>();
target.addLegalDialect<AffineDialect, memref::MemRefDialect,
StandardOpsDialect>();

// We also define the Toy dialect as Illegal so that the conversion will fail
// if any of these operations are *not* converted. Given that we actually want
Expand Down
12 changes: 7 additions & 5 deletions mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp
Expand Up @@ -16,6 +16,7 @@
#include "toy/Passes.h"

#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
Expand All @@ -36,15 +37,15 @@ static MemRefType convertTensorToMemRef(TensorType type) {
/// Insert an allocation and deallocation for the given MemRefType.
static Value insertAllocAndDealloc(MemRefType type, Location loc,
PatternRewriter &rewriter) {
auto alloc = rewriter.create<AllocOp>(loc, type);
auto alloc = rewriter.create<memref::AllocOp>(loc, type);

// Make sure to allocate at the beginning of the block.
auto *parentBlock = alloc->getBlock();
alloc->moveBefore(&parentBlock->front());

// Make sure to deallocate this alloc at the end of the block. This is fine
// as toy functions have no control flow.
auto dealloc = rewriter.create<DeallocOp>(loc, alloc);
auto dealloc = rewriter.create<memref::DeallocOp>(loc, alloc);
dealloc->moveBefore(&parentBlock->back());
return alloc;
}
Expand Down Expand Up @@ -152,8 +153,8 @@ struct ConstantOpLowering : public OpRewritePattern<toy::ConstantOp> {

if (!valueShape.empty()) {
for (auto i : llvm::seq<int64_t>(
0, *std::max_element(valueShape.begin(), valueShape.end())))
constantIndices.push_back(rewriter.create<ConstantIndexOp>(loc, i));
0, *std::max_element(valueShape.begin(), valueShape.end())))
constantIndices.push_back(rewriter.create<ConstantIndexOp>(loc, i));
} else {
// This is the case of a tensor of rank 0.
constantIndices.push_back(rewriter.create<ConstantIndexOp>(loc, 0));
Expand Down Expand Up @@ -284,7 +285,8 @@ void ToyToAffineLoweringPass::runOnFunction() {
// We define the specific operations, or dialects, that are legal targets for
// this lowering. In our case, we are lowering to a combination of the
// `Affine` and `Standard` dialects.
target.addLegalDialect<AffineDialect, StandardOpsDialect>();
target.addLegalDialect<AffineDialect, memref::MemRefDialect,
StandardOpsDialect>();

// We also define the Toy dialect as Illegal so that the conversion will fail
// if any of these operations are *not* converted. Given that we actually want
Expand Down
Expand Up @@ -72,7 +72,8 @@ void populateStdToLLVMConversionPatterns(LLVMTypeConverter &converter,

/// Creates a pass to convert the Standard dialect into the LLVMIR dialect.
/// stdlib malloc/free is used by default for allocating memrefs allocated with
/// std.alloc, while LLVM's alloca is used for those allocated with std.alloca.
/// memref.alloc, while LLVM's alloca is used for those allocated with
/// memref.alloca.
std::unique_ptr<OperationPass<ModuleOp>>
createLowerToLLVMPass(const LowerToLLVMOptions &options =
LowerToLLVMOptions::getDefaultOptions());
Expand Down
1 change: 1 addition & 0 deletions mlir/include/mlir/Dialect/CMakeLists.txt
Expand Up @@ -8,6 +8,7 @@ add_subdirectory(GPU)
add_subdirectory(Math)
add_subdirectory(Linalg)
add_subdirectory(LLVMIR)
add_subdirectory(MemRef)
add_subdirectory(OpenACC)
add_subdirectory(OpenMP)
add_subdirectory(PDL)
Expand Down
4 changes: 2 additions & 2 deletions mlir/include/mlir/Dialect/GPU/GPUOps.td
Expand Up @@ -812,7 +812,7 @@ def GPU_AllocOp : GPU_Op<"alloc", [
let summary = "GPU memory allocation operation.";
let description = [{
The `gpu.alloc` operation allocates a region of memory on the GPU. It is
similar to the `std.alloc` op, but supports asynchronous GPU execution.
similar to the `memref.alloc` op, but supports asynchronous GPU execution.

The op does not execute before all async dependencies have finished
executing.
Expand Down Expand Up @@ -850,7 +850,7 @@ def GPU_DeallocOp : GPU_Op<"dealloc", [GPU_AsyncOpInterface]> {
let description = [{
The `gpu.dealloc` operation frees the region of memory referenced by a
memref which was originally created by the `gpu.alloc` operation. It is
similar to the `std.dealloc` op, but supports asynchronous GPU execution.
similar to the `memref.dealloc` op, but supports asynchronous GPU execution.

The op does not execute before all async dependencies have finished
executing.
Expand Down
6 changes: 3 additions & 3 deletions mlir/include/mlir/Dialect/Linalg/EDSC/FoldedIntrinsics.h
Expand Up @@ -35,6 +35,9 @@ struct FoldedValueBuilder {
};

using folded_math_tanh = FoldedValueBuilder<math::TanhOp>;
using folded_memref_alloc = FoldedValueBuilder<memref::AllocOp>;
using folded_memref_cast = FoldedValueBuilder<memref::CastOp>;
using folded_memref_view = FoldedValueBuilder<memref::ViewOp>;
using folded_std_constant_index = FoldedValueBuilder<ConstantIndexOp>;
using folded_std_constant_float = FoldedValueBuilder<ConstantFloatOp>;
using folded_std_constant_int = FoldedValueBuilder<ConstantIntOp>;
Expand All @@ -43,7 +46,6 @@ using folded_std_dim = FoldedValueBuilder<DimOp>;
using folded_std_muli = FoldedValueBuilder<MulIOp>;
using folded_std_addi = FoldedValueBuilder<AddIOp>;
using folded_std_addf = FoldedValueBuilder<AddFOp>;
using folded_std_alloc = FoldedValueBuilder<AllocOp>;
using folded_std_constant = FoldedValueBuilder<ConstantOp>;
using folded_std_constant_float = FoldedValueBuilder<ConstantFloatOp>;
using folded_std_constant_index = FoldedValueBuilder<ConstantIndexOp>;
Expand All @@ -52,13 +54,11 @@ using folded_std_dim = FoldedValueBuilder<DimOp>;
using folded_std_index_cast = FoldedValueBuilder<IndexCastOp>;
using folded_std_muli = FoldedValueBuilder<MulIOp>;
using folded_std_mulf = FoldedValueBuilder<MulFOp>;
using folded_std_memref_cast = FoldedValueBuilder<MemRefCastOp>;
using folded_std_select = FoldedValueBuilder<SelectOp>;
using folded_std_load = FoldedValueBuilder<LoadOp>;
using folded_std_subi = FoldedValueBuilder<SubIOp>;
using folded_std_sub_view = FoldedValueBuilder<SubViewOp>;
using folded_std_tensor_load = FoldedValueBuilder<TensorLoadOp>;
using folded_std_view = FoldedValueBuilder<ViewOp>;
using folded_std_zero_extendi = FoldedValueBuilder<ZeroExtendIOp>;
using folded_std_sign_extendi = FoldedValueBuilder<SignExtendIOp>;
using folded_tensor_extract = FoldedValueBuilder<tensor::ExtractOp>;
Expand Down
4 changes: 2 additions & 2 deletions mlir/include/mlir/Dialect/Linalg/Passes.h
Expand Up @@ -34,11 +34,11 @@ createLinalgPromotionPass(bool dynamicBuffers, bool useAlloca);
std::unique_ptr<OperationPass<FuncOp>> createLinalgPromotionPass();

/// Create a pass to convert Linalg operations to scf.for loops and
/// std.load/std.store accesses.
/// std.load/memref.store accesses.
std::unique_ptr<OperationPass<FuncOp>> createConvertLinalgToLoopsPass();

/// Create a pass to convert Linalg operations to scf.parallel loops and
/// std.load/std.store accesses.
/// std.load/memref.store accesses.
std::unique_ptr<OperationPass<FuncOp>> createConvertLinalgToParallelLoopsPass();

/// Create a pass to convert Linalg operations to affine.for loops and
Expand Down
8 changes: 4 additions & 4 deletions mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
Expand Up @@ -822,7 +822,7 @@ struct PadTensorOpVectorizationPattern : public OpRewritePattern<PadTensorOp> {
/// Match and rewrite for the pattern:
/// ```
/// %alloc = ...
/// [optional] %view = std.view %alloc ...
/// [optional] %view = memref.view %alloc ...
/// %subView = subview %allocOrView ...
/// [optional] linalg.fill(%allocOrView, %cst) ...
/// ...
Expand All @@ -832,7 +832,7 @@ struct PadTensorOpVectorizationPattern : public OpRewritePattern<PadTensorOp> {
/// into
/// ```
/// [unchanged] %alloc = ...
/// [unchanged] [optional] %view = std.view %alloc ...
/// [unchanged] [optional] %view = memref.view %alloc ...
/// [unchanged] [unchanged] %subView = subview %allocOrView ...
/// ...
/// vector.transfer_read %in[...], %cst ...
Expand All @@ -853,7 +853,7 @@ struct LinalgCopyVTRForwardingPattern
/// Match and rewrite for the pattern:
/// ```
/// %alloc = ...
/// [optional] %view = std.view %alloc ...
/// [optional] %view = memref.view %alloc ...
/// %subView = subview %allocOrView...
/// ...
/// vector.transfer_write %..., %allocOrView[...]
Expand All @@ -862,7 +862,7 @@ struct LinalgCopyVTRForwardingPattern
/// into
/// ```
/// [unchanged] %alloc = ...
/// [unchanged] [optional] %view = std.view %alloc ...
/// [unchanged] [optional] %view = memref.view %alloc ...
/// [unchanged] %subView = subview %allocOrView...
/// ...
/// vector.transfer_write %..., %out[...]
Expand Down
1 change: 1 addition & 0 deletions mlir/include/mlir/Dialect/MemRef/CMakeLists.txt
@@ -0,0 +1 @@
add_subdirectory(IR)
2 changes: 2 additions & 0 deletions mlir/include/mlir/Dialect/MemRef/IR/CMakeLists.txt
@@ -0,0 +1,2 @@
add_mlir_dialect(MemRefOps memref)
add_mlir_doc(MemRefOps -gen-dialect-doc MemRefOps Dialects/)
34 changes: 34 additions & 0 deletions mlir/include/mlir/Dialect/MemRef/IR/MemRef.h
@@ -0,0 +1,34 @@
//===- MemRef.h - MemRef dialect --------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_DIALECT_MEMREF_IR_MEMREF_H_
#define MLIR_DIALECT_MEMREF_IR_MEMREF_H_

#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/Interfaces/CallInterfaces.h"
#include "mlir/Interfaces/CastInterfaces.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Interfaces/ViewLikeInterface.h"

//===----------------------------------------------------------------------===//
// MemRef Dialect
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/MemRef/IR/MemRefOpsDialect.h.inc"

//===----------------------------------------------------------------------===//
// MemRef Dialect Operations
//===----------------------------------------------------------------------===//

#define GET_OP_CLASSES
#include "mlir/Dialect/MemRef/IR/MemRefOps.h.inc"

#endif // MLIR_DIALECT_MEMREF_IR_MEMREF_H_
24 changes: 24 additions & 0 deletions mlir/include/mlir/Dialect/MemRef/IR/MemRefBase.td
@@ -0,0 +1,24 @@
//===- MemRefBase.td - Base definitions for memref dialect -*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef MEMREF_BASE
#define MEMREF_BASE

include "mlir/IR/OpBase.td"

def MemRef_Dialect : Dialect {
let name = "memref";
let cppNamespace = "::mlir::memref";
let description = [{
The `memref` dialect is intended to hold core memref creation and
manipulation ops, which are not strongly associated with any particular
other dialect or domain abstraction.
}];
}

#endif // MEMREF_BASE

0 comments on commit 8aa6c37

Please sign in to comment.