LLVM  17.0.0git
ThreadSafeModule.h
Go to the documentation of this file.
1 //===----------- ThreadSafeModule.h -- Layer interfaces ---------*- 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 // Thread safe wrappers and utilities for Module and LLVMContext.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULE_H
14 #define LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULE_H
15 
16 #include "llvm/IR/LLVMContext.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Support/Compiler.h"
19 
20 #include <functional>
21 #include <memory>
22 #include <mutex>
23 
24 namespace llvm {
25 namespace orc {
26 
27 /// An LLVMContext together with an associated mutex that can be used to lock
28 /// the context to prevent concurrent access by other threads.
30 private:
31  struct State {
32  State(std::unique_ptr<LLVMContext> Ctx) : Ctx(std::move(Ctx)) {}
33 
34  std::unique_ptr<LLVMContext> Ctx;
35  std::recursive_mutex Mutex;
36  };
37 
38 public:
39  // RAII based lock for ThreadSafeContext.
40  class [[nodiscard]] Lock {
41  public:
42  Lock(std::shared_ptr<State> S) : S(std::move(S)), L(this->S->Mutex) {}
43 
44  private:
45  std::shared_ptr<State> S;
46  std::unique_lock<std::recursive_mutex> L;
47  };
48 
49  /// Construct a null context.
50  ThreadSafeContext() = default;
51 
52  /// Construct a ThreadSafeContext from the given LLVMContext.
53  ThreadSafeContext(std::unique_ptr<LLVMContext> NewCtx)
54  : S(std::make_shared<State>(std::move(NewCtx))) {
55  assert(S->Ctx != nullptr &&
56  "Can not construct a ThreadSafeContext from a nullptr");
57  }
58 
59  /// Returns a pointer to the LLVMContext that was used to construct this
60  /// instance, or null if the instance was default constructed.
61  LLVMContext *getContext() { return S ? S->Ctx.get() : nullptr; }
62 
63  /// Returns a pointer to the LLVMContext that was used to construct this
64  /// instance, or null if the instance was default constructed.
65  const LLVMContext *getContext() const { return S ? S->Ctx.get() : nullptr; }
66 
67  Lock getLock() const {
68  assert(S && "Can not lock an empty ThreadSafeContext");
69  return Lock(S);
70  }
71 
72 private:
73  std::shared_ptr<State> S;
74 };
75 
76 /// An LLVM Module together with a shared ThreadSafeContext.
78 public:
79  /// Default construct a ThreadSafeModule. This results in a null module and
80  /// null context.
81  ThreadSafeModule() = default;
82 
84 
86  // We have to explicitly define this move operator to copy the fields in
87  // reverse order (i.e. module first) to ensure the dependencies are
88  // protected: The old module that is being overwritten must be destroyed
89  // *before* the context that it depends on.
90  // We also need to lock the context to make sure the module tear-down
91  // does not overlap any other work on the context.
92  if (M) {
93  auto L = TSCtx.getLock();
94  M = nullptr;
95  }
96  M = std::move(Other.M);
97  TSCtx = std::move(Other.TSCtx);
98  return *this;
99  }
100 
101  /// Construct a ThreadSafeModule from a unique_ptr<Module> and a
102  /// unique_ptr<LLVMContext>. This creates a new ThreadSafeContext from the
103  /// given context.
104  ThreadSafeModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> Ctx)
105  : M(std::move(M)), TSCtx(std::move(Ctx)) {}
106 
107  /// Construct a ThreadSafeModule from a unique_ptr<Module> and an
108  /// existing ThreadSafeContext.
109  ThreadSafeModule(std::unique_ptr<Module> M, ThreadSafeContext TSCtx)
110  : M(std::move(M)), TSCtx(std::move(TSCtx)) {}
111 
113  // We need to lock the context while we destruct the module.
114  if (M) {
115  auto L = TSCtx.getLock();
116  M = nullptr;
117  }
118  }
119 
120  /// Boolean conversion: This ThreadSafeModule will evaluate to true if it
121  /// wraps a non-null module.
122  explicit operator bool() const {
123  if (M) {
124  assert(TSCtx.getContext() &&
125  "Non-null module must have non-null context");
126  return true;
127  }
128  return false;
129  }
130 
131  /// Locks the associated ThreadSafeContext and calls the given function
132  /// on the contained Module.
133  template <typename Func> decltype(auto) withModuleDo(Func &&F) {
134  assert(M && "Can not call on null module");
135  auto Lock = TSCtx.getLock();
136  return F(*M);
137  }
138 
139  /// Locks the associated ThreadSafeContext and calls the given function
140  /// on the contained Module.
141  template <typename Func> decltype(auto) withModuleDo(Func &&F) const {
142  assert(M && "Can not call on null module");
143  auto Lock = TSCtx.getLock();
144  return F(*M);
145  }
146 
147  /// Locks the associated ThreadSafeContext and calls the given function,
148  /// passing the contained std::unique_ptr<Module>. The given function should
149  /// consume the Module.
150  template <typename Func> decltype(auto) consumingModuleDo(Func &&F) {
151  auto Lock = TSCtx.getLock();
152  return F(std::move(M));
153  }
154 
155  /// Get a raw pointer to the contained module without locking the context.
156  Module *getModuleUnlocked() { return M.get(); }
157 
158  /// Get a raw pointer to the contained module without locking the context.
159  const Module *getModuleUnlocked() const { return M.get(); }
160 
161  /// Returns the context for this ThreadSafeModule.
162  ThreadSafeContext getContext() const { return TSCtx; }
163 
164 private:
165  std::unique_ptr<Module> M;
166  ThreadSafeContext TSCtx;
167 };
168 
169 using GVPredicate = std::function<bool(const GlobalValue &)>;
171 
172 /// Clones the given module on to a new context.
175  GVPredicate ShouldCloneDef = GVPredicate(),
176  GVModifier UpdateClonedDefSource = GVModifier());
177 
178 } // End namespace orc
179 } // End namespace llvm
180 
181 #endif // LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULE_H
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::orc::ThreadSafeModule::~ThreadSafeModule
~ThreadSafeModule()
Definition: ThreadSafeModule.h:112
Module.h
llvm::orc::ThreadSafeModule::getContext
ThreadSafeContext getContext() const
Returns the context for this ThreadSafeModule.
Definition: ThreadSafeModule.h:162
llvm::orc::ThreadSafeModule::getModuleUnlocked
Module * getModuleUnlocked()
Get a raw pointer to the contained module without locking the context.
Definition: ThreadSafeModule.h:156
llvm::orc::ThreadSafeContext::ThreadSafeContext
ThreadSafeContext()=default
Construct a null context.
llvm::orc::ThreadSafeModule::getModuleUnlocked
const Module * getModuleUnlocked() const
Get a raw pointer to the contained module without locking the context.
Definition: ThreadSafeModule.h:159
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::sys::SmartMutex< false >
llvm::orc::ThreadSafeContext::ThreadSafeContext
ThreadSafeContext(std::unique_ptr< LLVMContext > NewCtx)
Construct a ThreadSafeContext from the given LLVMContext.
Definition: ThreadSafeModule.h:53
llvm::orc::ThreadSafeModule::ThreadSafeModule
ThreadSafeModule(std::unique_ptr< Module > M, std::unique_ptr< LLVMContext > Ctx)
Construct a ThreadSafeModule from a unique_ptr<Module> and a unique_ptr<LLVMContext>.
Definition: ThreadSafeModule.h:104
llvm::orc::ThreadSafeContext::Lock
Definition: ThreadSafeModule.h:40
llvm::orc::ThreadSafeContext::getLock
Lock getLock() const
Definition: ThreadSafeModule.h:67
llvm::orc::ThreadSafeContext::getContext
const LLVMContext * getContext() const
Returns a pointer to the LLVMContext that was used to construct this instance, or null if the instanc...
Definition: ThreadSafeModule.h:65
llvm::orc::ThreadSafeModule::ThreadSafeModule
ThreadSafeModule()=default
Default construct a ThreadSafeModule.
llvm::GlobalValue
Definition: GlobalValue.h:44
llvm::orc::ThreadSafeContext::getContext
LLVMContext * getContext()
Returns a pointer to the LLVMContext that was used to construct this instance, or null if the instanc...
Definition: ThreadSafeModule.h:61
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1862
llvm::orc::ThreadSafeContext
An LLVMContext together with an associated mutex that can be used to lock the context to prevent conc...
Definition: ThreadSafeModule.h:29
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:82
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::orc::ThreadSafeModule::withModuleDo
decltype(auto) withModuleDo(Func &&F)
Locks the associated ThreadSafeContext and calls the given function on the contained Module.
Definition: ThreadSafeModule.h:133
this
Analysis the ScalarEvolution expression for r is this
Definition: README.txt:8
llvm::orc::ThreadSafeModule::consumingModuleDo
decltype(auto) consumingModuleDo(Func &&F)
Locks the associated ThreadSafeContext and calls the given function, passing the contained std::uniqu...
Definition: ThreadSafeModule.h:150
Compiler.h
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::orc::ThreadSafeContext::Lock::Lock
Lock(std::shared_ptr< State > S)
Definition: ThreadSafeModule.h:42
llvm::sys::Mutex
SmartMutex< false > Mutex
Mutex - A standard, always enforced mutex.
Definition: Mutex.h:66
llvm::orc::GVPredicate
std::function< bool(const GlobalValue &)> GVPredicate
Definition: ThreadSafeModule.h:169
std
Definition: BitVector.h:851
Other
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1260
llvm::orc::ThreadSafeModule::ThreadSafeModule
ThreadSafeModule(std::unique_ptr< Module > M, ThreadSafeContext TSCtx)
Construct a ThreadSafeModule from a unique_ptr<Module> and an existing ThreadSafeContext.
Definition: ThreadSafeModule.h:109
llvm::orc::GVModifier
std::function< void(GlobalValue &)> GVModifier
Definition: ThreadSafeModule.h:170
llvm::orc::ThreadSafeModule
An LLVM Module together with a shared ThreadSafeContext.
Definition: ThreadSafeModule.h:77
LLVMContext.h
llvm::orc::ThreadSafeModule::operator=
ThreadSafeModule & operator=(ThreadSafeModule &&Other)
Definition: ThreadSafeModule.h:85
llvm::orc::cloneToNewContext
ThreadSafeModule cloneToNewContext(const ThreadSafeModule &TSMW, GVPredicate ShouldCloneDef=GVPredicate(), GVModifier UpdateClonedDefSource=GVModifier())
Clones the given module on to a new context.
Definition: ThreadSafeModule.cpp:18