1 //===- Dialect.cpp - Implementation of the linalg dialect and types -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the Linalg dialect types and dialect.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "mlir/Dialect/Affine/IR/AffineOps.h"
14 #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
15 #include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h"
16 #include "mlir/Dialect/Linalg/IR/Linalg.h"
17 #include "mlir/Dialect/Math/IR/Math.h"
18 #include "mlir/Dialect/MemRef/IR/MemRef.h"
19 #include "mlir/Dialect/Tensor/IR/Tensor.h"
20 #include "mlir/IR/BuiltinTypes.h"
21 #include "mlir/IR/Dialect.h"
22 #include "mlir/IR/DialectImplementation.h"
23 #include "mlir/IR/FunctionInterfaces.h"
24 #include "mlir/Parser/Parser.h"
25 #include "mlir/Support/LLVM.h"
26 #include "mlir/Transforms/InliningUtils.h"
27
28 #include "llvm/ADT/StringExtras.h"
29 #include "llvm/ADT/TypeSwitch.h"
30 #include "llvm/Support/raw_ostream.h"
31
32 using namespace mlir;
33 using namespace mlir::linalg;
34
35 //===----------------------------------------------------------------------===//
36 // LinalgDialect Dialect Interfaces
37 //===----------------------------------------------------------------------===//
38
39 namespace {
40
41 struct LinalgInlinerInterface : public DialectInlinerInterface {
42 using DialectInlinerInterface::DialectInlinerInterface;
43
44 // We don't have any special restrictions on what can be inlined into
45 // destination regions (e.g. while/conditional bodies). Always allow it.
isLegalToInline__anon564a429b0111::LinalgInlinerInterface46 bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
47 BlockAndValueMapping &valueMapping) const final {
48 return true;
49 }
50 // Operations in Linalg dialect are always legal to inline.
isLegalToInline__anon564a429b0111::LinalgInlinerInterface51 bool isLegalToInline(Operation *, Region *, bool,
52 BlockAndValueMapping &) const final {
53 return true;
54 }
55 // Handle the given inlined terminator by replacing it with a new operation
56 // as necessary. Required when the region has only one block.
handleTerminator__anon564a429b0111::LinalgInlinerInterface57 void handleTerminator(Operation *op,
58 ArrayRef<Value> valuesToRepl) const final {}
59 };
60
61 } // namespace
62
63 //===----------------------------------------------------------------------===//
64 // LinalgDialect
65 //===----------------------------------------------------------------------===//
66
67 /// Attribute name used to to memoize indexing maps for named ops.
68 constexpr const ::llvm::StringLiteral
69 LinalgDialect::kMemoizedIndexingMapsAttrName;
70
71 /// Trait to check if T provides a `regionBuilder` method.
72 template <typename T, typename... Args>
73 using has_region_builder = decltype(T::regionBuilder);
74 template <typename T>
75 using detect_has_region_builder = llvm::is_detected<has_region_builder, T>;
76
77 /// SFINAE helper for single C++ class without a `regionBuilder` method (e.g.
78 /// an OpInterface).
79 template <typename OpType, typename = std::enable_if_t<
80 !detect_has_region_builder<OpType>::value>>
addNamedOpBuilderImpl(llvm::StringMap<LinalgDialect::RegionBuilderFunType> & map)81 void addNamedOpBuilderImpl(
82 llvm::StringMap<LinalgDialect::RegionBuilderFunType> &map) {
83 // Do nothing.
84 }
85
86 template <typename OpType,
87 typename = std::enable_if_t<detect_has_region_builder<OpType>::value>,
88 typename = void>
addNamedOpBuilderImpl(llvm::StringMap<LinalgDialect::RegionBuilderFunType> & map)89 void addNamedOpBuilderImpl(
90 llvm::StringMap<LinalgDialect::RegionBuilderFunType> &map) {
91 map.insert(std::make_pair(
92 OpType::getOperationName(),
93 static_cast<LinalgDialect::RegionBuilderFunType>(OpType::regionBuilder)));
94 }
95
96 template <typename... OpTypes>
addNamedOpBuilders(llvm::StringMap<LinalgDialect::RegionBuilderFunType> & map)97 void addNamedOpBuilders(
98 llvm::StringMap<LinalgDialect::RegionBuilderFunType> &map) {
99 (void)std::initializer_list<int>{0,
100 (addNamedOpBuilderImpl<OpTypes>(map), 0)...};
101 }
102
initialize()103 void mlir::linalg::LinalgDialect::initialize() {
104 addAttributes<
105 #define GET_ATTRDEF_LIST
106 #include "mlir/Dialect/Linalg/IR/LinalgOpsAttrDefs.cpp.inc"
107 >();
108 addOperations<
109 #define GET_OP_LIST
110 #include "mlir/Dialect/Linalg/IR/LinalgOps.cpp.inc"
111 >();
112 addOperations<
113 #define GET_OP_LIST
114 #include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc"
115 >();
116
117 // Fill the Linalg-specific OpName to RegionBuilder map.
118 addNamedOpBuilders<
119 #define GET_OP_LIST
120 #include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc"
121 >(namedStructuredOpRegionBuilders);
122
123 addInterfaces<LinalgInlinerInterface>();
124 }
125
verifyOperationAttribute(Operation * op,NamedAttribute attr)126 LogicalResult LinalgDialect::verifyOperationAttribute(Operation *op,
127 NamedAttribute attr) {
128 if (attr.getName() == LinalgDialect::kMemoizedIndexingMapsAttrName)
129 return success();
130 return op->emitError() << "attribute '" << attr.getName()
131 << "' not supported by the linalg dialect";
132 }
133
134 #include "mlir/Dialect/Linalg/IR/LinalgOpsEnums.cpp.inc"
135
136 #define GET_ATTRDEF_CLASSES
137 #include "mlir/Dialect/Linalg/IR/LinalgOpsAttrDefs.cpp.inc"
138
139 #include "mlir/Dialect/Linalg/IR/LinalgOpsDialect.cpp.inc"
140