1 //===- ModuleTranslation.h - MLIR to LLVM conversion ------------*- 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 implements the translation between an MLIR LLVM dialect module and
10 // the corresponding LLVMIR module. It only handles core LLVM IR operations.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_TARGET_LLVMIR_MODULETRANSLATION_H
15 #define MLIR_TARGET_LLVMIR_MODULETRANSLATION_H
16 
17 #include "mlir/IR/Operation.h"
18 #include "mlir/IR/Value.h"
19 #include "mlir/Target/LLVMIR/Export.h"
20 #include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
21 #include "mlir/Target/LLVMIR/TypeToLLVM.h"
22 
23 #include "llvm/ADT/SetVector.h"
24 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
25 
26 namespace llvm {
27 class BasicBlock;
28 class IRBuilderBase;
29 class Function;
30 class Value;
31 } // namespace llvm
32 
33 namespace mlir {
34 class Attribute;
35 class Block;
36 class Location;
37 
38 namespace LLVM {
39 
40 namespace detail {
41 class DebugTranslation;
42 } // namespace detail
43 
44 class LLVMFuncOp;
45 
46 /// Implementation class for module translation. Holds a reference to the module
47 /// being translated, and the mappings between the original and the translated
48 /// functions, basic blocks and values. It is practically easier to hold these
49 /// mappings in one class since the conversion of control flow operations
50 /// needs to look up block and function mappings.
51 class ModuleTranslation {
52   friend std::unique_ptr<llvm::Module>
53   mlir::translateModuleToLLVMIR(Operation *, llvm::LLVMContext &, StringRef);
54 
55 public:
56   /// Stores the mapping between a function name and its LLVM IR representation.
mapFunction(StringRef name,llvm::Function * func)57   void mapFunction(StringRef name, llvm::Function *func) {
58     auto result = functionMapping.try_emplace(name, func);
59     (void)result;
60     assert(result.second &&
61            "attempting to map a function that is already mapped");
62   }
63 
64   /// Finds an LLVM IR function by its name.
lookupFunction(StringRef name)65   llvm::Function *lookupFunction(StringRef name) const {
66     return functionMapping.lookup(name);
67   }
68 
69   /// Stores the mapping between an MLIR value and its LLVM IR counterpart.
mapValue(Value mlir,llvm::Value * llvm)70   void mapValue(Value mlir, llvm::Value *llvm) { mapValue(mlir) = llvm; }
71 
72   /// Provides write-once access to store the LLVM IR value corresponding to the
73   /// given MLIR value.
mapValue(Value value)74   llvm::Value *&mapValue(Value value) {
75     llvm::Value *&llvm = valueMapping[value];
76     assert(llvm == nullptr &&
77            "attempting to map a value that is already mapped");
78     return llvm;
79   }
80 
81   /// Finds an LLVM IR value corresponding to the given MLIR value.
lookupValue(Value value)82   llvm::Value *lookupValue(Value value) const {
83     return valueMapping.lookup(value);
84   }
85 
86   /// Looks up remapped a list of remapped values.
87   SmallVector<llvm::Value *> lookupValues(ValueRange values);
88 
89   /// Stores the mapping between an MLIR block and LLVM IR basic block.
mapBlock(Block * mlir,llvm::BasicBlock * llvm)90   void mapBlock(Block *mlir, llvm::BasicBlock *llvm) {
91     auto result = blockMapping.try_emplace(mlir, llvm);
92     (void)result;
93     assert(result.second && "attempting to map a block that is already mapped");
94   }
95 
96   /// Finds an LLVM IR basic block that corresponds to the given MLIR block.
lookupBlock(Block * block)97   llvm::BasicBlock *lookupBlock(Block *block) const {
98     return blockMapping.lookup(block);
99   }
100 
101   /// Stores the mapping between an MLIR operation with successors and a
102   /// corresponding LLVM IR instruction.
mapBranch(Operation * mlir,llvm::Instruction * llvm)103   void mapBranch(Operation *mlir, llvm::Instruction *llvm) {
104     auto result = branchMapping.try_emplace(mlir, llvm);
105     (void)result;
106     assert(result.second &&
107            "attempting to map a branch that is already mapped");
108   }
109 
110   /// Finds an LLVM IR instruction that corresponds to the given MLIR operation
111   /// with successors.
lookupBranch(Operation * op)112   llvm::Instruction *lookupBranch(Operation *op) const {
113     return branchMapping.lookup(op);
114   }
115 
116   /// Removes the mapping for blocks contained in the region and values defined
117   /// in these blocks.
118   void forgetMapping(Region &region);
119 
120   /// Returns the LLVM metadata corresponding to a reference to an mlir LLVM
121   /// dialect access group operation.
122   llvm::MDNode *getAccessGroup(Operation &opInst,
123                                SymbolRefAttr accessGroupRef) const;
124 
125   /// Returns the LLVM metadata corresponding to a reference to an mlir LLVM
126   /// dialect alias scope operation
127   llvm::MDNode *getAliasScope(Operation &opInst,
128                               SymbolRefAttr aliasScopeRef) const;
129 
130   /// Returns the LLVM metadata corresponding to a llvm loop's codegen
131   /// options attribute.
lookupLoopOptionsMetadata(Attribute options)132   llvm::MDNode *lookupLoopOptionsMetadata(Attribute options) const {
133     return loopOptionsMetadataMapping.lookup(options);
134   }
135 
mapLoopOptionsMetadata(Attribute options,llvm::MDNode * metadata)136   void mapLoopOptionsMetadata(Attribute options, llvm::MDNode *metadata) {
137     auto result = loopOptionsMetadataMapping.try_emplace(options, metadata);
138     (void)result;
139     assert(result.second &&
140            "attempting to map loop options that was already mapped");
141   }
142 
143   // Sets LLVM metadata for memory operations that are in a parallel loop.
144   void setAccessGroupsMetadata(Operation *op, llvm::Instruction *inst);
145 
146   // Sets LLVM metadata for memory operations that have alias scope information.
147   void setAliasScopeMetadata(Operation *op, llvm::Instruction *inst);
148 
149   /// Converts the type from MLIR LLVM dialect to LLVM.
150   llvm::Type *convertType(Type type);
151 
152   /// Returns the MLIR context of the module being translated.
getContext()153   MLIRContext &getContext() { return *mlirModule->getContext(); }
154 
155   /// Returns the LLVM context in which the IR is being constructed.
getLLVMContext()156   llvm::LLVMContext &getLLVMContext() const { return llvmModule->getContext(); }
157 
158   /// Finds an LLVM IR global value that corresponds to the given MLIR operation
159   /// defining a global value.
lookupGlobal(Operation * op)160   llvm::GlobalValue *lookupGlobal(Operation *op) {
161     return globalsMapping.lookup(op);
162   }
163 
164   /// Returns the OpenMP IR builder associated with the LLVM IR module being
165   /// constructed.
getOpenMPBuilder()166   llvm::OpenMPIRBuilder *getOpenMPBuilder() {
167     if (!ompBuilder) {
168       ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
169       ompBuilder->initialize();
170     }
171     return ompBuilder.get();
172   }
173 
174   /// Translates the given location.
175   const llvm::DILocation *translateLoc(Location loc, llvm::DILocalScope *scope);
176 
177   /// Translates the contents of the given block to LLVM IR using this
178   /// translator. The LLVM IR basic block corresponding to the given block is
179   /// expected to exist in the mapping of this translator. Uses `builder` to
180   /// translate the IR, leaving it at the end of the block. If `ignoreArguments`
181   /// is set, does not produce PHI nodes for the block arguments. Otherwise, the
182   /// PHI nodes are constructed for block arguments but are _not_ connected to
183   /// the predecessors that may not exist yet.
184   LogicalResult convertBlock(Block &bb, bool ignoreArguments,
185                              llvm::IRBuilderBase &builder);
186 
187   /// Gets the named metadata in the LLVM IR module being constructed, creating
188   /// it if it does not exist.
189   llvm::NamedMDNode *getOrInsertNamedModuleMetadata(StringRef name);
190 
191   /// Common CRTP base class for ModuleTranslation stack frames.
192   class StackFrame {
193   public:
194     virtual ~StackFrame() = default;
getTypeID()195     TypeID getTypeID() const { return typeID; }
196 
197   protected:
StackFrame(TypeID typeID)198     explicit StackFrame(TypeID typeID) : typeID(typeID) {}
199 
200   private:
201     const TypeID typeID;
202     virtual void anchor();
203   };
204 
205   /// Concrete CRTP base class for ModuleTranslation stack frames. When
206   /// translating operations with regions, users of ModuleTranslation can store
207   /// state on ModuleTranslation stack before entering the region and inspect
208   /// it when converting operations nested within that region. Users are
209   /// expected to derive this class and put any relevant information into fields
210   /// of the derived class. The usual isa/dyn_cast functionality is available
211   /// for instances of derived classes.
212   template <typename Derived>
213   class StackFrameBase : public StackFrame {
214   public:
StackFrameBase()215     explicit StackFrameBase() : StackFrame(TypeID::get<Derived>()) {}
216   };
217 
218   /// Creates a stack frame of type `T` on ModuleTranslation stack. `T` must
219   /// be derived from `StackFrameBase<T>` and constructible from the provided
220   /// arguments. Doing this before entering the region of the op being
221   /// translated makes the frame available when translating ops within that
222   /// region.
223   template <typename T, typename... Args>
stackPush(Args &&...args)224   void stackPush(Args &&...args) {
225     static_assert(
226         std::is_base_of<StackFrame, T>::value,
227         "can only push instances of StackFrame on ModuleTranslation stack");
228     stack.push_back(std::make_unique<T>(std::forward<Args>(args)...));
229   }
230 
231   /// Pops the last element from the ModuleTranslation stack.
stackPop()232   void stackPop() { stack.pop_back(); }
233 
234   /// Calls `callback` for every ModuleTranslation stack frame of type `T`
235   /// starting from the top of the stack.
236   template <typename T>
237   WalkResult
stackWalk(llvm::function_ref<WalkResult (const T &)> callback)238   stackWalk(llvm::function_ref<WalkResult(const T &)> callback) const {
239     static_assert(std::is_base_of<StackFrame, T>::value,
240                   "expected T derived from StackFrame");
241     if (!callback)
242       return WalkResult::skip();
243     for (const std::unique_ptr<StackFrame> &frame : llvm::reverse(stack)) {
244       if (T *ptr = dyn_cast_or_null<T>(frame.get())) {
245         WalkResult result = callback(*ptr);
246         if (result.wasInterrupted())
247           return result;
248       }
249     }
250     return WalkResult::advance();
251   }
252 
253   /// RAII object calling stackPush/stackPop on construction/destruction.
254   template <typename T>
255   struct SaveStack {
256     template <typename... Args>
SaveStackSaveStack257     explicit SaveStack(ModuleTranslation &m, Args &&...args)
258         : moduleTranslation(m) {
259       moduleTranslation.stackPush<T>(std::forward<Args>(args)...);
260     }
~SaveStackSaveStack261     ~SaveStack() { moduleTranslation.stackPop(); }
262 
263   private:
264     ModuleTranslation &moduleTranslation;
265   };
266 
267 private:
268   ModuleTranslation(Operation *module,
269                     std::unique_ptr<llvm::Module> llvmModule);
270   ~ModuleTranslation();
271 
272   /// Converts individual components.
273   LogicalResult convertOperation(Operation &op, llvm::IRBuilderBase &builder);
274   LogicalResult convertFunctionSignatures();
275   LogicalResult convertFunctions();
276   LogicalResult convertGlobals();
277   LogicalResult convertOneFunction(LLVMFuncOp func);
278 
279   /// Process access_group LLVM Metadata operations and create LLVM
280   /// metadata nodes.
281   LogicalResult createAccessGroupMetadata();
282 
283   /// Process alias.scope LLVM Metadata operations and create LLVM
284   /// metadata nodes for them and their domains.
285   LogicalResult createAliasScopeMetadata();
286 
287   /// Translates dialect attributes attached to the given operation.
288   LogicalResult convertDialectAttributes(Operation *op);
289 
290   /// Original and translated module.
291   Operation *mlirModule;
292   std::unique_ptr<llvm::Module> llvmModule;
293   /// A converter for translating debug information.
294   std::unique_ptr<detail::DebugTranslation> debugTranslation;
295 
296   /// Builder for LLVM IR generation of OpenMP constructs.
297   std::unique_ptr<llvm::OpenMPIRBuilder> ompBuilder;
298 
299   /// Mappings between llvm.mlir.global definitions and corresponding globals.
300   DenseMap<Operation *, llvm::GlobalValue *> globalsMapping;
301 
302   /// A stateful object used to translate types.
303   TypeToLLVMIRTranslator typeTranslator;
304 
305   /// A dialect interface collection used for dispatching the translation to
306   /// specific dialects.
307   LLVMTranslationInterface iface;
308 
309   /// Mappings between original and translated values, used for lookups.
310   llvm::StringMap<llvm::Function *> functionMapping;
311   DenseMap<Value, llvm::Value *> valueMapping;
312   DenseMap<Block *, llvm::BasicBlock *> blockMapping;
313 
314   /// A mapping between MLIR LLVM dialect terminators and LLVM IR terminators
315   /// they are converted to. This allows for connecting PHI nodes to the source
316   /// values after all operations are converted.
317   DenseMap<Operation *, llvm::Instruction *> branchMapping;
318 
319   /// Mapping from an access group metadata operation to its LLVM metadata.
320   /// This map is populated on module entry and is used to annotate loops (as
321   /// identified via their branches) and contained memory accesses.
322   DenseMap<Operation *, llvm::MDNode *> accessGroupMetadataMapping;
323 
324   /// Mapping from an attribute describing loop codegen options to its LLVM
325   /// metadata. The metadata is attached to Latch block branches with this
326   /// attribute.
327   DenseMap<Attribute, llvm::MDNode *> loopOptionsMetadataMapping;
328 
329   /// Mapping from an access scope metadata operation to its LLVM metadata.
330   /// This map is populated on module entry.
331   DenseMap<Operation *, llvm::MDNode *> aliasScopeMetadataMapping;
332 
333   /// Stack of user-specified state elements, useful when translating operations
334   /// with regions.
335   SmallVector<std::unique_ptr<StackFrame>> stack;
336 };
337 
338 namespace detail {
339 /// For all blocks in the region that were converted to LLVM IR using the given
340 /// ModuleTranslation, connect the PHI nodes of the corresponding LLVM IR blocks
341 /// to the results of preceding blocks.
342 void connectPHINodes(Region &region, const ModuleTranslation &state);
343 
344 /// Get a topologically sorted list of blocks of the given region.
345 SetVector<Block *> getTopologicallySortedBlocks(Region &region);
346 
347 /// Create an LLVM IR constant of `llvmType` from the MLIR attribute `attr`.
348 /// This currently supports integer, floating point, splat and dense element
349 /// attributes and combinations thereof. Also, an array attribute with two
350 /// elements is supported to represent a complex constant.  In case of error,
351 /// report it to `loc` and return nullptr.
352 llvm::Constant *getLLVMConstant(llvm::Type *llvmType, Attribute attr,
353                                 Location loc,
354                                 const ModuleTranslation &moduleTranslation);
355 
356 /// Creates a call to an LLVM IR intrinsic function with the given arguments.
357 llvm::Value *createIntrinsicCall(llvm::IRBuilderBase &builder,
358                                  llvm::Intrinsic::ID intrinsic,
359                                  ArrayRef<llvm::Value *> args = {},
360                                  ArrayRef<llvm::Type *> tys = {});
361 } // namespace detail
362 
363 } // namespace LLVM
364 } // namespace mlir
365 
366 namespace llvm {
367 template <typename T>
368 struct isa_impl<T, ::mlir::LLVM::ModuleTranslation::StackFrame> {
369   static inline bool
370   doit(const ::mlir::LLVM::ModuleTranslation::StackFrame &frame) {
371     return frame.getTypeID() == ::mlir::TypeID::get<T>();
372   }
373 };
374 } // namespace llvm
375 
376 #endif // MLIR_TARGET_LLVMIR_MODULETRANSLATION_H
377