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