1//===- OpenACC.td - OpenACC operation definitions ----------*- tablegen -*-===//
2//
3// Part of the MLIR 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 MLIR OpenACC operations.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef OPENACC_OPS
14#define OPENACC_OPS
15
16include "mlir/IR/OpBase.td"
17include "mlir/Dialect/OpenACC/AccCommon.td"
18
19def OpenACC_Dialect : Dialect {
20  let name = "acc";
21
22  let summary = "An OpenACC dialect for MLIR.";
23
24  let description = [{
25    This dialect models the construct from the OpenACC 3.1 directive language.
26  }];
27
28  let cppNamespace = "::mlir::acc";
29}
30
31// Base class for OpenACC dialect ops.
32class OpenACC_Op<string mnemonic, list<OpTrait> traits = []> :
33  Op<OpenACC_Dialect, mnemonic, traits> {
34
35  let printer = [{ return ::print(p, *this); }];
36  let verifier = [{ return ::verify(*this); }];
37  let parser = [{ return ::parse$cppClass(parser, result); }];
38}
39
40// Reduction operation enumeration.
41def OpenACC_ReductionOpAdd : StrEnumAttrCase<"redop_add">;
42def OpenACC_ReductionOpMul : StrEnumAttrCase<"redop_mul">;
43def OpenACC_ReductionOpMax : StrEnumAttrCase<"redop_max">;
44def OpenACC_ReductionOpMin : StrEnumAttrCase<"redop_min">;
45def OpenACC_ReductionOpAnd : StrEnumAttrCase<"redop_and">;
46def OpenACC_ReductionOpOr : StrEnumAttrCase<"redop_or">;
47def OpenACC_ReductionOpXor : StrEnumAttrCase<"redop_xor">;
48def OpenACC_ReductionOpLogEqv : StrEnumAttrCase<"redop_leqv">;
49def OpenACC_ReductionOpLogNeqv : StrEnumAttrCase<"redop_lneqv">;
50def OpenACC_ReductionOpLogAnd : StrEnumAttrCase<"redop_land">;
51def OpenACC_ReductionOpLogOr : StrEnumAttrCase<"redop_lor">;
52
53def OpenACC_ReductionOpAttr : StrEnumAttr<"ReductionOpAttr",
54    "built-in reduction operations supported by OpenACC",
55    [OpenACC_ReductionOpAdd, OpenACC_ReductionOpMul, OpenACC_ReductionOpMax,
56     OpenACC_ReductionOpMin, OpenACC_ReductionOpAnd, OpenACC_ReductionOpOr,
57     OpenACC_ReductionOpXor, OpenACC_ReductionOpLogEqv,
58     OpenACC_ReductionOpLogNeqv, OpenACC_ReductionOpLogAnd,
59     OpenACC_ReductionOpLogOr
60    ]> {
61  let cppNamespace = "::mlir::acc";
62}
63
64// Type used in operation below.
65def IntOrIndex : AnyTypeOf<[AnyInteger, Index]>;
66
67//===----------------------------------------------------------------------===//
68// 2.5.1 parallel Construct
69//===----------------------------------------------------------------------===//
70
71def OpenACC_ParallelOp : OpenACC_Op<"parallel",
72    [AttrSizedOperandSegments]> {
73  let summary = "parallel construct";
74  let description = [{
75    The "acc.parallel" operation represents a parallel construct block. It has
76    one region to be executed in parallel on the current device.
77
78    Example:
79
80    ```mlir
81    acc.parallel num_gangs(%c10) num_workers(%c10)
82        private(%c : memref<10xf32>) {
83      // parallel region
84    }
85    ```
86  }];
87
88  let arguments = (ins Optional<IntOrIndex>:$async,
89                       UnitAttr:$asyncAttr,
90                       Variadic<IntOrIndex>:$waitOperands,
91                       UnitAttr:$waitAttr,
92                       Optional<IntOrIndex>:$numGangs,
93                       Optional<IntOrIndex>:$numWorkers,
94                       Optional<IntOrIndex>:$vectorLength,
95                       Optional<I1>:$ifCond,
96                       Optional<I1>:$selfCond,
97                       UnitAttr:$selfAttr,
98                       OptionalAttr<OpenACC_ReductionOpAttr>:$reductionOp,
99                       Variadic<AnyType>:$reductionOperands,
100                       Variadic<AnyType>:$copyOperands,
101                       Variadic<AnyType>:$copyinOperands,
102                       Variadic<AnyType>:$copyinReadonlyOperands,
103                       Variadic<AnyType>:$copyoutOperands,
104                       Variadic<AnyType>:$copyoutZeroOperands,
105                       Variadic<AnyType>:$createOperands,
106                       Variadic<AnyType>:$createZeroOperands,
107                       Variadic<AnyType>:$noCreateOperands,
108                       Variadic<AnyType>:$presentOperands,
109                       Variadic<AnyType>:$devicePtrOperands,
110                       Variadic<AnyType>:$attachOperands,
111                       Variadic<AnyType>:$gangPrivateOperands,
112                       Variadic<AnyType>:$gangFirstPrivateOperands,
113                       OptionalAttr<DefaultValue>:$defaultAttr);
114
115  let regions = (region AnyRegion:$region);
116
117  let extraClassDeclaration = [{
118    static StringRef getAsyncKeyword() { return "async"; }
119    static StringRef getAsyncAttrName() { return "asyncAttr"; }
120    static StringRef getWaitKeyword() { return "wait"; }
121    static StringRef getWaitAttrName() { return "waitAttr"; }
122    static StringRef getNumGangsKeyword() { return "num_gangs"; }
123    static StringRef getNumWorkersKeyword() { return "num_workers"; }
124    static StringRef getVectorLengthKeyword() { return "vector_length"; }
125    static StringRef getIfKeyword() { return "if"; }
126    static StringRef getSelfKeyword() { return "self"; }
127    static StringRef getSelfAttrName() { return "selfAttr"; }
128    static StringRef getReductionKeyword() { return "reduction"; }
129    static StringRef getCopyKeyword() { return "copy"; }
130    static StringRef getCopyinKeyword() { return "copyin"; }
131    static StringRef getCopyinReadonlyKeyword() { return "copyin_readonly"; }
132    static StringRef getCopyoutKeyword() { return "copyout"; }
133    static StringRef getCopyoutZeroKeyword() { return "copyout_zero"; }
134    static StringRef getCreateKeyword() { return "create"; }
135    static StringRef getCreateZeroKeyword() { return "create_zero"; }
136    static StringRef getNoCreateKeyword() { return "no_create"; }
137    static StringRef getPresentKeyword() { return "present"; }
138    static StringRef getDevicePtrKeyword() { return "deviceptr"; }
139    static StringRef getAttachKeyword() { return "attach"; }
140    static StringRef getPrivateKeyword() { return "private"; }
141    static StringRef getFirstPrivateKeyword() { return "firstprivate"; }
142
143    /// The number of data operands.
144    unsigned getNumDataOperands();
145
146    /// The i-th data operand passed.
147    Value getDataOperand(unsigned i);
148  }];
149
150  let verifier = ?;
151}
152
153//===----------------------------------------------------------------------===//
154// 2.6.5 data Construct
155//===----------------------------------------------------------------------===//
156
157def OpenACC_DataOp : OpenACC_Op<"data",
158    [AttrSizedOperandSegments]> {
159  let summary = "data construct";
160
161  let description = [{
162    The "acc.data" operation represents a data construct. It defines vars to
163    be allocated in the current device memory for the duration of the region,
164    whether data should be copied from local memory to the current device
165    memory upon region entry , and copied from device memory to local memory
166    upon region exit.
167
168    Example:
169
170    ```mlir
171    acc.data present(%a: memref<10x10xf32>, %b: memref<10x10xf32>,
172        %c: memref<10xf32>, %d: memref<10xf32>) {
173      // data region
174    }
175    ```
176  }];
177
178
179  let arguments = (ins Optional<I1>:$ifCond,
180                       Variadic<AnyType>:$copyOperands,
181                       Variadic<AnyType>:$copyinOperands,
182                       Variadic<AnyType>:$copyinReadonlyOperands,
183                       Variadic<AnyType>:$copyoutOperands,
184                       Variadic<AnyType>:$copyoutZeroOperands,
185                       Variadic<AnyType>:$createOperands,
186                       Variadic<AnyType>:$createZeroOperands,
187                       Variadic<AnyType>:$noCreateOperands,
188                       Variadic<AnyType>:$presentOperands,
189                       Variadic<AnyType>:$deviceptrOperands,
190                       Variadic<AnyType>:$attachOperands,
191                       OptionalAttr<DefaultValue>:$defaultAttr);
192
193  let regions = (region AnyRegion:$region);
194
195  let extraClassDeclaration = [{
196    /// The number of data operands.
197    unsigned getNumDataOperands();
198
199    /// The i-th data operand passed.
200    Value getDataOperand(unsigned i);
201  }];
202
203  let assemblyFormat = [{
204    ( `if` `(` $ifCond^ `)` )?
205    ( `copy` `(` $copyOperands^ `:` type($copyOperands) `)` )?
206    ( `copyin` `(` $copyinOperands^ `:` type($copyinOperands) `)` )?
207    ( `copyin_readonly` `(` $copyinReadonlyOperands^ `:`
208        type($copyinReadonlyOperands) `)` )?
209    ( `copyout` `(` $copyoutOperands^ `:` type($copyoutOperands) `)` )?
210    ( `copyout_zero` `(` $copyoutZeroOperands^ `:`
211        type($copyoutZeroOperands) `)` )?
212    ( `create` `(` $createOperands^ `:` type($createOperands) `)` )?
213    ( `create_zero` `(` $createZeroOperands^ `:`
214        type($createZeroOperands) `)` )?
215    ( `no_create` `(` $noCreateOperands^ `:` type($noCreateOperands) `)` )?
216    ( `present` `(` $presentOperands^ `:` type($presentOperands) `)` )?
217    ( `deviceptr` `(` $deviceptrOperands^ `:` type($deviceptrOperands) `)` )?
218    ( `attach` `(` $attachOperands^ `:` type($attachOperands) `)` )?
219    $region attr-dict-with-keyword
220  }];
221}
222
223def OpenACC_TerminatorOp : OpenACC_Op<"terminator", [Terminator]> {
224  let summary = "Generic terminator for OpenACC regions";
225
226  let description = [{
227    A terminator operation for regions that appear in the body of OpenACC
228    operation. Generic OpenACC construct regions are not expected to return any
229    value so the terminator takes no operands. The terminator op returns control
230    to the enclosing op.
231  }];
232
233  let verifier = ?;
234
235  let assemblyFormat = "attr-dict";
236}
237
238//===----------------------------------------------------------------------===//
239// 2.6.6 Enter Data Directive
240//===----------------------------------------------------------------------===//
241
242def OpenACC_EnterDataOp : OpenACC_Op<"enter_data", [AttrSizedOperandSegments]> {
243  let summary = "enter data operation";
244
245  let description = [{
246    The "acc.enter_data" operation represents the OpenACC enter data directive.
247
248    Example:
249
250    ```mlir
251    acc.enter_data create(%d1 : memref<10xf32>) attributes {async}
252    ```
253  }];
254
255  let arguments = (ins Optional<I1>:$ifCond,
256                       Optional<IntOrIndex>:$asyncOperand,
257                       UnitAttr:$async,
258                       Optional<IntOrIndex>:$waitDevnum,
259                       Variadic<IntOrIndex>:$waitOperands,
260                       UnitAttr:$wait,
261                       Variadic<AnyType>:$copyinOperands,
262                       Variadic<AnyType>:$createOperands,
263                       Variadic<AnyType>:$createZeroOperands,
264                       Variadic<AnyType>:$attachOperands);
265
266  let extraClassDeclaration = [{
267    /// The number of data operands.
268    unsigned getNumDataOperands();
269
270    /// The i-th data operand passed.
271    Value getDataOperand(unsigned i);
272  }];
273
274  let assemblyFormat = [{
275    ( `if` `(` $ifCond^ `)` )?
276    ( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
277    ( `wait_devnum` `(` $waitDevnum^ `:` type($waitDevnum) `)` )?
278    ( `wait` `(` $waitOperands^ `:` type($waitOperands) `)` )?
279    ( `copyin` `(` $copyinOperands^ `:` type($copyinOperands) `)` )?
280    ( `create` `(` $createOperands^ `:` type($createOperands) `)` )?
281    ( `create_zero` `(` $createZeroOperands^ `:`
282        type($createZeroOperands) `)` )?
283    ( `attach` `(` $attachOperands^ `:` type($attachOperands) `)` )?
284    attr-dict-with-keyword
285  }];
286
287  let hasCanonicalizer = 1;
288}
289
290//===----------------------------------------------------------------------===//
291// 2.6.6 Exit Data Directive
292//===----------------------------------------------------------------------===//
293
294def OpenACC_ExitDataOp : OpenACC_Op<"exit_data", [AttrSizedOperandSegments]> {
295  let summary = "exit data operation";
296
297  let description = [{
298    The "acc.exit_data" operation represents the OpenACC exit data directive.
299
300    Example:
301
302    ```mlir
303    acc.exit_data delete(%d1 : memref<10xf32>) attributes {async}
304    ```
305  }];
306
307  let arguments = (ins Optional<I1>:$ifCond,
308                       Optional<IntOrIndex>:$asyncOperand,
309                       UnitAttr:$async,
310                       Optional<IntOrIndex>:$waitDevnum,
311                       Variadic<IntOrIndex>:$waitOperands,
312                       UnitAttr:$wait,
313                       Variadic<AnyType>:$copyoutOperands,
314                       Variadic<AnyType>:$deleteOperands,
315                       Variadic<AnyType>:$detachOperands,
316                       UnitAttr:$finalize);
317
318  let extraClassDeclaration = [{
319    /// The number of data operands.
320    unsigned getNumDataOperands();
321
322    /// The i-th data operand passed.
323    Value getDataOperand(unsigned i);
324  }];
325
326  let assemblyFormat = [{
327    ( `if` `(` $ifCond^ `)` )?
328    ( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
329    ( `wait_devnum` `(` $waitDevnum^ `:` type($waitDevnum) `)` )?
330    ( `wait` `(` $waitOperands^ `:` type($waitOperands) `)` )?
331    ( `copyout` `(` $copyoutOperands^ `:` type($copyoutOperands) `)` )?
332    ( `delete` `(` $deleteOperands^ `:` type($deleteOperands) `)` )?
333    ( `detach` `(` $detachOperands^ `:` type($detachOperands) `)` )?
334    attr-dict-with-keyword
335  }];
336
337  let hasCanonicalizer = 1;
338}
339
340//===----------------------------------------------------------------------===//
341// 2.9 loop Construct
342//===----------------------------------------------------------------------===//
343
344def OpenACC_LoopOp : OpenACC_Op<"loop",
345      [AttrSizedOperandSegments,
346       SingleBlockImplicitTerminator<"acc::YieldOp">]> {
347  let summary = "loop construct";
348
349  let description = [{
350    The "acc.loop" operation represents the OpenACC loop construct.
351
352    Example:
353
354    ```mlir
355    acc.loop gang vector {
356      scf.for %arg3 = %c0 to %c10 step %c1 {
357        scf.for %arg4 = %c0 to %c10 step %c1 {
358          scf.for %arg5 = %c0 to %c10 step %c1 {
359            // ... body
360          }
361        }
362      }
363      acc.yield
364    } attributes { collapse = 3 }
365    ```
366  }];
367
368
369  let arguments = (ins OptionalAttr<I64Attr>:$collapse,
370                       Optional<IntOrIndex>:$gangNum,
371                       Optional<IntOrIndex>:$gangStatic,
372                       Optional<IntOrIndex>:$workerNum,
373                       Optional<IntOrIndex>:$vectorLength,
374                       UnitAttr:$seq,
375                       UnitAttr:$independent,
376                       UnitAttr:$auto_,
377                       Variadic<IntOrIndex>:$tileOperands,
378                       Variadic<AnyType>:$privateOperands,
379                       OptionalAttr<OpenACC_ReductionOpAttr>:$reductionOp,
380                       Variadic<AnyType>:$reductionOperands,
381                       DefaultValuedAttr<I64Attr, "0">:$exec_mapping);
382
383  let results = (outs Variadic<AnyType>:$results);
384
385  let regions = (region AnyRegion:$region);
386
387  let extraClassDeclaration = [{
388    static StringRef getCollapseAttrName() { return "collapse"; }
389    static StringRef getSeqAttrName() { return "seq"; }
390    static StringRef getIndependentAttrName() { return "independent"; }
391    static StringRef getAutoAttrName() { return "auto"; }
392    static StringRef getExecutionMappingAttrName() { return "exec_mapping"; }
393    static StringRef getGangKeyword() { return "gang"; }
394    static StringRef getGangNumKeyword() { return "num"; }
395    static StringRef getGangStaticKeyword() { return "static"; }
396    static StringRef getVectorKeyword() { return "vector"; }
397    static StringRef getWorkerKeyword() { return "worker"; }
398    static StringRef getTileKeyword() { return "tile"; }
399    static StringRef getPrivateKeyword() { return "private"; }
400    static StringRef getReductionKeyword() { return "reduction"; }
401  }];
402
403  let verifier = [{ return ::verifyLoopOp(*this); }];
404}
405
406// Yield operation for the acc.loop and acc.parallel operations.
407def OpenACC_YieldOp : OpenACC_Op<"yield", [Terminator,
408    ParentOneOf<["ParallelOp, LoopOp"]>]> {
409  let summary = "Acc yield and termination operation";
410
411  let description = [{
412    `acc.yield` is a special terminator operation for block inside regions in
413    acc ops (parallel and loop). It returns values to the immediately enclosing
414    acc op.
415  }];
416
417  let arguments = (ins Variadic<AnyType>:$operands);
418
419  let builders = [OpBuilder<(ins), [{ /* nothing to do */ }]>];
420
421  let verifier = ?;
422
423  let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?";
424}
425
426//===----------------------------------------------------------------------===//
427// 2.14.1. Init Directive
428//===----------------------------------------------------------------------===//
429
430def OpenACC_InitOp : OpenACC_Op<"init", [AttrSizedOperandSegments]> {
431  let summary = "init operation";
432
433  let description = [{
434    The "acc.init" operation represents the OpenACC init executable
435    directive.
436
437    Example:
438
439    ```mlir
440    acc.init
441    acc.init device_num(%dev1 : i32)
442    ```
443  }];
444
445  let arguments = (ins Variadic<AnyInteger>:$deviceTypeOperands,
446                       Optional<IntOrIndex>:$deviceNumOperand,
447                       Optional<I1>:$ifCond);
448
449  let assemblyFormat = [{
450    ( `device_type` `(` $deviceTypeOperands^ `:` type($deviceTypeOperands) `)` )?
451    ( `device_num` `(` $deviceNumOperand^ `:` type($deviceNumOperand) `)` )?
452    ( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword
453  }];
454}
455
456//===----------------------------------------------------------------------===//
457// 2.14.2. Shutdown
458//===----------------------------------------------------------------------===//
459
460def OpenACC_ShutdownOp : OpenACC_Op<"shutdown", [AttrSizedOperandSegments]> {
461  let summary = "shutdown operation";
462
463  let description = [{
464    The "acc.shutdown" operation represents the OpenACC shutdown executable
465    directive.
466
467    Example:
468
469    ```mlir
470    acc.shutdown
471    acc.shutdown device_num(%dev1 : i32)
472    ```
473  }];
474
475  let arguments = (ins Variadic<AnyInteger>:$deviceTypeOperands,
476                       Optional<IntOrIndex>:$deviceNumOperand,
477                       Optional<I1>:$ifCond);
478
479  let assemblyFormat = [{
480    ( `device_type` `(` $deviceTypeOperands^ `:` type($deviceTypeOperands) `)` )?
481    ( `device_num` `(` $deviceNumOperand^ `:` type($deviceNumOperand) `)` )?
482    ( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword
483  }];
484}
485
486//===----------------------------------------------------------------------===//
487// 2.14.4. Update Directive
488//===----------------------------------------------------------------------===//
489
490def OpenACC_UpdateOp : OpenACC_Op<"update", [AttrSizedOperandSegments]> {
491  let summary = "update operation";
492
493  let description = [{
494    The "acc.udpate" operation represents the OpenACC update executable
495    directive.
496    As host and self clauses are synonyms, any operands for host and self are
497    add to $hostOperands.
498
499    Example:
500
501    ```mlir
502    acc.update device(%d1 : memref<10xf32>) attributes {async}
503    ```
504  }];
505
506  let arguments = (ins Optional<I1>:$ifCond,
507                       Optional<IntOrIndex>:$asyncOperand,
508                       Optional<IntOrIndex>:$waitDevnum,
509                       Variadic<IntOrIndex>:$waitOperands,
510                       UnitAttr:$async,
511                       UnitAttr:$wait,
512                       Variadic<IntOrIndex>:$deviceTypeOperands,
513                       Variadic<AnyType>:$hostOperands,
514                       Variadic<AnyType>:$deviceOperands,
515                       UnitAttr:$ifPresent);
516
517  let extraClassDeclaration = [{
518    /// The number of data operands.
519    unsigned getNumDataOperands();
520
521    /// The i-th data operand passed.
522    Value getDataOperand(unsigned i);
523  }];
524
525  let assemblyFormat = [{
526    ( `if` `(` $ifCond^ `)` )?
527    ( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
528    ( `wait_devnum` `(` $waitDevnum^ `:` type($waitDevnum) `)` )?
529    ( `device_type` `(` $deviceTypeOperands^ `:`
530        type($deviceTypeOperands) `)` )?
531    ( `wait` `(` $waitOperands^ `:` type($waitOperands) `)` )?
532    ( `host` `(` $hostOperands^ `:` type($hostOperands) `)` )?
533    ( `device` `(` $deviceOperands^ `:` type($deviceOperands) `)` )?
534    attr-dict-with-keyword
535  }];
536
537  let hasCanonicalizer = 1;
538}
539
540//===----------------------------------------------------------------------===//
541// 2.16.3. Wait Directive
542//===----------------------------------------------------------------------===//
543
544def OpenACC_WaitOp : OpenACC_Op<"wait", [AttrSizedOperandSegments]> {
545  let summary = "wait operation";
546
547  let description = [{
548    The "acc.wait" operation represents the OpenACC wait executable
549    directive.
550
551    Example:
552
553    ```mlir
554    acc.wait(%value1: index)
555    acc.wait() async(%async1: i32)
556    ```
557  }];
558
559  let arguments = (ins Variadic<IntOrIndex>:$waitOperands,
560                       Optional<IntOrIndex>:$asyncOperand,
561                       Optional<IntOrIndex>:$waitDevnum,
562                       UnitAttr:$async,
563                       Optional<I1>:$ifCond);
564
565  let assemblyFormat = [{
566    ( `(` $waitOperands^ `:` type($waitOperands) `)` )?
567    ( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
568    ( `wait_devnum` `(` $waitDevnum^ `:` type($waitDevnum) `)` )?
569    ( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword
570  }];
571}
572
573#endif // OPENACC_OPS
574