111 lines
4.4 KiB
TableGen
111 lines
4.4 KiB
TableGen
//===-- Passes.td - Async pass definition file -------------*- tablegen -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_DIALECT_ASYNC_PASSES
|
|
#define MLIR_DIALECT_ASYNC_PASSES
|
|
|
|
include "mlir/Pass/PassBase.td"
|
|
|
|
def AsyncParallelForPass : Pass<"async-parallel-for", "ModuleOp"> {
|
|
let summary = "Convert scf.parallel operations to multiple async compute ops "
|
|
"executed concurrently for non-overlapping iteration ranges";
|
|
|
|
let options = [
|
|
Option<"asyncDispatch", "async-dispatch",
|
|
"bool", /*default=*/"true",
|
|
"Dispatch async compute tasks using recursive work splitting. If `false` "
|
|
"async compute tasks will be launched using simple for loop in the "
|
|
"caller thread.">,
|
|
|
|
Option<"numWorkerThreads", "num-workers",
|
|
"int32_t", /*default=*/"8",
|
|
"The number of available workers to execute async operations. If `-1` "
|
|
"the value will be retrieved from the runtime.">,
|
|
|
|
Option<"minTaskSize", "min-task-size",
|
|
"int32_t", /*default=*/"1000",
|
|
"The minimum task size for sharding parallel operation.">
|
|
];
|
|
|
|
let dependentDialects = [
|
|
"arith::ArithDialect",
|
|
"async::AsyncDialect",
|
|
"func::FuncDialect",
|
|
"scf::SCFDialect"
|
|
];
|
|
}
|
|
|
|
def AsyncToAsyncRuntimePass : Pass<"async-to-async-runtime", "ModuleOp"> {
|
|
let summary = "Lower all high level async operations (e.g. async.execute) to"
|
|
"the explicit async.runtime and async.coro operations";
|
|
let dependentDialects = ["async::AsyncDialect", "func::FuncDialect", "cf::ControlFlowDialect"];
|
|
}
|
|
|
|
def AsyncFuncToAsyncRuntimePass
|
|
: Pass<"async-func-to-async-runtime", "ModuleOp"> {
|
|
let summary = "Lower async.func operations to the explicit async.runtime and"
|
|
"async.coro operations";
|
|
let dependentDialects = ["async::AsyncDialect", "func::FuncDialect"];
|
|
}
|
|
|
|
def AsyncRuntimeRefCountingPass : Pass<"async-runtime-ref-counting"> {
|
|
let summary = "Automatic reference counting for Async runtime operations";
|
|
let description = [{
|
|
This pass works at the async runtime abtraction level, after all
|
|
`async.execute` and `async.await` operations are lowered to the async
|
|
runtime API calls, and async coroutine operations.
|
|
|
|
It relies on the LLVM coroutines switched-resume lowering semantics for
|
|
the correct placing of the reference counting operations.
|
|
|
|
See: https://llvm.org/docs/Coroutines.html#switched-resume-lowering
|
|
}];
|
|
|
|
let dependentDialects = ["async::AsyncDialect"];
|
|
}
|
|
|
|
def AsyncRuntimeRefCountingOptPass : Pass<"async-runtime-ref-counting-opt"> {
|
|
let summary = "Optimize automatic reference counting operations for the"
|
|
"Async runtime by removing redundant operations";
|
|
|
|
let dependentDialects = ["async::AsyncDialect"];
|
|
}
|
|
|
|
def AsyncRuntimePolicyBasedRefCountingPass
|
|
: Pass<"async-runtime-policy-based-ref-counting"> {
|
|
let summary = "Policy based reference counting for Async runtime operations";
|
|
let description = [{
|
|
This pass works at the async runtime abtraction level, after all
|
|
`async.execute` and `async.await` operations are lowered to the async
|
|
runtime API calls, and async coroutine operations.
|
|
|
|
This pass doesn't rely on reference counted values liveness analysis, and
|
|
instead uses simple policy to create reference counting operations. If the
|
|
program violates any of the assumptions, then this pass might lead to
|
|
memory leaks or runtime errors.
|
|
|
|
The default reference counting policy assumptions:
|
|
1. Async token can be awaited or added to the group only once.
|
|
2. Async value or group can be awaited only once.
|
|
|
|
Under these assumptions reference counting only needs to drop reference:
|
|
1. After `async.runtime.await` operation for async tokens and groups
|
|
(until error handling is not implemented for the sync await).
|
|
2. After `async.runtime.is_error` operation for async tokens and groups
|
|
(this is the last operation in the coroutine resume function).
|
|
3. After `async.runtime.load` operation for async values.
|
|
|
|
This pass introduces significanly less runtime overhead compared to the
|
|
automatic reference counting.
|
|
}];
|
|
|
|
let dependentDialects = ["async::AsyncDialect"];
|
|
}
|
|
|
|
#endif // MLIR_DIALECT_ASYNC_PASSES
|