xref: /llvm-project/mlir/include/mlir/Dialect/Async/Passes.td (revision 88f0e4c75c1ac498f2223fc640c4ff6c572c5ed1)
1//===-- Passes.td - Async pass definition file -------------*- 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#ifndef MLIR_DIALECT_ASYNC_PASSES
10#define MLIR_DIALECT_ASYNC_PASSES
11
12include "mlir/Pass/PassBase.td"
13
14def AsyncParallelFor : Pass<"async-parallel-for", "ModuleOp"> {
15  let summary = "Convert scf.parallel operations to multiple async compute ops "
16                "executed concurrently for non-overlapping iteration ranges";
17  let constructor = "mlir::createAsyncParallelForPass()";
18
19  let options = [
20    Option<"asyncDispatch", "async-dispatch",
21      "bool", /*default=*/"true",
22      "Dispatch async compute tasks using recursive work splitting. If `false` "
23      "async compute tasks will be launched using simple for loop in the "
24      "caller thread.">,
25
26    Option<"numWorkerThreads", "num-workers",
27      "int32_t", /*default=*/"8",
28      "The number of available workers to execute async operations. If `-1` "
29      "the value will be retrieved from the runtime.">,
30
31    Option<"minTaskSize", "min-task-size",
32      "int32_t", /*default=*/"1000",
33      "The minimum task size for sharding parallel operation.">
34  ];
35
36  let dependentDialects = [
37    "arith::ArithDialect",
38    "async::AsyncDialect",
39    "func::FuncDialect",
40    "scf::SCFDialect"
41  ];
42}
43
44def AsyncToAsyncRuntime : Pass<"async-to-async-runtime", "ModuleOp"> {
45  let summary = "Lower all high level async operations (e.g. async.execute) to"
46                "the explicit async.runtime and async.coro operations";
47  let constructor = "mlir::createAsyncToAsyncRuntimePass()";
48  let dependentDialects = ["async::AsyncDialect", "func::FuncDialect", "cf::ControlFlowDialect"];
49}
50
51def AsyncFuncToAsyncRuntime : Pass<"async-func-to-async-runtime", "ModuleOp"> {
52  let summary = "Lower async.func operations to the explicit async.runtime and"
53                "async.coro operations";
54  let constructor = "mlir::createAsyncFuncToAsyncRuntimePass()";
55  let dependentDialects = ["async::AsyncDialect", "func::FuncDialect"];
56}
57
58def AsyncRuntimeRefCounting : Pass<"async-runtime-ref-counting"> {
59  let summary = "Automatic reference counting for Async runtime operations";
60  let description = [{
61    This pass works at the async runtime abtraction level, after all
62    `async.execute` and `async.await` operations are lowered to the async
63    runtime API calls, and async coroutine operations.
64
65    It relies on the LLVM coroutines switched-resume lowering semantics for
66    the correct placing of the reference counting operations.
67
68    See: https://llvm.org/docs/Coroutines.html#switched-resume-lowering
69  }];
70
71  let constructor = "mlir::createAsyncRuntimeRefCountingPass()";
72  let dependentDialects = ["async::AsyncDialect"];
73}
74
75def AsyncRuntimeRefCountingOpt : Pass<"async-runtime-ref-counting-opt"> {
76  let summary = "Optimize automatic reference counting operations for the"
77                "Async runtime by removing redundant operations";
78  let constructor = "mlir::createAsyncRuntimeRefCountingOptPass()";
79  let dependentDialects = ["async::AsyncDialect"];
80}
81
82def AsyncRuntimePolicyBasedRefCounting
83    : Pass<"async-runtime-policy-based-ref-counting"> {
84  let summary = "Policy based reference counting for Async runtime operations";
85  let description = [{
86    This pass works at the async runtime abtraction level, after all
87    `async.execute` and `async.await` operations are lowered to the async
88    runtime API calls, and async coroutine operations.
89
90    This pass doesn't rely on reference counted values liveness analysis, and
91    instead uses simple policy to create reference counting operations. If the
92    program violates any of the assumptions, then this pass might lead to
93    memory leaks or runtime errors.
94
95    The default reference counting policy assumptions:
96      1. Async token can be awaited or added to the group only once.
97      2. Async value or group can be awaited only once.
98
99    Under these assumptions reference counting only needs to drop reference:
100      1. After `async.runtime.await` operation for async tokens and groups
101         (until error handling is not implemented for the sync await).
102      2. After `async.runtime.is_error` operation for async tokens and groups
103         (this is the last operation in the coroutine resume function).
104      3. After `async.runtime.load` operation for async values.
105
106    This pass introduces significanly less runtime overhead compared to the
107    automatic reference counting.
108  }];
109
110  let constructor = "mlir::createAsyncRuntimePolicyBasedRefCountingPass()";
111  let dependentDialects = ["async::AsyncDialect"];
112}
113
114#endif // MLIR_DIALECT_ASYNC_PASSES
115