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
144  let verifier = ?;
145}
146
147//===----------------------------------------------------------------------===//
148// 2.6.5 data Construct
149//===----------------------------------------------------------------------===//
150
151def OpenACC_DataOp : OpenACC_Op<"data",
152    [AttrSizedOperandSegments]> {
153  let summary = "data construct";
154
155  let description = [{
156    The "acc.data" operation represents a data construct. It defines vars to
157    be allocated in the current device memory for the duration of the region,
158    whether data should be copied from local memory to the current device
159    memory upon region entry , and copied from device memory to local memory
160    upon region exit.
161
162    Example:
163
164    ```mlir
165    acc.data present(%a: memref<10x10xf32>, %b: memref<10x10xf32>,
166        %c: memref<10xf32>, %d: memref<10xf32>) {
167      // data region
168    }
169    ```
170  }];
171
172
173  let arguments = (ins Optional<I1>:$ifCond,
174                       Variadic<AnyType>:$copyOperands,
175                       Variadic<AnyType>:$copyinOperands,
176                       Variadic<AnyType>:$copyinReadonlyOperands,
177                       Variadic<AnyType>:$copyoutOperands,
178                       Variadic<AnyType>:$copyoutZeroOperands,
179                       Variadic<AnyType>:$createOperands,
180                       Variadic<AnyType>:$createZeroOperands,
181                       Variadic<AnyType>:$noCreateOperands,
182                       Variadic<AnyType>:$presentOperands,
183                       Variadic<AnyType>:$deviceptrOperands,
184                       Variadic<AnyType>:$attachOperands,
185                       OptionalAttr<DefaultValue>:$defaultAttr);
186
187  let regions = (region AnyRegion:$region);
188
189  let assemblyFormat = [{
190    ( `if` `(` $ifCond^ `)` )?
191    ( `copy` `(` $copyOperands^ `:` type($copyOperands) `)` )?
192    ( `copyin` `(` $copyinOperands^ `:` type($copyinOperands) `)` )?
193    ( `copyin_readonly` `(` $copyinReadonlyOperands^ `:`
194        type($copyinReadonlyOperands) `)` )?
195    ( `copyout` `(` $copyoutOperands^ `:` type($copyoutOperands) `)` )?
196    ( `copyout_zero` `(` $copyoutZeroOperands^ `:`
197        type($copyoutZeroOperands) `)` )?
198    ( `create` `(` $createOperands^ `:` type($createOperands) `)` )?
199    ( `create_zero` `(` $createZeroOperands^ `:`
200        type($createZeroOperands) `)` )?
201    ( `no_create` `(` $noCreateOperands^ `:` type($noCreateOperands) `)` )?
202    ( `present` `(` $presentOperands^ `:` type($presentOperands) `)` )?
203    ( `deviceptr` `(` $deviceptrOperands^ `:` type($deviceptrOperands) `)` )?
204    ( `attach` `(` $attachOperands^ `:` type($attachOperands) `)` )?
205    $region attr-dict-with-keyword
206  }];
207}
208
209def OpenACC_TerminatorOp : OpenACC_Op<"terminator", [Terminator]> {
210  let summary = "Generic terminator for OpenACC regions";
211
212  let description = [{
213    A terminator operation for regions that appear in the body of OpenACC
214    operation. Generic OpenACC construct regions are not expected to return any
215    value so the terminator takes no operands. The terminator op returns control
216    to the enclosing op.
217  }];
218
219  let verifier = ?;
220
221  let assemblyFormat = "attr-dict";
222}
223
224//===----------------------------------------------------------------------===//
225// 2.6.6 Enter Data Directive
226//===----------------------------------------------------------------------===//
227
228def OpenACC_EnterDataOp : OpenACC_Op<"enter_data", [AttrSizedOperandSegments]> {
229  let summary = "enter data operation";
230
231  let description = [{
232    The "acc.enter_data" operation represents the OpenACC enter data directive.
233
234    Example:
235
236    ```mlir
237    acc.enter_data create(%d1 : memref<10xf32>) attributes {async}
238    ```
239  }];
240
241  let arguments = (ins Optional<I1>:$ifCond,
242                       Optional<IntOrIndex>:$asyncOperand,
243                       UnitAttr:$async,
244                       Optional<IntOrIndex>:$waitDevnum,
245                       Variadic<IntOrIndex>:$waitOperands,
246                       UnitAttr:$wait,
247                       Variadic<AnyType>:$copyinOperands,
248                       Variadic<AnyType>:$createOperands,
249                       Variadic<AnyType>:$createZeroOperands,
250                       Variadic<AnyType>:$attachOperands);
251
252  let assemblyFormat = [{
253    ( `if` `(` $ifCond^ `)` )?
254    ( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
255    ( `wait_devnum` `(` $waitDevnum^ `:` type($waitDevnum) `)` )?
256    ( `wait` `(` $waitOperands^ `:` type($waitOperands) `)` )?
257    ( `copyin` `(` $copyinOperands^ `:` type($copyinOperands) `)` )?
258    ( `create` `(` $createOperands^ `:` type($createOperands) `)` )?
259    ( `create_zero` `(` $createZeroOperands^ `:`
260        type($createZeroOperands) `)` )?
261    ( `attach` `(` $attachOperands^ `:` type($attachOperands) `)` )?
262    attr-dict-with-keyword
263  }];
264}
265
266//===----------------------------------------------------------------------===//
267// 2.6.6 Exit Data Directive
268//===----------------------------------------------------------------------===//
269
270def OpenACC_ExitDataOp : OpenACC_Op<"exit_data", [AttrSizedOperandSegments]> {
271  let summary = "exit data operation";
272
273  let description = [{
274    The "acc.exit_data" operation represents the OpenACC exit data directive.
275
276    Example:
277
278    ```mlir
279    acc.exit_data delete(%d1 : memref<10xf32>) attributes {async}
280    ```
281  }];
282
283  let arguments = (ins Optional<I1>:$ifCond,
284                       Optional<IntOrIndex>:$asyncOperand,
285                       UnitAttr:$async,
286                       Optional<IntOrIndex>:$waitDevnum,
287                       Variadic<IntOrIndex>:$waitOperands,
288                       UnitAttr:$wait,
289                       Variadic<AnyType>:$copyoutOperands,
290                       Variadic<AnyType>:$deleteOperands,
291                       Variadic<AnyType>:$detachOperands,
292                       UnitAttr:$finalize);
293
294  let assemblyFormat = [{
295    ( `if` `(` $ifCond^ `)` )?
296    ( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
297    ( `wait_devnum` `(` $waitDevnum^ `:` type($waitDevnum) `)` )?
298    ( `wait` `(` $waitOperands^ `:` type($waitOperands) `)` )?
299    ( `copyout` `(` $copyoutOperands^ `:` type($copyoutOperands) `)` )?
300    ( `delete` `(` $deleteOperands^ `:` type($deleteOperands) `)` )?
301    ( `detach` `(` $detachOperands^ `:` type($detachOperands) `)` )?
302    attr-dict-with-keyword
303  }];
304}
305
306//===----------------------------------------------------------------------===//
307// 2.9 loop Construct
308//===----------------------------------------------------------------------===//
309
310def OpenACC_LoopOp : OpenACC_Op<"loop",
311      [AttrSizedOperandSegments,
312       SingleBlockImplicitTerminator<"acc::YieldOp">]> {
313  let summary = "loop construct";
314
315  let description = [{
316    The "acc.loop" operation represents the OpenACC loop construct.
317
318    Example:
319
320    ```mlir
321    acc.loop gang vector {
322      scf.for %arg3 = %c0 to %c10 step %c1 {
323        scf.for %arg4 = %c0 to %c10 step %c1 {
324          scf.for %arg5 = %c0 to %c10 step %c1 {
325            // ... body
326          }
327        }
328      }
329      acc.yield
330    } attributes { collapse = 3 }
331    ```
332  }];
333
334
335  let arguments = (ins OptionalAttr<I64Attr>:$collapse,
336                       Optional<IntOrIndex>:$gangNum,
337                       Optional<IntOrIndex>:$gangStatic,
338                       Optional<IntOrIndex>:$workerNum,
339                       Optional<IntOrIndex>:$vectorLength,
340                       UnitAttr:$seq,
341                       UnitAttr:$independent,
342                       UnitAttr:$auto_,
343                       Variadic<IntOrIndex>:$tileOperands,
344                       Variadic<AnyType>:$privateOperands,
345                       OptionalAttr<OpenACC_ReductionOpAttr>:$reductionOp,
346                       Variadic<AnyType>:$reductionOperands,
347                       DefaultValuedAttr<I64Attr, "0">:$exec_mapping);
348
349  let results = (outs Variadic<AnyType>:$results);
350
351  let regions = (region AnyRegion:$region);
352
353  let extraClassDeclaration = [{
354    static StringRef getCollapseAttrName() { return "collapse"; }
355    static StringRef getSeqAttrName() { return "seq"; }
356    static StringRef getIndependentAttrName() { return "independent"; }
357    static StringRef getAutoAttrName() { return "auto"; }
358    static StringRef getExecutionMappingAttrName() { return "exec_mapping"; }
359    static StringRef getGangKeyword() { return "gang"; }
360    static StringRef getGangNumKeyword() { return "num"; }
361    static StringRef getGangStaticKeyword() { return "static"; }
362    static StringRef getVectorKeyword() { return "vector"; }
363    static StringRef getWorkerKeyword() { return "worker"; }
364    static StringRef getTileKeyword() { return "tile"; }
365    static StringRef getPrivateKeyword() { return "private"; }
366    static StringRef getReductionKeyword() { return "reduction"; }
367  }];
368
369  let verifier = [{ return ::verifyLoopOp(*this); }];
370}
371
372// Yield operation for the acc.loop and acc.parallel operations.
373def OpenACC_YieldOp : OpenACC_Op<"yield", [Terminator,
374    ParentOneOf<["ParallelOp, LoopOp"]>]> {
375  let summary = "Acc yield and termination operation";
376
377  let description = [{
378    `acc.yield` is a special terminator operation for block inside regions in
379    acc ops (parallel and loop). It returns values to the immediately enclosing
380    acc op.
381  }];
382
383  let arguments = (ins Variadic<AnyType>:$operands);
384
385  let builders = [OpBuilderDAG<(ins), [{ /* nothing to do */ }]>];
386
387  let verifier = ?;
388
389  let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?";
390}
391
392//===----------------------------------------------------------------------===//
393// 2.14.1. Init Directive
394//===----------------------------------------------------------------------===//
395
396def OpenACC_InitOp : OpenACC_Op<"init", [AttrSizedOperandSegments]> {
397  let summary = "init operation";
398
399  let description = [{
400    The "acc.init" operation represents the OpenACC init executable
401    directive.
402
403    Example:
404
405    ```mlir
406    acc.init
407    acc.init device_num(%dev1 : i32)
408    ```
409  }];
410
411  let arguments = (ins Variadic<AnyInteger>:$deviceTypeOperands,
412                       Optional<IntOrIndex>:$deviceNumOperand,
413                       Optional<I1>:$ifCond);
414
415  let assemblyFormat = [{
416    ( `device_type` `(` $deviceTypeOperands^ `:` type($deviceTypeOperands) `)` )?
417    ( `device_num` `(` $deviceNumOperand^ `:` type($deviceNumOperand) `)` )?
418    ( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword
419  }];
420}
421
422//===----------------------------------------------------------------------===//
423// 2.14.2. Shutdown
424//===----------------------------------------------------------------------===//
425
426def OpenACC_ShutdownOp : OpenACC_Op<"shutdown", [AttrSizedOperandSegments]> {
427  let summary = "shutdown operation";
428
429  let description = [{
430    The "acc.shutdown" operation represents the OpenACC shutdown executable
431    directive.
432
433    Example:
434
435    ```mlir
436    acc.shutdown
437    acc.shutdown device_num(%dev1 : i32)
438    ```
439  }];
440
441  let arguments = (ins Variadic<AnyInteger>:$deviceTypeOperands,
442                       Optional<IntOrIndex>:$deviceNumOperand,
443                       Optional<I1>:$ifCond);
444
445  let assemblyFormat = [{
446    ( `device_type` `(` $deviceTypeOperands^ `:` type($deviceTypeOperands) `)` )?
447    ( `device_num` `(` $deviceNumOperand^ `:` type($deviceNumOperand) `)` )?
448    ( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword
449  }];
450}
451
452//===----------------------------------------------------------------------===//
453// 2.14.4. Update Directive
454//===----------------------------------------------------------------------===//
455
456def OpenACC_UpdateOp : OpenACC_Op<"update", [AttrSizedOperandSegments]> {
457  let summary = "update operation";
458
459  let description = [{
460    The "acc.udpate" operation represents the OpenACC update executable
461    directive.
462    As host and self clauses are synonyms, any operands for host and self are
463    add to $hostOperands.
464
465    Example:
466
467    ```mlir
468    acc.update device(%d1 : memref<10xf32>) attributes {async}
469    ```
470  }];
471
472  let arguments = (ins Optional<IntOrIndex>:$asyncOperand,
473                       Optional<IntOrIndex>:$waitDevnum,
474                       Variadic<IntOrIndex>:$waitOperands,
475                       UnitAttr:$async,
476                       UnitAttr:$wait,
477                       Variadic<IntOrIndex>:$deviceTypeOperands,
478                       Optional<I1>:$ifCond,
479                       Variadic<AnyType>:$hostOperands,
480                       Variadic<AnyType>:$deviceOperands,
481                       UnitAttr:$ifPresent);
482
483  let assemblyFormat = [{
484    ( `if` `(` $ifCond^ `)` )?
485    ( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
486    ( `wait_devnum` `(` $waitDevnum^ `:` type($waitDevnum) `)` )?
487    ( `device_type` `(` $deviceTypeOperands^ `:`
488        type($deviceTypeOperands) `)` )?
489    ( `wait` `(` $waitOperands^ `:` type($waitOperands) `)` )?
490    ( `host` `(` $hostOperands^ `:` type($hostOperands) `)` )?
491    ( `device` `(` $deviceOperands^ `:` type($deviceOperands) `)` )?
492    attr-dict-with-keyword
493  }];
494}
495
496//===----------------------------------------------------------------------===//
497// 2.16.3. Wait Directive
498//===----------------------------------------------------------------------===//
499
500def OpenACC_WaitOp : OpenACC_Op<"wait", [AttrSizedOperandSegments]> {
501  let summary = "wait operation";
502
503  let description = [{
504    The "acc.wait" operation represents the OpenACC wait executable
505    directive.
506
507    Example:
508
509    ```mlir
510    acc.wait(%value1: index)
511    acc.wait() async(%async1: i32)
512    ```
513  }];
514
515  let arguments = (ins Variadic<IntOrIndex>:$waitOperands,
516                       Optional<IntOrIndex>:$asyncOperand,
517                       Optional<IntOrIndex>:$waitDevnum,
518                       UnitAttr:$async,
519                       Optional<I1>:$ifCond);
520
521  let assemblyFormat = [{
522    ( `(` $waitOperands^ `:` type($waitOperands) `)` )?
523    ( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
524    ( `wait_devnum` `(` $waitDevnum^ `:` type($waitDevnum) `)` )?
525    ( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword
526  }];
527}
528
529#endif // OPENACC_OPS
530