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 ®ion); 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 ®ion, const ModuleTranslation &state); 343 344 /// Get a topologically sorted list of blocks of the given region. 345 SetVector<Block *> getTopologicallySortedBlocks(Region ®ion); 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