-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
Copy pathllvm_instance.h
384 lines (353 loc) · 12.7 KB
/
llvm_instance.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*! \file llvm_instance.h
*/
#ifndef TVM_TARGET_LLVM_LLVM_INSTANCE_H_
#define TVM_TARGET_LLVM_LLVM_INSTANCE_H_
#ifdef TVM_LLVM_VERSION
#include <llvm/ADT/ArrayRef.h>
#if TVM_LLVM_VERSION >= 150
#include <llvm/IR/FMF.h>
#else
#include <llvm/IR/Operator.h>
#endif
#include <llvm/Support/CodeGen.h>
#include <llvm/Target/TargetOptions.h>
#include <tvm/ir/expr.h>
#include <tvm/runtime/container/array.h>
#include <tvm/runtime/container/optional.h>
#include <tvm/runtime/container/string.h>
#include <tvm/target/target.h>
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace llvm {
class LLVMContext;
class MemoryBuffer;
class Module;
class TargetMachine;
} // namespace llvm
namespace tvm {
namespace codegen {
class LLVMTarget;
/*!
* \class LLVMInstance
* \brief LLVMInstance is a class that (conceptually) starts and stops LLVM.
* All uses of LLVM should take place within a lifetime of an object
* of this class.
*
* E.g.
* ```{.cpp}
* {
* LLVMInstance llvm_instance;
* ...
* someFunctionFromLLVM(...);
* ...
* }
* // no more calls to LLVM here
* ```
* In addition to that, LLVMInstance provides an LLVM context (llvm::LLVMContext).
* The context is a structure in LLVM where common IR constructs are maintained,
* (such as types, constants, etc.) so that they can be identified by their
* address (i.e. pointer comparison). Because of that, it's important to use
* the same context throughout compilation.
*
* At the moment the "starting" of LLVM performs initialization of LLVM, but
* "stopping" doesn't do anything. In the future, if such a need arises, this
* functionality may be extended to perform dlopen/dlclose of the LLVM-based
* code in TVM.
*
* This class provides means to deserialize an LLVM module, either from text
* (in a string), or from a file. In either case, the serialized module can
* be LLVM IR assembly, or binary bitcode enconding.
*/
class LLVMInstance {
public:
/*!
* \brief Constructs LLVMInstance
*/
LLVMInstance();
/*!
* \brief Destroys LLVMInstance object
*/
~LLVMInstance(); // Must not be "= default" here in the header file.
/*!
* \brief Get the LLVM context for this scope.
*/
std::shared_ptr<llvm::LLVMContext> GetContext() const { return ctx_; }
/*!
* \brief Create `llvm::Module` from a string.
*
* Parse the string in \param llvm_ir, and return the `llvm::Module`.
* At the moment this function will abort if the parsing fails.
* \param llvm_ir string with the LLVM IR assembly or bitcode
* \return created `llvm::Module`
*/
std::unique_ptr<llvm::Module> ParseIR(const std::string& llvm_ir) const;
/*!
* \brief Load `llvm::Module` from a given file
*
* Read the file \param file_name, and return the `llvm::Module`.
* At the moment this function will abort if reading of the file or creation
* of the module fails.
* \param file_name file with the LLVM IR assembly or bitcode
* \return created `llvm::Module`
*/
std::unique_ptr<llvm::Module> LoadIR(const std::string& file_name) const;
private:
std::unique_ptr<llvm::Module> ParseBuffer(const llvm::MemoryBuffer& buffer) const;
std::shared_ptr<llvm::LLVMContext> ctx_;
};
/*!
* \class LLVMTargetInfo
* \brief Summary of information for this TVM target relevant to LLVM code
* generation.
*
* This class contains all information that LLVM needs for code generation for
* a particular target. The purpose of this class is only to provide information
* in an easily-accessible form (for example for querying the target properties).
*
* Note that objects of this class must be created within the lifetime of an
* LLVMInstance object.
*/
class LLVMTargetInfo {
public:
/*!
* \brief Constructs LLVMTargetInfo from `Target`
* \param scope LLVMInstance object
* \param target TVM Target object for target "llvm"
*/
LLVMTargetInfo(LLVMInstance& scope, const Target& target); // NOLINT(runtime/references)
/*!
* \brief Constructs LLVMTargetInfo from target string
* \param scope LLVMInstance object
* \param target TVM target string for target "llvm"
*/
// NOLINTNEXTLINE(runtime/references)
LLVMTargetInfo(LLVMInstance& scope, const std::string& target_str);
/*!
* \brief Destroys LLVMTargetInfo object
*/
~LLVMTargetInfo();
/*!
* \brief Returns string representation (as TVM target) of the LLVMTargetInfo
* \return Target string
*
* Note: If the LLVMTargetInfo object was created from a string `s`, the string
* returned here may not be exactly equal to `s`. For example, if the CPU
* was "default", the returned string will have CPU set to the detected host
* CPU.
*/
std::string str() const;
/*!
* \brief Return LLVM's `TargetMachine`, or nullptr
* \param allow_missing do not abort if the target machine cannot be created,
* return nullptr instead
* \return Pointer to the `TargetMachine` object (or nullptr if it cannot be
* created, \see allow_missing)
*/
llvm::TargetMachine* GetOrCreateTargetMachine(bool allow_missing = false);
/*!
* \brief Get the target triple
* \return the target triple
*/
const std::string& GetTargetTriple() const { return triple_; }
/*!
* \brief Get the CPU name
* \return the CPU name: the detected host CPU if the original TVM target
* specified it as "default"
*/
const std::string& GetCPU() const { return cpu_; }
/*!
* \brief Get the list of LLVM target features
* \return array of individual feature strings
*/
llvm::ArrayRef<std::string> GetTargetFeatures() const { return attrs_; }
/*!
* \brief Get the LLVM target feature string
* \return comma-separated list of LLVM target features
*/
std::string GetTargetFeatureString() const;
/*!
* \brief Get the LLVM target options
* \return `llvm::TargetOptions` object for this target
*/
const llvm::TargetOptions& GetTargetOptions() const { return target_options_; }
/*!
* \brief Get fast math flags
* \return `llvm::FastMathFlags` for this target
*/
llvm::FastMathFlags GetFastMathFlags() const { return fast_math_flags_; }
/*!
* \brief Get the LLVM optimization level
* \return optimization level for this target
*/
llvm::CodeGenOpt::Level GetOptLevel() const { return opt_level_; }
/*!
* \class Option
* \brief Internal representation of command-line option
*/
struct Option {
enum class OptType {
Invalid = 0, //!< placeholder, indicates parsing error
Bool, //!< enum value corresponding to type string "bool"
Int, //!< enum value corresponding to type string "int"
UInt, //!< enum value corresponding to type string "uint"
String, //!< enum value corresponding to type string "string"
};
std::string name; //!< option name
OptType type; //!< type of the option value
struct {
union {
bool b; //!< bool option value
int i; //!< int option value
unsigned u = 0; //!< unsigned option value
};
std::string s; //!< string option value
} value; //!< option value specified in the option string
};
/*!
* \brief Get LLVM command line options
* \return the list of LLVM command line options specified for this target
*/
const std::vector<Option>& GetCommandLineOptions() const { return llvm_options_; }
/*!
* \brief Parse a string from the `cl-opt` target attribute
* \param str the option string
* \return parsed `Option` object, if parsing failed the type member will be
* set to `Option::OptType::Invalid`
*/
static Option ParseOptionString(const std::string& str);
/*!
* \brief Checks if the settings in this object that describe global state
* match the current global state
* \return true or false correspondingly
* \note The global state can be modified by command line options. This
* function checks if the specified options differ from their current
* values.
*/
bool MatchesGlobalState() const;
protected:
/*!
* \brief Get the current value of given LLVM option
* \param opt Option with "type" and "name" set
* Fills in the "value" field in the provided Option argument, or sets the
* "type" to Invalid if the option value cannot be obtained.
*/
void GetOptionValue(Option* opt) const;
private:
std::string triple_;
std::string cpu_;
std::vector<std::string> attrs_;
std::vector<Option> llvm_options_;
llvm::TargetOptions target_options_;
llvm::FastMathFlags fast_math_flags_;
llvm::CodeGenOpt::Level opt_level_;
llvm::Reloc::Model reloc_model_ = llvm::Reloc::PIC_;
llvm::CodeModel::Model code_model_ = llvm::CodeModel::Small;
std::shared_ptr<llvm::TargetMachine> target_machine_;
};
/*!
* \class LLVMTarget
* \brief Information used by LLVM for code generation for particular target
*
* In addition to all information that LLVM needs for code generation for
* a particular target, objects of this class handle saving and restoring
* global LLVM state that may be affected by these flags. This way, code
* generation for each LLVM-based target in TVM will start with the same LLVM
* global state.
*
* Note that objects of this class must be created within the lifetime of an
* LLVMInstance object.
*/
class LLVMTarget : public LLVMTargetInfo {
public:
/*!
* \brief Constructs LLVMTarget from `Target`
* \param scope LLVMInstance object
* \param target_info Target info object for target "llvm"
*/
LLVMTarget(LLVMInstance& scope, const LLVMTargetInfo& target_info); // NOLINT(runtime/references)
/*!
* \brief Constructs LLVMTarget from `Target`
* \param scope LLVMInstance object
* \param target TVM Target object for target "llvm"
*/
LLVMTarget(LLVMInstance& scope, const Target& target); // NOLINT(runtime/references)
/*!
* \brief Constructs LLVMTarget from target string
* \param scope LLVMInstance object
* \param target TVM target string for target "llvm"
*/
LLVMTarget(LLVMInstance& scope, const std::string& target_str); // NOLINT(runtime/references)
/*!
* \brief Destroys LLVMTarget object
*/
~LLVMTarget();
/*!
* \brief Get the LLVMInstance object from which the LLVMTarget object was
* created
* \return The enclosing LLVMInstance object
*/
const LLVMInstance& GetInstance() const { return instance_; }
/*!
* \brief Get the current LLVM context
* \return the current LLVM context
*/
llvm::LLVMContext* GetContext() const;
/*!
* \brief Extract the target string from given `llvm::Module`
* \param module LLVM module with the TVM target string embedded as metadata
* \return the target string from module's metadata
*/
static std::string GetTargetMetadata(const llvm::Module& module);
/*!
* \brief Embed target string as metadata in given `llvm::Module`
* \param module the module to insert the target string into
*/
void SetTargetMetadata(llvm::Module* module) const;
// Stubs to enable use with `With`.
void EnterWithScope() {}
void ExitWithScope() {}
private:
std::vector<Option> saved_llvm_options_;
/*!
* \brief Apply or revert command-line LLVM options
* \param apply_otherwise_revert if true, apply the options (saving previous
* values, if false, then restore the saved values
* \param dry_run if true, do not make any changes (or save anything)
* \return true is changes were made (or would have been made in a dry run),
* false otherwise
*/
bool ApplyLLVMOptions(bool apply_otherwise_revert, bool dry_run = false);
const LLVMInstance& instance_;
std::weak_ptr<llvm::LLVMContext> ctx_;
/*!
* \brief Global singleton flag indicating whether LLVM's global state has
* been modified or not (via command-line flags). There can only be
* a single such modification in effect at any given time.
*/
static bool modified_llvm_state_;
};
} // namespace codegen
} // namespace tvm
#endif // TVM_LLVM_VERSION
#endif // TVM_TARGET_LLVM_LLVM_INSTANCE_H_