1 //===- ROCDLToLLVMIRTranslation.cpp - Translate ROCDL 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 ROCDL dialect and 10 // LLVM IR. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h" 15 #include "mlir/Dialect/LLVMIR/ROCDLDialect.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/IntrinsicsAMDGPU.h" 21 22 using namespace mlir; 23 using namespace mlir::LLVM; 24 using mlir::LLVM::detail::createIntrinsicCall; 25 26 // Create a call to ROCm-Device-Library function 27 // Currently this routine will work only for calling ROCDL functions that 28 // take a single int32 argument. It is likely that the interface of this 29 // function will change to make it more generic. 30 static llvm::Value *createDeviceFunctionCall(llvm::IRBuilderBase &builder, 31 StringRef fn_name, int parameter) { 32 llvm::Module *module = builder.GetInsertBlock()->getModule(); 33 llvm::FunctionType *function_type = llvm::FunctionType::get( 34 llvm::Type::getInt64Ty(module->getContext()), // return type. 35 llvm::Type::getInt32Ty(module->getContext()), // parameter type. 36 false); // no variadic arguments. 37 llvm::Function *fn = dyn_cast<llvm::Function>( 38 module->getOrInsertFunction(fn_name, function_type).getCallee()); 39 llvm::Value *fn_op0 = llvm::ConstantInt::get( 40 llvm::Type::getInt32Ty(module->getContext()), parameter); 41 return builder.CreateCall(fn, ArrayRef<llvm::Value *>(fn_op0)); 42 } 43 44 namespace { 45 /// Implementation of the dialect interface that converts operations belonging 46 /// to the ROCDL dialect to LLVM IR. 47 class ROCDLDialectLLVMIRTranslationInterface 48 : public LLVMTranslationDialectInterface { 49 public: 50 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface; 51 52 /// Translates the given operation to LLVM IR using the provided IR builder 53 /// and saving the state in `moduleTranslation`. 54 LogicalResult 55 convertOperation(Operation *op, llvm::IRBuilderBase &builder, 56 LLVM::ModuleTranslation &moduleTranslation) const final { 57 Operation &opInst = *op; 58 #include "mlir/Dialect/LLVMIR/ROCDLConversions.inc" 59 60 return failure(); 61 } 62 63 /// Attaches module-level metadata for functions marked as kernels. 64 LogicalResult 65 amendOperation(Operation *op, NamedAttribute attribute, 66 LLVM::ModuleTranslation &moduleTranslation) const final { 67 if (attribute.first == ROCDL::ROCDLDialect::getKernelFuncAttrName()) { 68 auto func = dyn_cast<LLVM::LLVMFuncOp>(op); 69 if (!func) 70 return failure(); 71 72 // For GPU kernels, 73 // 1. Insert AMDGPU_KERNEL calling convention. 74 // 2. Insert amdgpu-flat-workgroup-size(1, 1024) attribute. 75 llvm::Function *llvmFunc = 76 moduleTranslation.lookupFunction(func.getName()); 77 llvmFunc->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); 78 llvmFunc->addFnAttr("amdgpu-flat-work-group-size", "1, 1024"); 79 } 80 return success(); 81 } 82 }; 83 } // end namespace 84 85 void mlir::registerROCDLDialectTranslation(DialectRegistry ®istry) { 86 registry.insert<ROCDL::ROCDLDialect>(); 87 registry.addDialectInterface<ROCDL::ROCDLDialect, 88 ROCDLDialectLLVMIRTranslationInterface>(); 89 } 90 91 void mlir::registerROCDLDialectTranslation(MLIRContext &context) { 92 DialectRegistry registry; 93 registerROCDLDialectTranslation(registry); 94 context.appendDialectRegistry(registry); 95 } 96