1 //===- NVVMToLLVMIRTranslation.cpp - Translate NVVM to LLVM IR ------------===//
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 a translation between the MLIR NVVM dialect and
10 // LLVM IR.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h"
15 #include "mlir/Dialect/LLVMIR/NVVMDialect.h"
16 #include "mlir/IR/Operation.h"
17 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
18 
19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/IR/IntrinsicsNVPTX.h"
21 
22 using namespace mlir;
23 using namespace mlir::LLVM;
24 using mlir::LLVM::detail::createIntrinsicCall;
25 
26 static llvm::Intrinsic::ID getShflBflyIntrinsicId(llvm::Type *resultType,
27                                                   bool withPredicate) {
28   if (withPredicate) {
29     resultType = cast<llvm::StructType>(resultType)->getElementType(0);
30     return resultType->isFloatTy() ? llvm::Intrinsic::nvvm_shfl_sync_bfly_f32p
31                                    : llvm::Intrinsic::nvvm_shfl_sync_bfly_i32p;
32   }
33   return resultType->isFloatTy() ? llvm::Intrinsic::nvvm_shfl_sync_bfly_f32
34                                  : llvm::Intrinsic::nvvm_shfl_sync_bfly_i32;
35 }
36 
37 namespace {
38 /// Implementation of the dialect interface that converts operations belonging
39 /// to the NVVM dialect to LLVM IR.
40 class NVVMDialectLLVMIRTranslationInterface
41     : public LLVMTranslationDialectInterface {
42 public:
43   using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
44 
45   /// Translates the given operation to LLVM IR using the provided IR builder
46   /// and saving the state in `moduleTranslation`.
47   LogicalResult
48   convertOperation(Operation *op, llvm::IRBuilderBase &builder,
49                    LLVM::ModuleTranslation &moduleTranslation) const final {
50     Operation &opInst = *op;
51 #include "mlir/Dialect/LLVMIR/NVVMConversions.inc"
52 
53     return failure();
54   }
55 
56   /// Attaches module-level metadata for functions marked as kernels.
57   LogicalResult
58   amendOperation(Operation *op, NamedAttribute attribute,
59                  LLVM::ModuleTranslation &moduleTranslation) const final {
60     if (attribute.first == NVVM::NVVMDialect::getKernelFuncAttrName()) {
61       auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
62       if (!func)
63         return failure();
64 
65       llvm::LLVMContext &llvmContext = moduleTranslation.getLLVMContext();
66       llvm::Function *llvmFunc =
67           moduleTranslation.lookupFunction(func.getName());
68       llvm::Metadata *llvmMetadata[] = {
69           llvm::ValueAsMetadata::get(llvmFunc),
70           llvm::MDString::get(llvmContext, "kernel"),
71           llvm::ValueAsMetadata::get(
72               llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvmContext), 1))};
73       llvm::MDNode *llvmMetadataNode =
74           llvm::MDNode::get(llvmContext, llvmMetadata);
75       moduleTranslation.getOrInsertNamedModuleMetadata("nvvm.annotations")
76           ->addOperand(llvmMetadataNode);
77     }
78     return success();
79   }
80 };
81 } // end namespace
82 
83 void mlir::registerNVVMDialectTranslation(DialectRegistry &registry) {
84   registry.insert<NVVM::NVVMDialect>();
85   registry.addDialectInterface<NVVM::NVVMDialect,
86                                NVVMDialectLLVMIRTranslationInterface>();
87 }
88 
89 void mlir::registerNVVMDialectTranslation(MLIRContext &context) {
90   DialectRegistry registry;
91   registerNVVMDialectTranslation(registry);
92   context.appendDialectRegistry(registry);
93 }
94