[llvm-branch-commits] [mlir] a2223b0 - [mlir:async] Fix data races in AsyncRuntime
Author: Eugene Zhulenev Date: 2021-01-20T13:23:39-08:00 New Revision: a2223b09b10a4cc87b5e9c4a36ab9401c46610f6 URL: https://github.com/llvm/llvm-project/commit/a2223b09b10a4cc87b5e9c4a36ab9401c46610f6 DIFF: https://github.com/llvm/llvm-project/commit/a2223b09b10a4cc87b5e9c4a36ab9401c46610f6.diff LOG: [mlir:async] Fix data races in AsyncRuntime Resumed coroutine potentially can deallocate the token/value/group and destroy the mutex before the std::unique_ptr destructor. Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D95037 Added: Modified: mlir/lib/ExecutionEngine/AsyncRuntime.cpp Removed: diff --git a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp index a20bd6d1e996..e38ebf92cd84 100644 --- a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp +++ b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp @@ -136,13 +136,14 @@ struct AsyncToken : public RefCounted { // asynchronously executed task. If the caller immediately will drop its // reference we must ensure that the token will be alive until the // asynchronous operation is completed. - AsyncToken(AsyncRuntime *runtime) : RefCounted(runtime, /*count=*/2) {} + AsyncToken(AsyncRuntime *runtime) + : RefCounted(runtime, /*count=*/2), ready(false) {} - // Internal state below guarded by a mutex. + std::atomic ready; + + // Pending awaiters are guarded by a mutex. std::mutex mu; std::condition_variable cv; - - bool ready = false; std::vector> awaiters; }; @@ -152,17 +153,17 @@ struct AsyncToken : public RefCounted { struct AsyncValue : public RefCounted { // AsyncValue similar to an AsyncToken created with a reference count of 2. AsyncValue(AsyncRuntime *runtime, int32_t size) - : RefCounted(runtime, /*count=*/2), storage(size) {} - - // Internal state below guarded by a mutex. - std::mutex mu; - std::condition_variable cv; + : RefCounted(runtime, /*count=*/2), ready(false), storage(size) {} - bool ready = false; - std::vector> awaiters; + std::atomic ready; // Use vector of bytes to store async value payload. std::vector storage; + + // Pending awaiters are guarded by a mutex. + std::mutex mu; + std::condition_variable cv; + std::vector> awaiters; }; // Async group provides a mechanism to group together multiple async tokens or @@ -175,10 +176,9 @@ struct AsyncGroup : public RefCounted { std::atomic pendingTokens; std::atomic rank; - // Internal state below guarded by a mutex. + // Pending awaiters are guarded by a mutex. std::mutex mu; std::condition_variable cv; - std::vector> awaiters; }; @@ -291,13 +291,13 @@ extern "C" void mlirAsyncRuntimeEmplaceValue(AsyncValue *value) { extern "C" void mlirAsyncRuntimeAwaitToken(AsyncToken *token) { std::unique_lock lock(token->mu); if (!token->ready) -token->cv.wait(lock, [token] { return token->ready; }); +token->cv.wait(lock, [token] { return token->ready.load(); }); } extern "C" void mlirAsyncRuntimeAwaitValue(AsyncValue *value) { std::unique_lock lock(value->mu); if (!value->ready) -value->cv.wait(lock, [value] { return value->ready; }); +value->cv.wait(lock, [value] { return value->ready.load(); }); } extern "C" void mlirAsyncRuntimeAwaitAllInGroup(AsyncGroup *group) { @@ -319,34 +319,37 @@ extern "C" void mlirAsyncRuntimeExecute(CoroHandle handle, CoroResume resume) { extern "C" void mlirAsyncRuntimeAwaitTokenAndExecute(AsyncToken *token, CoroHandle handle, CoroResume resume) { - std::unique_lock lock(token->mu); auto execute = [handle, resume]() { (*resume)(handle); }; - if (token->ready) + if (token->ready) { execute(); - else + } else { +std::unique_lock lock(token->mu); token->awaiters.push_back([execute]() { execute(); }); + } } extern "C" void mlirAsyncRuntimeAwaitValueAndExecute(AsyncValue *value, CoroHandle handle, CoroResume resume) { - std::unique_lock lock(value->mu); auto execute = [handle, resume]() { (*resume)(handle); }; - if (value->ready) + if (value->ready) { execute(); - else + } else { +std::unique_lock lock(value->mu); value->awaiters.push_back([execute]() { execute(); }); + } } extern "C" void mlirAsyncRuntimeAwaitAllInGroupAndExecute(AsyncGroup *group, CoroHandle handle, CoroResume resume) { - std::unique_lock lock(group->mu); auto execute = [handle, resume]() { (*resume)(handle); }; - if (group->pendingTokens == 0) + if (group->pendingTokens == 0) { execute(); - else + } else { +std::unique_lock loc
[llvm-branch-commits] [mlir] cc77a2c - [mlir] Add coro intrinsics operations to LLVM dialect
Author: Eugene Zhulenev Date: 2021-01-22T10:01:45-08:00 New Revision: cc77a2c7685a9c82566332ba9bd070473ef679d4 URL: https://github.com/llvm/llvm-project/commit/cc77a2c7685a9c82566332ba9bd070473ef679d4 DIFF: https://github.com/llvm/llvm-project/commit/cc77a2c7685a9c82566332ba9bd070473ef679d4.diff LOG: [mlir] Add coro intrinsics operations to LLVM dialect This PR only has coro intrinsics needed for the Async to LLVM lowering. Will add other intrinsics as needed in the followup PRs. Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D95143 Added: Modified: mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td mlir/test/Target/llvmir-intrinsics.mlir Removed: diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td index 0ef223c4b023..21984ae2914c 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -52,6 +52,12 @@ def LLVM_Type : DialectType, "LLVM dialect-compatible type">; +// Type constraint accepting LLVM token type. +def LLVM_TokenType : Type< + CPred<"$_self.isa<::mlir::LLVM::LLVMTokenType>()">, + "LLVM token type">, + BuildableType<"::mlir::LLVM::LLVMTokenType::get($_builder.getContext())">; + // Type constraint accepting LLVM integer types. def LLVM_AnyInteger : Type< CPred<"$_self.isa<::mlir::IntegerType>()">, @@ -99,6 +105,16 @@ class LLVM_PointerTo : Type< pointee.predicate>]>, "LLVM pointer to " # pointee.summary>; +// Type constraints accepting LLVM pointer type to integer of a specific width. +class LLVM_IntPtrBase : Type< + LLVM_PointerTo>.predicate, + "LLVM pointer to " # LLVM_IntBase.summary>, + BuildableType<"::mlir::LLVM::LLVMPointerType::get(" +"::mlir::IntegerType::get($_builder.getContext(), " +# width #"))">; + +def LLVM_i8Ptr : LLVM_IntPtrBase<8>; + // Type constraint accepting any LLVM structure type. def LLVM_AnyStruct : Type()">, "LLVM structure type">; diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index cb2eede3040e..908080ace058 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -1226,6 +1226,57 @@ def LLVM_UMulWithOverflowOp let arguments = (ins LLVM_Type, LLVM_Type); } +// +// Coroutine intrinsics. +// + +def LLVM_CoroIdOp : LLVM_IntrOp<"coro.id", [], [], [], 1> { + let arguments = (ins LLVM_i32:$align, + LLVM_i8Ptr:$promise, + LLVM_i8Ptr:$coroaddr, + LLVM_i8Ptr:$fnaddrs); + let assemblyFormat = "$align `,` $promise `,` $coroaddr `,` $fnaddrs" +" attr-dict `:` type($res)"; +} + +def LLVM_CoroBeginOp : LLVM_IntrOp<"coro.begin", [], [], [], 1> { + let arguments = (ins LLVM_TokenType:$token, + LLVM_i8Ptr:$mem); + let assemblyFormat = "$token `,` $mem attr-dict `:` type($res)"; +} + +def LLVM_CoroSizeOp : LLVM_IntrOp<"coro.size", [0], [], [], 1> { + let assemblyFormat = "attr-dict `:` type($res)"; +} + +def LLVM_CoroSaveOp : LLVM_IntrOp<"coro.save", [], [], [], 1> { + let arguments = (ins LLVM_i8Ptr:$handle); + let assemblyFormat = "$handle attr-dict `:` type($res)"; +} + +def LLVM_CoroSuspendOp : LLVM_IntrOp<"coro.suspend", [], [], [], 1> { + let arguments = (ins LLVM_TokenType:$save, + LLVM_i1:$final); + let assemblyFormat = "$save `,` $final attr-dict `:` type($res)"; +} + +def LLVM_CoroEndOp : LLVM_IntrOp<"coro.end", [], [], [], 1> { + let arguments = (ins LLVM_i8Ptr:$handle, + LLVM_i1:$unwind); + let assemblyFormat = "$handle `,` $unwind attr-dict `:` type($res)"; +} + +def LLVM_CoroFreeOp : LLVM_IntrOp<"coro.free", [], [], [], 1> { + let arguments = (ins LLVM_TokenType:$id, + LLVM_i8Ptr:$handle); + let assemblyFormat = "$id `,` $handle attr-dict `:` type($res)"; +} + +def LLVM_CoroResumeOp : LLVM_IntrOp<"coro.resume", [], [], [], 0> { + let arguments = (ins LLVM_i8Ptr:$handle); + let assemblyFormat = "$handle attr-dict"; +} + // // Vector Reductions. // diff --git a/mlir/test/Target/llvmir-intrinsics.mlir b/mlir/test/Target/llvmir-intrinsics.mlir index d218e35e774d..bbffb8965a3a 100644 --- a/mlir/test/Target/llvmir-intrinsics.mlir +++ b/mlir/test/Target/llvmir-intrinsics.mlir @@ -347,6 +347,64 @@ llvm.func @umul_with_overflow_test(%arg0: i32, %arg1: i32, %arg2: vector<8xi32>, llvm.return } +// CHECK-LABEL: @coro_id +llvm.func @coro_id(%arg0: i32, %arg1: !llvm.ptr) { + // CHECK: call token @llvm.coro.id + llvm.intr.coro.id %arg0, %arg1, %arg1, %arg1 : !llvm.token + llvm.return +} + +// CHECK-LABEL: @coro_begin +llvm.func @coro_begin(%arg0: !llvm.token, %arg1: !llvm.
[llvm-branch-commits] [mlir] 84dc9b4 - [mlir:JitRunner] Use custom shared library init/destroy functions if available
Author: Eugene Zhulenev Date: 2021-01-08T07:14:21-08:00 New Revision: 84dc9b451bfd62474f44dd1af0e4955a0110d523 URL: https://github.com/llvm/llvm-project/commit/84dc9b451bfd62474f44dd1af0e4955a0110d523 DIFF: https://github.com/llvm/llvm-project/commit/84dc9b451bfd62474f44dd1af0e4955a0110d523.diff LOG: [mlir:JitRunner] Use custom shared library init/destroy functions if available Use custom mlir runner init/destroy functions to safely init and destroy shared libraries loaded by the JitRunner. Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D94270 Added: Modified: mlir/lib/ExecutionEngine/AsyncRuntime.cpp mlir/lib/ExecutionEngine/CMakeLists.txt mlir/lib/ExecutionEngine/JitRunner.cpp Removed: diff --git a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp index 45bdcb3733b8..080be9ca029a 100644 --- a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp +++ b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp @@ -24,6 +24,8 @@ #include #include +#include "llvm/ADT/StringMap.h" + using namespace mlir::runtime; //===--===// @@ -109,9 +111,17 @@ class RefCounted { } // namespace // Returns the default per-process instance of an async runtime. -static AsyncRuntime *getDefaultAsyncRuntimeInstance() { +static std::unique_ptr &getDefaultAsyncRuntimeInstance() { static auto runtime = std::make_unique(); - return runtime.get(); + return runtime; +} + +static void resetDefaultAsyncRuntime() { + return getDefaultAsyncRuntimeInstance().reset(); +} + +static AsyncRuntime *getDefaultAsyncRuntime() { + return getDefaultAsyncRuntimeInstance().get(); } // Async token provides a mechanism to signal asynchronous operation completion. @@ -184,19 +194,19 @@ extern "C" void mlirAsyncRuntimeDropRef(RefCountedObjPtr ptr, int32_t count) { // Creates a new `async.token` in not-ready state. extern "C" AsyncToken *mlirAsyncRuntimeCreateToken() { - AsyncToken *token = new AsyncToken(getDefaultAsyncRuntimeInstance()); + AsyncToken *token = new AsyncToken(getDefaultAsyncRuntime()); return token; } // Creates a new `async.value` in not-ready state. extern "C" AsyncValue *mlirAsyncRuntimeCreateValue(int32_t size) { - AsyncValue *value = new AsyncValue(getDefaultAsyncRuntimeInstance(), size); + AsyncValue *value = new AsyncValue(getDefaultAsyncRuntime(), size); return value; } // Create a new `async.group` in empty state. extern "C" AsyncGroup *mlirAsyncRuntimeCreateGroup() { - AsyncGroup *group = new AsyncGroup(getDefaultAsyncRuntimeInstance()); + AsyncGroup *group = new AsyncGroup(getDefaultAsyncRuntime()); return group; } @@ -342,4 +352,55 @@ extern "C" void mlirAsyncRuntimePrintCurrentThreadId() { std::cout << "Current thread id: " << thisId << std::endl; } +//===--===// +// MLIR Runner (JitRunner) dynamic library integration. +//===--===// + +// Export symbols for the MLIR runner integration. All other symbols are hidden. +#define API __attribute__((visibility("default"))) + +extern "C" API void __mlir_runner_init(llvm::StringMap &exportSymbols) { + auto exportSymbol = [&](llvm::StringRef name, auto ptr) { +assert(exportSymbols.count(name) == 0 && "symbol already exists"); +exportSymbols[name] = reinterpret_cast(ptr); + }; + + exportSymbol("mlirAsyncRuntimeAddRef", + &mlir::runtime::mlirAsyncRuntimeAddRef); + exportSymbol("mlirAsyncRuntimeDropRef", + &mlir::runtime::mlirAsyncRuntimeDropRef); + exportSymbol("mlirAsyncRuntimeExecute", + &mlir::runtime::mlirAsyncRuntimeExecute); + exportSymbol("mlirAsyncRuntimeGetValueStorage", + &mlir::runtime::mlirAsyncRuntimeGetValueStorage); + exportSymbol("mlirAsyncRuntimeCreateToken", + &mlir::runtime::mlirAsyncRuntimeCreateToken); + exportSymbol("mlirAsyncRuntimeCreateValue", + &mlir::runtime::mlirAsyncRuntimeCreateValue); + exportSymbol("mlirAsyncRuntimeEmplaceToken", + &mlir::runtime::mlirAsyncRuntimeEmplaceToken); + exportSymbol("mlirAsyncRuntimeEmplaceValue", + &mlir::runtime::mlirAsyncRuntimeEmplaceValue); + exportSymbol("mlirAsyncRuntimeAwaitToken", + &mlir::runtime::mlirAsyncRuntimeAwaitToken); + exportSymbol("mlirAsyncRuntimeAwaitValue", + &mlir::runtime::mlirAsyncRuntimeAwaitValue); + exportSymbol("mlirAsyncRuntimeAwaitTokenAndExecute", + &mlir::runtime::mlirAsyncRuntimeAwaitTokenAndExecute); + exportSymbol("mlirAsyncRuntimeAwaitValueAndExecute", + &mlir::runtime::mlirAsyncRuntimeAwaitValueAndExecute); + exportSymbol("mlirAsyncRuntimeCreateGroup", + &mlir::runtime::
[llvm-branch-commits] [mlir] 740950c - Revert "[mlir:JitRunner] Use custom shared library init/destroy functions if available"
Author: Eugene Zhulenev Date: 2021-01-08T07:46:35-08:00 New Revision: 740950cf1cda4e5ccecf3781b7b64c9a9a72b168 URL: https://github.com/llvm/llvm-project/commit/740950cf1cda4e5ccecf3781b7b64c9a9a72b168 DIFF: https://github.com/llvm/llvm-project/commit/740950cf1cda4e5ccecf3781b7b64c9a9a72b168.diff LOG: Revert "[mlir:JitRunner] Use custom shared library init/destroy functions if available" This reverts commit 84dc9b451bfd62474f44dd1af0e4955a0110d523. Fix Windows breakage: http://lab.llvm.org:8011/#/builders/13/builds/3658/steps/6/logs/stdio Differential Revision: https://reviews.llvm.org/D94309 Added: Modified: mlir/lib/ExecutionEngine/AsyncRuntime.cpp mlir/lib/ExecutionEngine/CMakeLists.txt mlir/lib/ExecutionEngine/JitRunner.cpp Removed: diff --git a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp index 080be9ca029a..45bdcb3733b8 100644 --- a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp +++ b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp @@ -24,8 +24,6 @@ #include #include -#include "llvm/ADT/StringMap.h" - using namespace mlir::runtime; //===--===// @@ -111,17 +109,9 @@ class RefCounted { } // namespace // Returns the default per-process instance of an async runtime. -static std::unique_ptr &getDefaultAsyncRuntimeInstance() { +static AsyncRuntime *getDefaultAsyncRuntimeInstance() { static auto runtime = std::make_unique(); - return runtime; -} - -static void resetDefaultAsyncRuntime() { - return getDefaultAsyncRuntimeInstance().reset(); -} - -static AsyncRuntime *getDefaultAsyncRuntime() { - return getDefaultAsyncRuntimeInstance().get(); + return runtime.get(); } // Async token provides a mechanism to signal asynchronous operation completion. @@ -194,19 +184,19 @@ extern "C" void mlirAsyncRuntimeDropRef(RefCountedObjPtr ptr, int32_t count) { // Creates a new `async.token` in not-ready state. extern "C" AsyncToken *mlirAsyncRuntimeCreateToken() { - AsyncToken *token = new AsyncToken(getDefaultAsyncRuntime()); + AsyncToken *token = new AsyncToken(getDefaultAsyncRuntimeInstance()); return token; } // Creates a new `async.value` in not-ready state. extern "C" AsyncValue *mlirAsyncRuntimeCreateValue(int32_t size) { - AsyncValue *value = new AsyncValue(getDefaultAsyncRuntime(), size); + AsyncValue *value = new AsyncValue(getDefaultAsyncRuntimeInstance(), size); return value; } // Create a new `async.group` in empty state. extern "C" AsyncGroup *mlirAsyncRuntimeCreateGroup() { - AsyncGroup *group = new AsyncGroup(getDefaultAsyncRuntime()); + AsyncGroup *group = new AsyncGroup(getDefaultAsyncRuntimeInstance()); return group; } @@ -352,55 +342,4 @@ extern "C" void mlirAsyncRuntimePrintCurrentThreadId() { std::cout << "Current thread id: " << thisId << std::endl; } -//===--===// -// MLIR Runner (JitRunner) dynamic library integration. -//===--===// - -// Export symbols for the MLIR runner integration. All other symbols are hidden. -#define API __attribute__((visibility("default"))) - -extern "C" API void __mlir_runner_init(llvm::StringMap &exportSymbols) { - auto exportSymbol = [&](llvm::StringRef name, auto ptr) { -assert(exportSymbols.count(name) == 0 && "symbol already exists"); -exportSymbols[name] = reinterpret_cast(ptr); - }; - - exportSymbol("mlirAsyncRuntimeAddRef", - &mlir::runtime::mlirAsyncRuntimeAddRef); - exportSymbol("mlirAsyncRuntimeDropRef", - &mlir::runtime::mlirAsyncRuntimeDropRef); - exportSymbol("mlirAsyncRuntimeExecute", - &mlir::runtime::mlirAsyncRuntimeExecute); - exportSymbol("mlirAsyncRuntimeGetValueStorage", - &mlir::runtime::mlirAsyncRuntimeGetValueStorage); - exportSymbol("mlirAsyncRuntimeCreateToken", - &mlir::runtime::mlirAsyncRuntimeCreateToken); - exportSymbol("mlirAsyncRuntimeCreateValue", - &mlir::runtime::mlirAsyncRuntimeCreateValue); - exportSymbol("mlirAsyncRuntimeEmplaceToken", - &mlir::runtime::mlirAsyncRuntimeEmplaceToken); - exportSymbol("mlirAsyncRuntimeEmplaceValue", - &mlir::runtime::mlirAsyncRuntimeEmplaceValue); - exportSymbol("mlirAsyncRuntimeAwaitToken", - &mlir::runtime::mlirAsyncRuntimeAwaitToken); - exportSymbol("mlirAsyncRuntimeAwaitValue", - &mlir::runtime::mlirAsyncRuntimeAwaitValue); - exportSymbol("mlirAsyncRuntimeAwaitTokenAndExecute", - &mlir::runtime::mlirAsyncRuntimeAwaitTokenAndExecute); - exportSymbol("mlirAsyncRuntimeAwaitValueAndExecute", - &mlir::runtime::mlirAsyncRuntimeAwaitValueAndExecute); - exportSymbol("mlirAsyncRuntimeCreateGroup", -
[llvm-branch-commits] [mlir] 1fc9864 - [mlir:JitRunner] Use custom shared library init/destroy functions if available
Author: Eugene Zhulenev Date: 2021-01-08T13:16:08-08:00 New Revision: 1fc986427ba32384a03286472d3c04b37420ad73 URL: https://github.com/llvm/llvm-project/commit/1fc986427ba32384a03286472d3c04b37420ad73 DIFF: https://github.com/llvm/llvm-project/commit/1fc986427ba32384a03286472d3c04b37420ad73.diff LOG: [mlir:JitRunner] Use custom shared library init/destroy functions if available Use custom mlir runner init/destroy functions to safely init and destroy shared libraries loaded by the JitRunner. This mechanism is ignored for Windows builds (for now) because init/destroy functions are not exported, and library unloading relies on static destructors. Re-submit https://reviews.llvm.org/D94270 with a temporary workaround for windows Differential Revision: https://reviews.llvm.org/D94312 Added: Modified: mlir/lib/ExecutionEngine/AsyncRuntime.cpp mlir/lib/ExecutionEngine/CMakeLists.txt mlir/lib/ExecutionEngine/JitRunner.cpp Removed: diff --git a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp index 45bdcb3733b8..1fb6a843f015 100644 --- a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp +++ b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp @@ -24,6 +24,8 @@ #include #include +#include "llvm/ADT/StringMap.h" + using namespace mlir::runtime; //===--===// @@ -109,9 +111,17 @@ class RefCounted { } // namespace // Returns the default per-process instance of an async runtime. -static AsyncRuntime *getDefaultAsyncRuntimeInstance() { +static std::unique_ptr &getDefaultAsyncRuntimeInstance() { static auto runtime = std::make_unique(); - return runtime.get(); + return runtime; +} + +static void resetDefaultAsyncRuntime() { + return getDefaultAsyncRuntimeInstance().reset(); +} + +static AsyncRuntime *getDefaultAsyncRuntime() { + return getDefaultAsyncRuntimeInstance().get(); } // Async token provides a mechanism to signal asynchronous operation completion. @@ -184,19 +194,19 @@ extern "C" void mlirAsyncRuntimeDropRef(RefCountedObjPtr ptr, int32_t count) { // Creates a new `async.token` in not-ready state. extern "C" AsyncToken *mlirAsyncRuntimeCreateToken() { - AsyncToken *token = new AsyncToken(getDefaultAsyncRuntimeInstance()); + AsyncToken *token = new AsyncToken(getDefaultAsyncRuntime()); return token; } // Creates a new `async.value` in not-ready state. extern "C" AsyncValue *mlirAsyncRuntimeCreateValue(int32_t size) { - AsyncValue *value = new AsyncValue(getDefaultAsyncRuntimeInstance(), size); + AsyncValue *value = new AsyncValue(getDefaultAsyncRuntime(), size); return value; } // Create a new `async.group` in empty state. extern "C" AsyncGroup *mlirAsyncRuntimeCreateGroup() { - AsyncGroup *group = new AsyncGroup(getDefaultAsyncRuntimeInstance()); + AsyncGroup *group = new AsyncGroup(getDefaultAsyncRuntime()); return group; } @@ -342,4 +352,59 @@ extern "C" void mlirAsyncRuntimePrintCurrentThreadId() { std::cout << "Current thread id: " << thisId << std::endl; } +//===--===// +// MLIR Runner (JitRunner) dynamic library integration. +//===--===// + +// Export symbols for the MLIR runner integration. All other symbols are hidden. +#ifndef _WIN32 +#define API __attribute__((visibility("default"))) +#else +#define API +#endif // _WIN32 + +extern "C" API void __mlir_runner_init(llvm::StringMap &exportSymbols) { + auto exportSymbol = [&](llvm::StringRef name, auto ptr) { +assert(exportSymbols.count(name) == 0 && "symbol already exists"); +exportSymbols[name] = reinterpret_cast(ptr); + }; + + exportSymbol("mlirAsyncRuntimeAddRef", + &mlir::runtime::mlirAsyncRuntimeAddRef); + exportSymbol("mlirAsyncRuntimeDropRef", + &mlir::runtime::mlirAsyncRuntimeDropRef); + exportSymbol("mlirAsyncRuntimeExecute", + &mlir::runtime::mlirAsyncRuntimeExecute); + exportSymbol("mlirAsyncRuntimeGetValueStorage", + &mlir::runtime::mlirAsyncRuntimeGetValueStorage); + exportSymbol("mlirAsyncRuntimeCreateToken", + &mlir::runtime::mlirAsyncRuntimeCreateToken); + exportSymbol("mlirAsyncRuntimeCreateValue", + &mlir::runtime::mlirAsyncRuntimeCreateValue); + exportSymbol("mlirAsyncRuntimeEmplaceToken", + &mlir::runtime::mlirAsyncRuntimeEmplaceToken); + exportSymbol("mlirAsyncRuntimeEmplaceValue", + &mlir::runtime::mlirAsyncRuntimeEmplaceValue); + exportSymbol("mlirAsyncRuntimeAwaitToken", + &mlir::runtime::mlirAsyncRuntimeAwaitToken); + exportSymbol("mlirAsyncRuntimeAwaitValue", + &mlir::runtime::mlirAsyncRuntimeAwaitValue); + exportSymbol("mlirAsyncRuntimeAwaitTokenAndExecute", +
[llvm-branch-commits] [mlir] 78b3bce - [mlir] AsyncRuntime: disable mlir-runner init/disable for WIN32
Author: Eugene Zhulenev Date: 2021-01-08T14:03:25-08:00 New Revision: 78b3bce23b113ab5dbd33d746ba48f2a3c20c5ff URL: https://github.com/llvm/llvm-project/commit/78b3bce23b113ab5dbd33d746ba48f2a3c20c5ff DIFF: https://github.com/llvm/llvm-project/commit/78b3bce23b113ab5dbd33d746ba48f2a3c20c5ff.diff LOG: [mlir] AsyncRuntime: disable mlir-runner init/disable for WIN32 Differential Revision: https://reviews.llvm.org/D94339 Added: Modified: mlir/lib/ExecutionEngine/AsyncRuntime.cpp Removed: diff --git a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp index 1fb6a843f015..1e0c35afebd8 100644 --- a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp +++ b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp @@ -359,9 +359,6 @@ extern "C" void mlirAsyncRuntimePrintCurrentThreadId() { // Export symbols for the MLIR runner integration. All other symbols are hidden. #ifndef _WIN32 #define API __attribute__((visibility("default"))) -#else -#define API -#endif // _WIN32 extern "C" API void __mlir_runner_init(llvm::StringMap &exportSymbols) { auto exportSymbol = [&](llvm::StringRef name, auto ptr) { @@ -407,4 +404,6 @@ extern "C" API void __mlir_runner_init(llvm::StringMap &exportSymbols) { extern "C" API void __mlir_runner_destroy() { resetDefaultAsyncRuntime(); } +#endif // _WIN32 + #endif // MLIR_ASYNCRUNTIME_DEFINE_FUNCTIONS ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] bb0e621 - [mlir] AsyncRuntime: use LLVM ThreadPool to run async tasks
Author: Eugene Zhulenev Date: 2021-01-09T02:39:52-08:00 New Revision: bb0e621387f86c1e40b39fcfd9127d4d18294748 URL: https://github.com/llvm/llvm-project/commit/bb0e621387f86c1e40b39fcfd9127d4d18294748 DIFF: https://github.com/llvm/llvm-project/commit/bb0e621387f86c1e40b39fcfd9127d4d18294748.diff LOG: [mlir] AsyncRuntime: use LLVM ThreadPool to run async tasks Revert https://reviews.llvm.org/D92368 after the dynamic library unloading was fixed in https://reviews.llvm.org/D94312 Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D94346 Added: Modified: mlir/lib/ExecutionEngine/AsyncRuntime.cpp Removed: diff --git a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp index 1e0c35afebd8..a20bd6d1e996 100644 --- a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp +++ b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp @@ -25,6 +25,7 @@ #include #include "llvm/ADT/StringMap.h" +#include "llvm/Support/ThreadPool.h" using namespace mlir::runtime; @@ -49,6 +50,7 @@ class AsyncRuntime { AsyncRuntime() : numRefCountedObjects(0) {} ~AsyncRuntime() { +threadPool.wait(); // wait for the completion of all async tasks assert(getNumRefCountedObjects() == 0 && "all ref counted objects must be destroyed"); } @@ -57,6 +59,8 @@ class AsyncRuntime { return numRefCountedObjects.load(std::memory_order_relaxed); } + llvm::ThreadPool &getThreadPool() { return threadPool; } + private: friend class RefCounted; @@ -70,6 +74,7 @@ class AsyncRuntime { } std::atomic numRefCountedObjects; + llvm::ThreadPool threadPool; }; // -- // @@ -307,7 +312,8 @@ extern "C" ValueStorage mlirAsyncRuntimeGetValueStorage(AsyncValue *value) { } extern "C" void mlirAsyncRuntimeExecute(CoroHandle handle, CoroResume resume) { - (*resume)(handle); + auto *runtime = getDefaultAsyncRuntime(); + runtime->getThreadPool().async([handle, resume]() { (*resume)(handle); }); } extern "C" void mlirAsyncRuntimeAwaitTokenAndExecute(AsyncToken *token, ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 0b510e7 - [mlir] Fix opaque struct typedef in AsyncRuntime header
Author: Eugene Zhulenev Date: 2020-12-14T15:04:59-08:00 New Revision: 0b510e79ce341af6a0ad951d52d516b833d5cefd URL: https://github.com/llvm/llvm-project/commit/0b510e79ce341af6a0ad951d52d516b833d5cefd DIFF: https://github.com/llvm/llvm-project/commit/0b510e79ce341af6a0ad951d52d516b833d5cefd.diff LOG: [mlir] Fix opaque struct typedef in AsyncRuntime header Differential Revision: https://reviews.llvm.org/D93250 Added: Modified: mlir/include/mlir/ExecutionEngine/AsyncRuntime.h Removed: diff --git a/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h b/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h index 26b0a236f0d3..54724af4133d 100644 --- a/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h +++ b/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h @@ -37,10 +37,10 @@ //===--===// // Runtime implementation of `async.token` data type. -typedef struct AsyncToken MLIR_AsyncToken; +typedef struct AsyncToken AsyncToken; // Runtime implementation of `async.group` data type. -typedef struct AsyncGroup MLIR_AsyncGroup; +typedef struct AsyncGroup AsyncGroup; // Async runtime uses LLVM coroutines to represent asynchronous tasks. Task // function is a coroutine handle and a resume function that continue coroutine ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 11f1027 - [mlir] AsyncRuntime: mode runtime declarations to mlir::runtime namespace
Author: Eugene Zhulenev Date: 2020-12-16T11:05:21-08:00 New Revision: 11f1027b4d8d851c94497330bb901bd5753188f3 URL: https://github.com/llvm/llvm-project/commit/11f1027b4d8d851c94497330bb901bd5753188f3 DIFF: https://github.com/llvm/llvm-project/commit/11f1027b4d8d851c94497330bb901bd5753188f3.diff LOG: [mlir] AsyncRuntime: mode runtime declarations to mlir::runtime namespace Define Async runtime related typedefs in the `mlir::runtime` namespace. Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D93391 Added: Modified: mlir/include/mlir/ExecutionEngine/AsyncRuntime.h mlir/lib/ExecutionEngine/AsyncRuntime.cpp Removed: diff --git a/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h b/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h index 54724af4133d..e3d90198f36c 100644 --- a/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h +++ b/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h @@ -32,6 +32,9 @@ #define MLIR_ASYNCRUNTIME_DEFINE_FUNCTIONS #endif // _WIN32 +namespace mlir { +namespace runtime { + //===--===// // Async runtime API. //===--===// @@ -102,4 +105,7 @@ mlirAsyncRuntimeAwaitAllInGroupAndExecute(AsyncGroup *, CoroHandle, CoroResume); extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimePrintCurrentThreadId(); +} // namespace runtime +} // namespace mlir + #endif // MLIR_EXECUTIONENGINE_ASYNCRUNTIME_H_ diff --git a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp index 3b90b9c694f3..3bfed86aa996 100644 --- a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp +++ b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp @@ -24,10 +24,14 @@ #include #include +using namespace mlir::runtime; + //===--===// // Async runtime API. //===--===// +namespace mlir { +namespace runtime { namespace { // Forward declare class defined below. @@ -66,12 +70,6 @@ class AsyncRuntime { std::atomic numRefCountedObjects; }; -// Returns the default per-process instance of an async runtime. -AsyncRuntime *getDefaultAsyncRuntimeInstance() { - static auto runtime = std::make_unique(); - return runtime.get(); -} - // -- // // A base class for all reference counted objects created by the async runtime. // -- // @@ -110,6 +108,12 @@ class RefCounted { } // namespace +// Returns the default per-process instance of an async runtime. +static AsyncRuntime *getDefaultAsyncRuntimeInstance() { + static auto runtime = std::make_unique(); + return runtime.get(); +} + struct AsyncToken : public RefCounted { // AsyncToken created with a reference count of 2 because it will be returned // to the `async.execute` caller and also will be later on emplaced by the @@ -140,6 +144,9 @@ struct AsyncGroup : public RefCounted { std::vector> awaiters; }; +} // namespace runtime +} // namespace mlir + // Adds references to reference counted runtime object. extern "C" void mlirAsyncRuntimeAddRef(RefCountedObjPtr ptr, int32_t count) { RefCounted *refCounted = static_cast(ptr); ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 900d71a - [mlir] Async: re-enable tests after fixing fkakines
Author: Eugene Zhulenev Date: 2020-12-16T11:07:03-08:00 New Revision: 900d71a851db5d50a52906c0146451b4b71cd85f URL: https://github.com/llvm/llvm-project/commit/900d71a851db5d50a52906c0146451b4b71cd85f DIFF: https://github.com/llvm/llvm-project/commit/900d71a851db5d50a52906c0146451b4b71cd85f.diff LOG: [mlir] Async: re-enable tests after fixing fkakines Test flakiness was fixed by: https://github.com/llvm/llvm-project/commit/9edcedf7f222ce7c893d1e3bf19b3a7a1f0f2218 Runs these tests to verify that all parts of the lowering work correctly. Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D93384 Added: Modified: mlir/test/mlir-cpu-runner/async-group.mlir mlir/test/mlir-cpu-runner/async.mlir Removed: diff --git a/mlir/test/mlir-cpu-runner/async-group.mlir b/mlir/test/mlir-cpu-runner/async-group.mlir index e7a07dc4f1ab..50f85ff54609 100644 --- a/mlir/test/mlir-cpu-runner/async-group.mlir +++ b/mlir/test/mlir-cpu-runner/async-group.mlir @@ -1,14 +1,12 @@ -// RUN: true -// TODO: re-enable when not flaky. -// _UN: mlir-opt %s -async-ref-counting \ -// _UN: -convert-async-to-llvm \ -// _UN: -convert-std-to-llvm \ -// _UN: | mlir-cpu-runner \ -// _UN: -e main -entry-point-result=void -O0 \ -// _UN: -shared-libs=%linalg_test_lib_dir/libmlir_c_runner_utils%shlibext \ -// _UN: -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext \ -// _UN: -shared-libs=%linalg_test_lib_dir/libmlir_async_runtime%shlibext \ -// _UN: | FileCheck %s +// RUN: mlir-opt %s -async-ref-counting \ +// RUN: -convert-async-to-llvm \ +// RUN: -convert-std-to-llvm \ +// RUN: | mlir-cpu-runner \ +// RUN: -e main -entry-point-result=void -O0 \ +// RUN: -shared-libs=%linalg_test_lib_dir/libmlir_c_runner_utils%shlibext \ +// RUN: -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext \ +// RUN: -shared-libs=%linalg_test_lib_dir/libmlir_async_runtime%shlibext \ +// RUN: | FileCheck %s func @main() { %group = async.create_group diff --git a/mlir/test/mlir-cpu-runner/async.mlir b/mlir/test/mlir-cpu-runner/async.mlir index 4546628e5969..5f06dd17ed61 100644 --- a/mlir/test/mlir-cpu-runner/async.mlir +++ b/mlir/test/mlir-cpu-runner/async.mlir @@ -1,16 +1,14 @@ -// RUN: true -// TODO: re-enable when not flaky. -// _UN: mlir-opt %s -async-ref-counting \ -// _UN: -convert-async-to-llvm \ -// _UN: -convert-linalg-to-loops \ -// _UN: -convert-linalg-to-llvm \ -// _UN: -convert-std-to-llvm \ -// _UN: | mlir-cpu-runner \ -// _UN: -e main -entry-point-result=void -O0 \ -// _UN: -shared-libs=%linalg_test_lib_dir/libmlir_c_runner_utils%shlibext \ -// _UN: -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext \ -// _UN: -shared-libs=%linalg_test_lib_dir/libmlir_async_runtime%shlibext \ -// _UN: | FileCheck %s +// RUN: mlir-opt %s -async-ref-counting \ +// RUN: -convert-async-to-llvm \ +// RUN: -convert-linalg-to-loops \ +// RUN: -convert-linalg-to-llvm \ +// RUN: -convert-std-to-llvm \ +// RUN: | mlir-cpu-runner \ +// RUN: -e main -entry-point-result=void -O0 \ +// RUN: -shared-libs=%linalg_test_lib_dir/libmlir_c_runner_utils%shlibext \ +// RUN: -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext \ +// RUN: -shared-libs=%linalg_test_lib_dir/libmlir_async_runtime%shlibext \ +// RUN: | FileCheck %s func @main() { %i0 = constant 0 : index ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 621ad46 - [mlir] Async: lowering async.value to LLVM
Author: Eugene Zhulenev Date: 2020-12-25T02:23:48-08:00 New Revision: 621ad468d99d4013a4298465f02707a5e9e89cae URL: https://github.com/llvm/llvm-project/commit/621ad468d99d4013a4298465f02707a5e9e89cae DIFF: https://github.com/llvm/llvm-project/commit/621ad468d99d4013a4298465f02707a5e9e89cae.diff LOG: [mlir] Async: lowering async.value to LLVM 1. Add new methods to Async runtime API to support yielding async values 2. Add lowering from `async.yield` with value payload to the new runtime API calls `async.value` lowering requires that payload type is convertible to LLVM and supported by `llvm.mlir.cast` (DialectCast) operation. Reviewed By: csigg Differential Revision: https://reviews.llvm.org/D93592 Added: mlir/test/mlir-cpu-runner/async-value.mlir Modified: mlir/include/mlir/ExecutionEngine/AsyncRuntime.h mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp mlir/lib/Conversion/AsyncToLLVM/CMakeLists.txt mlir/lib/ExecutionEngine/AsyncRuntime.cpp mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir Removed: diff --git a/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h b/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h index e3d90198f36c..0fe44cd1c127 100644 --- a/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h +++ b/mlir/include/mlir/ExecutionEngine/AsyncRuntime.h @@ -45,6 +45,12 @@ typedef struct AsyncToken AsyncToken; // Runtime implementation of `async.group` data type. typedef struct AsyncGroup AsyncGroup; +// Runtime implementation of `async.value` data type. +typedef struct AsyncValue AsyncValue; + +// Async value payload stored in a memory owned by the async.value. +using ValueStorage = void *; + // Async runtime uses LLVM coroutines to represent asynchronous tasks. Task // function is a coroutine handle and a resume function that continue coroutine // execution from a suspension point. @@ -66,6 +72,13 @@ extern "C" MLIR_ASYNCRUNTIME_EXPORT void // Create a new `async.token` in not-ready state. extern "C" MLIR_ASYNCRUNTIME_EXPORT AsyncToken *mlirAsyncRuntimeCreateToken(); +// Create a new `async.value` in not-ready state. Size parameter specifies the +// number of bytes that will be allocated for the async value storage. Storage +// is owned by the `async.value` and deallocated when the async value is +// destructed (reference count drops to zero). +extern "C" MLIR_ASYNCRUNTIME_EXPORT AsyncValue * +mlirAsyncRuntimeCreateValue(int32_t); + // Create a new `async.group` in empty state. extern "C" MLIR_ASYNCRUNTIME_EXPORT AsyncGroup *mlirAsyncRuntimeCreateGroup(); @@ -76,14 +89,26 @@ mlirAsyncRuntimeAddTokenToGroup(AsyncToken *, AsyncGroup *); extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeEmplaceToken(AsyncToken *); +// Switches `async.value` to ready state and runs all awaiters. +extern "C" MLIR_ASYNCRUNTIME_EXPORT void +mlirAsyncRuntimeEmplaceValue(AsyncValue *); + // Blocks the caller thread until the token becomes ready. extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeAwaitToken(AsyncToken *); +// Blocks the caller thread until the value becomes ready. +extern "C" MLIR_ASYNCRUNTIME_EXPORT void +mlirAsyncRuntimeAwaitValue(AsyncValue *); + // Blocks the caller thread until the elements in the group become ready. extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeAwaitAllInGroup(AsyncGroup *); +// Returns a pointer to the storage owned by the async value. +extern "C" MLIR_ASYNCRUNTIME_EXPORT ValueStorage +mlirAsyncRuntimeGetValueStorage(AsyncValue *); + // Executes the task (coro handle + resume function) in one of the threads // managed by the runtime. extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeExecute(CoroHandle, @@ -94,6 +119,11 @@ extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeExecute(CoroHandle, extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeAwaitTokenAndExecute(AsyncToken *, CoroHandle, CoroResume); +// Executes the task (coro handle + resume function) in one of the threads +// managed by the runtime after the value becomes ready. +extern "C" MLIR_ASYNCRUNTIME_EXPORT void +mlirAsyncRuntimeAwaitValueAndExecute(AsyncValue *, CoroHandle, CoroResume); + // Executes the task (coro handle + resume function) in one of the threads // managed by the runtime after the all members of the group become ready. extern "C" MLIR_ASYNCRUNTIME_EXPORT void diff --git a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp index 3daa70b0a952..f1d6264606be 100644 --- a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp +++ b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp @@ -9,9 +9,11 @@ #include "mlir/Conversion/AsyncToLLVM/AsyncToLLVM.h" #include "../PassDetail.h" +#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h" #include "mlir/Dialect/Async/IR/Async.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/Sta
[llvm-branch-commits] [mlir] 61422c8 - [mlir] Async: add support for lowering async value operands to LLVM
Author: Eugene Zhulenev Date: 2020-12-25T02:25:20-08:00 New Revision: 61422c8b661c506b25b5ac705cdbb2265af120d1 URL: https://github.com/llvm/llvm-project/commit/61422c8b661c506b25b5ac705cdbb2265af120d1 DIFF: https://github.com/llvm/llvm-project/commit/61422c8b661c506b25b5ac705cdbb2265af120d1.diff LOG: [mlir] Async: add support for lowering async value operands to LLVM Depends On D93592 Add support for `async.execute` async value unwrapping operands: ``` %token = async.execute(%async_value as %unwrapped : !async.value) { ... async.yield } ``` Reviewed By: csigg Differential Revision: https://reviews.llvm.org/D93598 Added: Modified: mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir mlir/test/mlir-cpu-runner/async-value.mlir Removed: diff --git a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp index f1d6264606be..517c8d2c6f56 100644 --- a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp +++ b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp @@ -586,7 +586,7 @@ outlineExecuteOp(SymbolTable &symbolTable, ExecuteOp execute) { // Collect all outlined function inputs. llvm::SetVector functionInputs(execute.dependencies().begin(), execute.dependencies().end()); - assert(execute.operands().empty() && "operands are not supported"); + functionInputs.insert(execute.operands().begin(), execute.operands().end()); getUsedValuesDefinedAbove(execute.body(), functionInputs); // Collect types for the outlined function inputs and outputs. @@ -636,15 +636,26 @@ outlineExecuteOp(SymbolTable &symbolTable, ExecuteOp execute) { addSuspensionPoint(coro, coroSave.getResult(0), terminatorOp, suspended, resume, builder); + size_t numDependencies = execute.dependencies().size(); + size_t numOperands = execute.operands().size(); + // Await on all dependencies before starting to execute the body region. builder.setInsertionPointToStart(resume); - for (size_t i = 0; i < execute.dependencies().size(); ++i) + for (size_t i = 0; i < numDependencies; ++i) builder.create(func.getArgument(i)); + // Await on all async value operands and unwrap the payload. + SmallVector unwrappedOperands(numOperands); + for (size_t i = 0; i < numOperands; ++i) { +Value operand = func.getArgument(numDependencies + i); +unwrappedOperands[i] = builder.create(loc, operand).result(); + } + // Map from function inputs defined above the execute op to the function // arguments. BlockAndValueMapping valueMapping; valueMapping.map(functionInputs, func.getArguments()); + valueMapping.map(execute.body().getArguments(), unwrappedOperands); // Clone all operations from the execute operation body into the outlined // function body. @@ -1069,14 +1080,6 @@ void ConvertAsyncToLLVMPass::runOnOperation() { return WalkResult::interrupt(); } -// We currently do not support execute operations that have async value -// operands or produce async results. -if (!execute.operands().empty()) { - execute.emitOpError( - "can't outline async.execute op with async value operands"); - return WalkResult::interrupt(); -} - outlinedFunctions.insert(outlineExecuteOp(symbolTable, execute)); return WalkResult::advance(); diff --git a/mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir b/mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir index dce0cf89628f..75b323490cbb 100644 --- a/mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir +++ b/mlir/test/Conversion/AsyncToLLVM/convert-to-llvm.mlir @@ -252,3 +252,54 @@ func @execute_and_return_f32() -> f32 { // Emplace result token. // CHECK: call @mlirAsyncRuntimeEmplaceToken(%[[TOKEN]]) +// - + +// RUN: mlir-opt %s -split-input-file -convert-async-to-llvm | FileCheck %s + +func @async_value_operands() { + // CHECK: %[[RET:.*]]:2 = call @async_execute_fn + %token, %result = async.execute -> !async.value { +%c0 = constant 123.0 : f32 +async.yield %c0 : f32 + } + + // CHECK: %[[TOKEN:.*]] = call @async_execute_fn_0(%[[RET]]#1) + %token0 = async.execute(%result as %value: !async.value) { +%0 = addf %value, %value : f32 +async.yield + } + + // CHECK: call @mlirAsyncRuntimeAwaitToken(%[[TOKEN]]) + async.await %token0 : !async.token + + return +} + +// Function outlined from the first async.execute operation. +// CHECK-LABEL: func private @async_execute_fn() + +// Function outlined from the second async.execute operation. +// CHECK-LABEL: func private @async_execute_fn_0(%arg0: !llvm.ptr) +// CHECK: %[[TOKEN:.*]] = call @mlirAsyncRuntimeCreateToken() +// CHECK: %[[HDL:.*]] = llvm.call @llvm.coro.begin + +// Suspend coroutine in the beginning. +// CHECK: call @mlirAsyncRuntimeExecute(%[[HDL]], +// CHEC
[llvm-branch-commits] [mlir] d4f1a3c - [mlir] Add microbenchmark for linalg+async-parallel-for
Author: Eugene Zhulenev Date: 2020-11-21T03:47:14-08:00 New Revision: d4f1a3c6e2c6031eb45ddb51e3f4fbf50bde6ed8 URL: https://github.com/llvm/llvm-project/commit/d4f1a3c6e2c6031eb45ddb51e3f4fbf50bde6ed8 DIFF: https://github.com/llvm/llvm-project/commit/d4f1a3c6e2c6031eb45ddb51e3f4fbf50bde6ed8.diff LOG: [mlir] Add microbenchmark for linalg+async-parallel-for Reviewed By: nicolasvasilache Differential Revision: https://reviews.llvm.org/D91896 Added: mlir/integration_test/Dialect/Async/CPU/microbench-linalg-async-parallel-for.mlir Modified: mlir/lib/ExecutionEngine/AsyncRuntime.cpp Removed: diff --git a/mlir/integration_test/Dialect/Async/CPU/microbench-linalg-async-parallel-for.mlir b/mlir/integration_test/Dialect/Async/CPU/microbench-linalg-async-parallel-for.mlir new file mode 100644 index ..553e1c339c0a --- /dev/null +++ b/mlir/integration_test/Dialect/Async/CPU/microbench-linalg-async-parallel-for.mlir @@ -0,0 +1,127 @@ +// RUN: mlir-opt %s \ +// RUN: -linalg-tile-to-parallel-loops="linalg-tile-sizes=256" \ +// RUN: -async-parallel-for="num-concurrent-async-execute=4" \ +// RUN: -async-ref-counting \ +// RUN: -convert-async-to-llvm \ +// RUN: -lower-affine \ +// RUN: -convert-linalg-to-loops \ +// RUN: -convert-scf-to-std \ +// RUN: -std-expand \ +// RUN: -convert-vector-to-llvm \ +// RUN: -convert-std-to-llvm \ +// RUN: | mlir-cpu-runner \ +// RUN: -e entry -entry-point-result=void -O3 \ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_async_runtime%shlibext\ +// RUN: | FileCheck %s --dump-input=always + +// RUN: mlir-opt %s \ +// RUN: -convert-linalg-to-loops \ +// RUN: -convert-scf-to-std \ +// RUN: -convert-vector-to-llvm \ +// RUN: -convert-std-to-llvm \ +// RUN: | mlir-cpu-runner \ +// RUN: -e entry -entry-point-result=void -O3 \ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_async_runtime%shlibext\ +// RUN: | FileCheck %s --dump-input=always + +#map0 = affine_map<(d0, d1) -> (d0, d1)> + +func @linalg_generic(%lhs: memref, + %rhs: memref, + %sum: memref) { + linalg.generic { +indexing_maps = [#map0, #map0, #map0], +iterator_types = ["parallel", "parallel"] + } +ins(%lhs, %rhs : memref, memref) +outs(%sum : memref) + { +^bb0(%lhs_in: f32, %rhs_in: f32, %sum_out: f32): + %0 = addf %lhs_in, %rhs_in : f32 + linalg.yield %0 : f32 + } + + return +} + +func @entry() { + %f1 = constant 1.0 : f32 + %f4 = constant 4.0 : f32 + %c0 = constant 0 : index + %c1 = constant 1 : index + %cM = constant 1000 : index + + // + // Sanity check for the function under test. + // + + %LHS10 = alloc() {alignment = 64} : memref<1x10xf32> + %RHS10 = alloc() {alignment = 64} : memref<1x10xf32> + %DST10 = alloc() {alignment = 64} : memref<1x10xf32> + + linalg.fill(%LHS10, %f1) : memref<1x10xf32>, f32 + linalg.fill(%RHS10, %f1) : memref<1x10xf32>, f32 + + %LHS = memref_cast %LHS10 : memref<1x10xf32> to memref + %RHS = memref_cast %RHS10 : memref<1x10xf32> to memref + %DST = memref_cast %DST10 : memref<1x10xf32> to memref + + call @linalg_generic(%LHS, %RHS, %DST) +: (memref, memref, memref) -> () + + // CHECK: [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] + %U = memref_cast %DST10 : memref<1x10xf32> to memref<*xf32> + call @print_memref_f32(%U): (memref<*xf32>) -> () + + dealloc %LHS10: memref<1x10xf32> + dealloc %RHS10: memref<1x10xf32> + dealloc %DST10: memref<1x10xf32> + + // + // Allocate data for microbenchmarks. + // + + %LHS1024 = alloc() {alignment = 64} : memref<1024x1024xf32> + %RHS1024 = alloc() {alignment = 64} : memref<1024x1024xf32> + %DST1024 = alloc() {alignment = 64} : memref<1024x1024xf32> + + %LHS0 = memref_cast %LHS1024 : memref<1024x1024xf32> to memref + %RHS0 = memref_cast %RHS1
[llvm-branch-commits] [mlir] 13ab072 - [mlir] AsynToLLVM: do no use op->getOperands() in conversion patterns
Author: Eugene Zhulenev Date: 2020-11-21T04:57:26-08:00 New Revision: 13ab072b25b062d9510ebc9a7d0e1d2e619e4a34 URL: https://github.com/llvm/llvm-project/commit/13ab072b25b062d9510ebc9a7d0e1d2e619e4a34 DIFF: https://github.com/llvm/llvm-project/commit/13ab072b25b062d9510ebc9a7d0e1d2e619e4a34.diff LOG: [mlir] AsynToLLVM: do no use op->getOperands() in conversion patterns Differential Revision: https://reviews.llvm.org/D91910 Added: Modified: mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp Removed: diff --git a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp index b08f7e4c45b7..c36cde1054ed 100644 --- a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp +++ b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp @@ -592,7 +592,7 @@ class CallOpOpConversion : public ConversionPattern { CallOp call = cast(op); rewriter.replaceOpWithNewOp(op, resultTypes, call.callee(), -call.getOperands()); +operands); return success(); } @@ -733,7 +733,7 @@ class AwaitOpLoweringBase : public ConversionPattern { // async API await function call. if (!isInCoroutine) rewriter.create(loc, TypeRange(), blockingAwaitFuncName, - ValueRange(op->getOperand(0))); + ValueRange(operands[0])); // Inside the coroutine we convert await operation into coroutine suspension // point, and resume execution asynchronously. @@ -755,8 +755,8 @@ class AwaitOpLoweringBase : public ConversionPattern { // Call async runtime API to resume a coroutine in the managed thread when // the async await argument becomes ready. - SmallVector awaitAndExecuteArgs = { - await.getOperand(), coro.coroHandle, resumePtr.res()}; + SmallVector awaitAndExecuteArgs = {operands[0], coro.coroHandle, + resumePtr.res()}; builder.create(loc, TypeRange(), coroAwaitFuncName, awaitAndExecuteArgs); ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] f2df67e - [mlir] Fix async microbench integration test
Author: Eugene Zhulenev Date: 2020-11-21T07:02:24-08:00 New Revision: f2df67e2a69e15b3e1117d99d076ffcdaeb2304f URL: https://github.com/llvm/llvm-project/commit/f2df67e2a69e15b3e1117d99d076ffcdaeb2304f DIFF: https://github.com/llvm/llvm-project/commit/f2df67e2a69e15b3e1117d99d076ffcdaeb2304f.diff LOG: [mlir] Fix async microbench integration test Differential Revision: https://reviews.llvm.org/D91912 Added: Modified: mlir/integration_test/Dialect/Async/CPU/microbench-linalg-async-parallel-for.mlir Removed: diff --git a/mlir/integration_test/Dialect/Async/CPU/microbench-linalg-async-parallel-for.mlir b/mlir/integration_test/Dialect/Async/CPU/microbench-linalg-async-parallel-for.mlir index 553e1c339c0a..189eeaefc21d 100644 --- a/mlir/integration_test/Dialect/Async/CPU/microbench-linalg-async-parallel-for.mlir +++ b/mlir/integration_test/Dialect/Async/CPU/microbench-linalg-async-parallel-for.mlir @@ -10,9 +10,10 @@ // RUN: -convert-vector-to-llvm \ // RUN: -convert-std-to-llvm \ // RUN: | mlir-cpu-runner \ -// RUN: -e entry -entry-point-result=void -O3 \ -// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ -// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_async_runtime%shlibext\ +// RUN: -e entry -entry-point-result=void -O3 \ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_c_runner_utils%shlibext\ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_async_runtime%shlibext \ // RUN: | FileCheck %s --dump-input=always // RUN: mlir-opt %s \ @@ -21,9 +22,10 @@ // RUN: -convert-vector-to-llvm \ // RUN: -convert-std-to-llvm \ // RUN: | mlir-cpu-runner \ -// RUN: -e entry -entry-point-result=void -O3 \ -// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ -// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_async_runtime%shlibext\ +// RUN: -e entry -entry-point-result=void -O3 \ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_c_runner_utils%shlibext\ +// RUN: -shared-libs=%mlir_integration_test_dir/libmlir_async_runtime%shlibext \ // RUN: | FileCheck %s --dump-input=always #map0 = affine_map<(d0, d1) -> (d0, d1)> ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 9edcedf - [mlir] AsyncRuntime: disable threading until test flakiness is fixed
Author: Eugene Zhulenev Date: 2020-12-01T01:12:16-08:00 New Revision: 9edcedf7f222ce7c893d1e3bf19b3a7a1f0f2218 URL: https://github.com/llvm/llvm-project/commit/9edcedf7f222ce7c893d1e3bf19b3a7a1f0f2218 DIFF: https://github.com/llvm/llvm-project/commit/9edcedf7f222ce7c893d1e3bf19b3a7a1f0f2218.diff LOG: [mlir] AsyncRuntime: disable threading until test flakiness is fixed ExecutionEngine/LLJIT do not run globals destructors in loaded dynamic libraries when destroyed, and threads managed by ThreadPool can race with program termination, and it leads to segfaults. TODO: Re-enable threading after fixing a problem with destructors, or removing static globals from dynamic library. Differential Revision: https://reviews.llvm.org/D92368 Added: Modified: mlir/lib/ExecutionEngine/AsyncRuntime.cpp Removed: diff --git a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp index 6bf59f86208d..3b90b9c694f3 100644 --- a/mlir/lib/ExecutionEngine/AsyncRuntime.cpp +++ b/mlir/lib/ExecutionEngine/AsyncRuntime.cpp @@ -24,8 +24,6 @@ #include #include -#include "llvm/Support/ThreadPool.h" - //===--===// // Async runtime API. //===--===// @@ -45,7 +43,6 @@ class AsyncRuntime { AsyncRuntime() : numRefCountedObjects(0) {} ~AsyncRuntime() { -threadPool.wait(); // wait for the completion of all async tasks assert(getNumRefCountedObjects() == 0 && "all ref counted objects must be destroyed"); } @@ -54,8 +51,6 @@ class AsyncRuntime { return numRefCountedObjects.load(std::memory_order_relaxed); } - llvm::ThreadPool &getThreadPool() { return threadPool; } - private: friend class RefCounted; @@ -69,8 +64,6 @@ class AsyncRuntime { } std::atomic numRefCountedObjects; - - llvm::ThreadPool threadPool; }; // Returns the default per-process instance of an async runtime. @@ -241,8 +234,7 @@ extern "C" void mlirAsyncRuntimeAwaitAllInGroup(AsyncGroup *group) { } extern "C" void mlirAsyncRuntimeExecute(CoroHandle handle, CoroResume resume) { - auto *runtime = getDefaultAsyncRuntimeInstance(); - runtime->getThreadPool().async([handle, resume]() { (*resume)(handle); }); + (*resume)(handle); } extern "C" void mlirAsyncRuntimeAwaitTokenAndExecute(AsyncToken *token, ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 94e645f - [mlir] Async: Add numWorkerThreads argument to createAsyncParallelForPass
Author: Eugene Zhulenev Date: 2020-12-08T10:30:14-08:00 New Revision: 94e645f9cce8fba26b4aec069103794f1779065f URL: https://github.com/llvm/llvm-project/commit/94e645f9cce8fba26b4aec069103794f1779065f DIFF: https://github.com/llvm/llvm-project/commit/94e645f9cce8fba26b4aec069103794f1779065f.diff LOG: [mlir] Async: Add numWorkerThreads argument to createAsyncParallelForPass Add an option to pass the number of worker threads to select the number of async regions for parallel for transformation. ``` std::unique_ptr> createAsyncParallelForPass(int numWorkerThreads); ``` Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D92835 Added: Modified: mlir/include/mlir/Dialect/Async/Passes.h mlir/lib/Dialect/Async/Transforms/AsyncParallelFor.cpp Removed: diff --git a/mlir/include/mlir/Dialect/Async/Passes.h b/mlir/include/mlir/Dialect/Async/Passes.h index 9716bde76593..ab5abdc28611 100644 --- a/mlir/include/mlir/Dialect/Async/Passes.h +++ b/mlir/include/mlir/Dialect/Async/Passes.h @@ -19,6 +19,9 @@ namespace mlir { std::unique_ptr> createAsyncParallelForPass(); +std::unique_ptr> +createAsyncParallelForPass(int numWorkerThreads); + std::unique_ptr> createAsyncRefCountingPass(); std::unique_ptr> createAsyncRefCountingOptimizationPass(); diff --git a/mlir/lib/Dialect/Async/Transforms/AsyncParallelFor.cpp b/mlir/lib/Dialect/Async/Transforms/AsyncParallelFor.cpp index c6508610c796..d6553974bc38 100644 --- a/mlir/lib/Dialect/Async/Transforms/AsyncParallelFor.cpp +++ b/mlir/lib/Dialect/Async/Transforms/AsyncParallelFor.cpp @@ -96,6 +96,10 @@ struct AsyncParallelForRewrite : public OpRewritePattern { struct AsyncParallelForPass : public AsyncParallelForBase { AsyncParallelForPass() = default; + AsyncParallelForPass(int numWorkerThreads) { +assert(numWorkerThreads >= 1); +numConcurrentAsyncExecute = numWorkerThreads; + } void runOnFunction() override; }; @@ -276,3 +280,8 @@ void AsyncParallelForPass::runOnFunction() { std::unique_ptr> mlir::createAsyncParallelForPass() { return std::make_unique(); } + +std::unique_ptr> +mlir::createAsyncParallelForPass(int numWorkerThreads) { + return std::make_unique(numWorkerThreads); +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits