MLIR  15.0.0git
ExecutionEngine.h
Go to the documentation of this file.
1 //===- ExecutionEngine.h - MLIR Execution engine and utils -----*- C++ -*--===//
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 // This file provides a JIT-backed execution engine for MLIR modules.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_EXECUTIONENGINE_EXECUTIONENGINE_H_
14 #define MLIR_EXECUTIONENGINE_EXECUTIONENGINE_H_
15 
16 #include "mlir/Support/LLVM.h"
17 #include "llvm/ExecutionEngine/ObjectCache.h"
18 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
19 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/Support/Error.h"
22 
23 #include <functional>
24 #include <memory>
25 
26 namespace llvm {
27 template <typename T> class Expected;
28 class Module;
29 class ExecutionEngine;
30 class JITEventListener;
31 class MemoryBuffer;
32 } // namespace llvm
33 
34 namespace mlir {
35 
36 class ModuleOp;
37 
38 /// A simple object cache following Lang's LLJITWithObjectCache example.
39 class SimpleObjectCache : public llvm::ObjectCache {
40 public:
41  void notifyObjectCompiled(const llvm::Module *m,
42  llvm::MemoryBufferRef objBuffer) override;
43  std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module *m) override;
44 
45  /// Dump cached object to output file `filename`.
46  void dumpToObjectFile(StringRef filename);
47 
48 private:
49  llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> cachedObjects;
50 };
51 
53  /// If `llvmModuleBuilder` is provided, it will be used to create LLVM module
54  /// from the given MLIR module. Otherwise, a default `translateModuleToLLVMIR`
55  /// function will be used to translate MLIR module to LLVM IR.
57  llvm::LLVMContext &)>
58  llvmModuleBuilder = nullptr;
59 
60  /// If `transformer` is provided, it will be called on the LLVM module during
61  /// JIT-compilation and can be used, e.g., for reporting or optimization.
63 
64  /// `jitCodeGenOptLevel`, when provided, is used as the optimization level for
65  /// target code generation.
66  Optional<llvm::CodeGenOpt::Level> jitCodeGenOptLevel = llvm::None;
67 
68  /// If `sharedLibPaths` are provided, the underlying JIT-compilation will
69  /// open and link the shared libraries for symbol resolution.
70  ArrayRef<StringRef> sharedLibPaths = {};
71 
72  /// Specifies an existing `sectionMemoryMapper` to be associated with the
73  /// compiled code. If none is provided, a default memory mapper that directly
74  /// calls into the operating system is used.
75  llvm::SectionMemoryManager::MemoryMapper *sectionMemoryMapper = nullptr;
76 
77  /// If `enableObjectCache` is set, the JIT compiler will create one to store
78  /// the object generated for the given module. The contents of the cache can
79  /// be dumped to a file via the `dumpToObjectfile` method.
80  bool enableObjectCache = false;
81 
82  /// If enable `enableGDBNotificationListener` is set, the JIT compiler will
83  /// notify the llvm's global GDB notification listener.
84  bool enableGDBNotificationListener = true;
85 
86  /// If `enablePerfNotificationListener` is set, the JIT compiler will notify
87  /// the llvm's global Perf notification listener.
88  bool enablePerfNotificationListener = true;
89 };
90 
91 /// JIT-backed execution engine for MLIR modules. Assumes the module can be
92 /// converted to LLVM IR. For each function, creates a wrapper function with
93 /// the fixed interface
94 ///
95 /// void _mlir_funcName(void **)
96 ///
97 /// where the only argument is interpreted as a list of pointers to the actual
98 /// arguments of the function, followed by a pointer to the result. This allows
99 /// the engine to provide the caller with a generic function pointer that can
100 /// be used to invoke the JIT-compiled function.
102 public:
103  ExecutionEngine(bool enableObjectCache, bool enableGDBNotificationListener,
104  bool enablePerfNotificationListener);
105 
106  /// Creates an execution engine for the given module.
108  create(ModuleOp m, const ExecutionEngineOptions &options = {});
109 
110  /// Looks up a packed-argument function wrapping the function with the given
111  /// name and returns a pointer to it. Propagates errors in case of failure.
112  llvm::Expected<void (*)(void **)> lookupPacked(StringRef name) const;
113 
114  /// Looks up the original function with the given name and returns a
115  /// pointer to it. This is not necesarily a packed function. Propagates
116  /// errors in case of failure.
117  llvm::Expected<void *> lookup(StringRef name) const;
118 
119  /// Invokes the function with the given name passing it the list of opaque
120  /// pointers to the actual arguments.
121  llvm::Error invokePacked(StringRef name,
122  MutableArrayRef<void *> args = llvm::None);
123 
124  /// Trait that defines how a given type is passed to the JIT code. This
125  /// defaults to passing the address but can be specialized.
126  template <typename T>
127  struct Argument {
128  static void pack(SmallVectorImpl<void *> &args, T &val) {
129  args.push_back(&val);
130  }
131  };
132 
133  /// Tag to wrap an output parameter when invoking a jitted function.
134  template <typename T>
135  struct Result {
136  Result(T &result) : value(result) {}
137  T &value;
138  };
139 
140  /// Helper function to wrap an output operand when using
141  /// ExecutionEngine::invoke.
142  template <typename T>
143  static Result<T> result(T &t) {
144  return Result<T>(t);
145  }
146 
147  // Specialization for output parameter: their address is forwarded directly to
148  // the native code.
149  template <typename T>
150  struct Argument<Result<T>> {
151  static void pack(SmallVectorImpl<void *> &args, Result<T> &result) {
152  args.push_back(&result.value);
153  }
154  };
155 
156  /// Invokes the function with the given name passing it the list of arguments
157  /// by value. Function result can be obtain through output parameter using the
158  /// `Result` wrapper defined above. For example:
159  ///
160  /// func @foo(%arg0 : i32) -> i32 attributes { llvm.emit_c_interface }
161  ///
162  /// can be invoked:
163  ///
164  /// int32_t result = 0;
165  /// llvm::Error error = jit->invoke("foo", 42,
166  /// result(result));
167  template <typename... Args>
168  llvm::Error invoke(StringRef funcName, Args... args) {
169  const std::string adapterName =
170  std::string("_mlir_ciface_") + funcName.str();
171  llvm::SmallVector<void *> argsArray;
172  // Pack every arguments in an array of pointers. Delegate the packing to a
173  // trait so that it can be overridden per argument type.
174  // TODO: replace with a fold expression when migrating to C++17.
175  int dummy[] = {0, ((void)Argument<Args>::pack(argsArray, args), 0)...};
176  (void)dummy;
177  return invokePacked(adapterName, argsArray);
178  }
179 
180  /// Set the target triple on the module. This is implicitly done when creating
181  /// the engine.
182  static bool setupTargetTriple(llvm::Module *llvmModule);
183 
184  /// Dump object code to output file `filename`.
185  void dumpToObjectFile(StringRef filename);
186 
187  /// Register symbols with this ExecutionEngine.
188  void registerSymbols(
189  llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)>
190  symbolMap);
191 
192 private:
193  /// Ordering of llvmContext and jit is important for destruction purposes: the
194  /// jit must be destroyed before the context.
195  llvm::LLVMContext llvmContext;
196 
197  /// Underlying LLJIT.
198  std::unique_ptr<llvm::orc::LLJIT> jit;
199 
200  /// Underlying cache.
201  std::unique_ptr<SimpleObjectCache> cache;
202 
203  /// GDB notification listener.
204  llvm::JITEventListener *gdbListener;
205 
206  /// Perf notification listener.
207  llvm::JITEventListener *perfListener;
208 };
209 
210 } // namespace mlir
211 
212 #endif // MLIR_EXECUTIONENGINE_EXECUTIONENGINE_H_
Include the generated interface declarations.
Explicitly register a set of "builtin" types.
Definition: CallGraph.h:221
static void pack(SmallVectorImpl< void *> &args, Result< T > &result)
static constexpr const bool value
A simple object cache following Lang&#39;s LLJITWithObjectCache example.
static void pack(SmallVectorImpl< void *> &args, T &val)
JIT-backed execution engine for MLIR modules.
Trait that defines how a given type is passed to the JIT code.
static llvm::ManagedStatic< PassManagerOptions > options
Tag to wrap an output parameter when invoking a jitted function.
llvm::Error invoke(StringRef funcName, Args... args)
Invokes the function with the given name passing it the list of arguments by value.
static Result< T > result(T &t)
Helper function to wrap an output operand when using ExecutionEngine::invoke.