• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//===- ViewLikeInterface.td - ViewLike interface -----------*- tablegen -*-===//
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// Defines the interface for view-like operations.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_INTERFACES_VIEWLIKEINTERFACE
14#define MLIR_INTERFACES_VIEWLIKEINTERFACE
15
16include "mlir/IR/OpBase.td"
17
18def ViewLikeOpInterface : OpInterface<"ViewLikeOpInterface"> {
19  let description = [{
20    A view-like operation "views" a buffer in a potentially different way. It
21    takes in a (view of) buffer (and potentially some other operands) and returns
22    another view of buffer.
23  }];
24  let cppNamespace = "::mlir";
25
26  let methods = [
27    InterfaceMethod<
28      "Returns the source buffer from which the view is created.",
29      "Value", "getViewSource">
30  ];
31}
32
33def OffsetSizeAndStrideOpInterface : OpInterface<"OffsetSizeAndStrideOpInterface"> {
34  let description = [{
35    Common interface for ops that allow specifying mixed dynamic and static
36    offsets, sizes and strides variadic operands.
37    Ops that implement this interface need to expose the following methods:
38      1. `getArrayAttrRanks` to specify the length of static integer
39          attributes.
40      2. `offsets`, `sizes` and `strides` variadic operands.
41      3. `static_offsets`, resp. `static_sizes` and `static_strides` integer
42          array attributes.
43
44    The invariants of this interface are:
45      1. `static_offsets`, `static_sizes` and `static_strides` have length
46          exactly `getArrayAttrRanks()`[0] (resp. [1], [2]).
47      2. `offsets`, `sizes` and `strides` have each length at most
48         `getArrayAttrRanks()`[0] (resp. [1], [2]).
49      3. if an entry of `static_offsets` (resp. `static_sizes`,
50         `static_strides`) is equal to a special sentinel value, namely
51         `ShapedType::kDynamicStrideOrOffset` (resp. `ShapedType::kDynamicSize`,
52         `ShapedType::kDynamicStrideOrOffset`), then the corresponding entry is
53         a dynamic offset (resp. size, stride).
54      4. a variadic `offset` (resp. `sizes`, `strides`) operand  must be present
55         for each dynamic offset (resp. size, stride).
56
57    This interface is useful to factor out common behavior and provide support
58    for carrying or injecting static behavior through the use of the static
59    attributes.
60  }];
61
62  let cppNamespace = "::mlir";
63
64  let methods = [
65    InterfaceMethod<
66      /*desc=*/[{
67        Return the expected rank of each of the`static_offsets`, `static_sizes`
68        and `static_strides` attributes.
69      }],
70      /*retTy=*/"std::array<unsigned, 3>",
71      /*methodName=*/"getArrayAttrRanks",
72      /*args=*/(ins),
73      /*methodBody=*/"",
74      /*defaultImplementation=*/[{
75        return $_op.offsets();
76      }]
77    >,
78    InterfaceMethod<
79      /*desc=*/[{
80        Return the dynamic offset operands.
81      }],
82      /*retTy=*/"OperandRange",
83      /*methodName=*/"offsets",
84      /*args=*/(ins),
85      /*methodBody=*/"",
86      /*defaultImplementation=*/[{
87        return $_op.offsets();
88      }]
89    >,
90    InterfaceMethod<
91      /*desc=*/[{
92        Return the dynamic size operands.
93      }],
94      /*retTy=*/"OperandRange",
95      /*methodName=*/"sizes",
96      /*args=*/(ins),
97      /*methodBody=*/"",
98      /*defaultImplementation=*/[{
99        return $_op.sizes();
100      }]
101    >,
102    InterfaceMethod<
103      /*desc=*/[{
104        Return the dynamic stride operands.
105      }],
106      /*retTy=*/"OperandRange",
107      /*methodName=*/"strides",
108      /*args=*/(ins),
109      /*methodBody=*/"",
110      /*defaultImplementation=*/[{
111        return $_op.strides();
112      }]
113    >,
114    InterfaceMethod<
115      /*desc=*/[{
116        Return the static offset attributes.
117      }],
118      /*retTy=*/"ArrayAttr",
119      /*methodName=*/"static_offsets",
120      /*args=*/(ins),
121      /*methodBody=*/"",
122      /*defaultImplementation=*/[{
123        return $_op.static_offsets();
124      }]
125    >,
126    InterfaceMethod<
127      /*desc=*/[{
128        Return the static size attributes.
129      }],
130      /*retTy=*/"ArrayAttr",
131      /*methodName=*/"static_sizes",
132      /*args=*/(ins),
133      /*methodBody=*/"",
134      /*defaultImplementation=*/[{
135        return $_op.static_sizes();
136      }]
137    >,
138    InterfaceMethod<
139      /*desc=*/[{
140        Return the dynamic stride attributes.
141      }],
142      /*retTy=*/"ArrayAttr",
143      /*methodName=*/"static_strides",
144      /*args=*/(ins),
145      /*methodBody=*/"",
146      /*defaultImplementation=*/[{
147        return $_op.static_strides();
148      }]
149    >,
150
151    InterfaceMethod<
152      /*desc=*/[{
153        Return true if the offset `idx` is dynamic.
154      }],
155      /*retTy=*/"bool",
156      /*methodName=*/"isDynamicOffset",
157      /*args=*/(ins "unsigned":$idx),
158      /*methodBody=*/"",
159      /*defaultImplementation=*/[{
160        APInt v = *(static_offsets()
161          .template getAsValueRange<IntegerAttr>().begin() + idx);
162        return ShapedType::isDynamicStrideOrOffset(v.getSExtValue());
163      }]
164    >,
165    InterfaceMethod<
166      /*desc=*/[{
167        Return true if the size `idx` is dynamic.
168      }],
169      /*retTy=*/"bool",
170      /*methodName=*/"isDynamicSize",
171      /*args=*/(ins "unsigned":$idx),
172      /*methodBody=*/"",
173      /*defaultImplementation=*/[{
174        APInt v = *(static_sizes()
175          .template getAsValueRange<IntegerAttr>().begin() + idx);
176        return ShapedType::isDynamic(v.getSExtValue());
177      }]
178    >,
179    InterfaceMethod<
180      /*desc=*/[{
181       Return true if the stride `idx` is dynamic.
182      }],
183      /*retTy=*/"bool",
184      /*methodName=*/"isDynamicStride",
185      /*args=*/(ins "unsigned":$idx),
186      /*methodBody=*/"",
187      /*defaultImplementation=*/[{
188        APInt v = *(static_strides()
189          .template getAsValueRange<IntegerAttr>().begin() + idx);
190        return ShapedType::isDynamicStrideOrOffset(v.getSExtValue());
191      }]
192    >,
193
194    InterfaceMethod<
195      /*desc=*/[{
196        Assert the offset `idx` is a static constant and return its value.
197      }],
198      /*retTy=*/"int64_t",
199      /*methodName=*/"getStaticOffset",
200      /*args=*/(ins "unsigned":$idx),
201      /*methodBody=*/"",
202      /*defaultImplementation=*/[{
203        assert(!$_op.isDynamicOffset(idx) && "expected static offset");
204        APInt v = *(static_offsets().
205          template getAsValueRange<IntegerAttr>().begin() + idx);
206        return v.getSExtValue();
207      }]
208    >,
209    InterfaceMethod<
210      /*desc=*/[{
211        Assert the size `idx` is a static constant and return its value.
212      }],
213      /*retTy=*/"int64_t",
214      /*methodName=*/"getStaticSize",
215      /*args=*/(ins "unsigned":$idx),
216      /*methodBody=*/"",
217      /*defaultImplementation=*/[{
218        assert(!$_op.isDynamicSize(idx) && "expected static size");
219        APInt v = *(static_sizes().
220          template getAsValueRange<IntegerAttr>().begin() + idx);
221        return v.getSExtValue();
222      }]
223    >,
224    InterfaceMethod<
225      /*desc=*/[{
226        Assert the stride `idx` is a static constant and return its value.
227      }],
228      /*retTy=*/"int64_t",
229      /*methodName=*/"getStaticStride",
230      /*args=*/(ins "unsigned":$idx),
231      /*methodBody=*/"",
232      /*defaultImplementation=*/[{
233        assert(!$_op.isDynamicStride(idx) && "expected static stride");
234        APInt v = *(static_strides().
235          template getAsValueRange<IntegerAttr>().begin() + idx);
236        return v.getSExtValue();
237      }]
238    >,
239
240    InterfaceMethod<
241      /*desc=*/[{
242        Assert the offset `idx` is dynamic and return the position of the
243        corresponding operand.
244      }],
245      /*retTy=*/"unsigned",
246      /*methodName=*/"getIndexOfDynamicOffset",
247      /*args=*/(ins "unsigned":$idx),
248      /*methodBody=*/"",
249      /*defaultImplementation=*/[{
250        assert($_op.isDynamicOffset(idx) && "expected dynamic offset");
251        auto numDynamic = getNumDynamicEntriesUpToIdx(
252          static_offsets().template cast<ArrayAttr>(),
253          ShapedType::isDynamicStrideOrOffset,
254          idx);
255        return 1 + numDynamic;
256      }]
257    >,
258    InterfaceMethod<
259      /*desc=*/[{
260        Assert the size `idx` is dynamic and return the position of the
261        corresponding operand.
262      }],
263      /*retTy=*/"unsigned",
264      /*methodName=*/"getIndexOfDynamicSize",
265      /*args=*/(ins "unsigned":$idx),
266      /*methodBody=*/"",
267      /*defaultImplementation=*/[{
268        assert($_op.isDynamicSize(idx) && "expected dynamic size");
269        auto numDynamic = getNumDynamicEntriesUpToIdx(
270          static_sizes().template cast<ArrayAttr>(), ShapedType::isDynamic, idx);
271        return 1 + offsets().size() + numDynamic;
272      }]
273    >,
274    InterfaceMethod<
275      /*desc=*/[{
276        Assert the stride `idx` is dynamic and return the position of the
277        corresponding operand.
278      }],
279      /*retTy=*/"unsigned",
280      /*methodName=*/"getIndexOfDynamicStride",
281      /*args=*/(ins "unsigned":$idx),
282      /*methodBody=*/"",
283      /*defaultImplementation=*/[{
284        assert($_op.isDynamicStride(idx) && "expected dynamic stride");
285        auto numDynamic = getNumDynamicEntriesUpToIdx(
286          static_strides().template cast<ArrayAttr>(),
287          ShapedType::isDynamicStrideOrOffset,
288          idx);
289        return 1 + offsets().size() + sizes().size() + numDynamic;
290      }]
291    >,
292    InterfaceMethod<
293      /*desc=*/[{
294        Helper method to compute the number of dynamic entries of `attr`, up to
295        `idx` using `isDynamic` to determine whether an entry is dynamic.
296      }],
297      /*retTy=*/"unsigned",
298      /*methodName=*/"getNumDynamicEntriesUpToIdx",
299      /*args=*/(ins "ArrayAttr":$attr,
300                    "llvm::function_ref<bool(int64_t)>":$isDynamic,
301                    "unsigned":$idx),
302      /*methodBody=*/"",
303      /*defaultImplementation=*/[{
304        return std::count_if(
305          attr.getValue().begin(), attr.getValue().begin() + idx,
306          [&](Attribute attr) {
307            return isDynamic(attr.cast<IntegerAttr>().getInt());
308          });
309      }]
310    >,
311
312    InterfaceMethod<
313      /*desc=*/[{
314        Assert the offset `idx` is dynamic and return its value.
315      }],
316      /*retTy=*/"Value",
317      /*methodName=*/"getDynamicOffset",
318      /*args=*/(ins "unsigned":$idx),
319      /*methodBody=*/"",
320      /*defaultImplementation=*/[{
321        return $_op.getOperand(getIndexOfDynamicOffset(idx));
322      }]
323    >,
324    InterfaceMethod<
325      /*desc=*/[{
326        Assert the size `idx` is dynamic and return its value.
327      }],
328      /*retTy=*/"Value",
329      /*methodName=*/"getDynamicSize",
330      /*args=*/(ins "unsigned":$idx),
331      /*methodBody=*/"",
332      /*defaultImplementation=*/[{
333        return $_op.getOperand(getIndexOfDynamicSize(idx));
334      }]
335    >,
336    InterfaceMethod<
337      /*desc=*/[{
338        Assert the stride `idx` is dynamic and return its value.
339      }],
340      /*retTy=*/"Value",
341      /*methodName=*/"getDynamicStride",
342      /*args=*/(ins "unsigned":$idx),
343      /*methodBody=*/"",
344      /*defaultImplementation=*/[{
345        return $_op.getOperand(getIndexOfDynamicStride(idx));
346      }]
347    >,
348  ];
349
350  let extraClassDeclaration = [{
351    static StringRef getStaticOffsetsAttrName() {
352      return "static_offsets";
353    }
354    static StringRef getStaticSizesAttrName() {
355      return "static_sizes";
356    }
357    static StringRef getStaticStridesAttrName() {
358      return "static_strides";
359    }
360    static ArrayRef<StringRef> getSpecialAttrNames() {
361      static SmallVector<StringRef, 4> names{
362        OffsetSizeAndStrideOpInterface::getStaticOffsetsAttrName(),
363        OffsetSizeAndStrideOpInterface::getStaticSizesAttrName(),
364        OffsetSizeAndStrideOpInterface::getStaticStridesAttrName(),
365        OpTrait::AttrSizedOperandSegments<void>::getOperandSegmentSizeAttr()};
366      return names;
367   }
368  }];
369
370  let verify = [{
371    return mlir::verify(cast<OffsetSizeAndStrideOpInterface>($_op));
372  }];
373}
374
375#endif // MLIR_INTERFACES_VIEWLIKEINTERFACE
376