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