20 #include "llvm/IR/ConstantRange.h"
21 #include "llvm/IR/IRBuilder.h"
22 #include "llvm/IR/IntrinsicsAMDGPU.h"
23 #include "llvm/Support/raw_ostream.h"
32 auto *inst = llvm::cast<llvm::CallInst>(
35 llvm::ConstantRange
Range(APInt(32, maybeRange[0]),
36 APInt(32, maybeRange[1]));
37 inst->addRangeRetAttr(
Range);
47 StringRef fnName,
int parameter) {
48 llvm::Module *module = builder.GetInsertBlock()->getModule();
50 llvm::Type::getInt64Ty(module->getContext()),
51 llvm::Type::getInt32Ty(module->getContext()),
53 llvm::Function *fn = dyn_cast<llvm::Function>(
54 module->getOrInsertFunction(fnName, functionType).getCallee());
56 llvm::Type::getInt32Ty(module->getContext()), parameter);
63 class ROCDLDialectLLVMIRTranslationInterface
71 convertOperation(
Operation *op, llvm::IRBuilderBase &builder,
74 #include "mlir/Dialect/LLVMIR/ROCDLConversions.inc"
84 auto *dialect = dyn_cast<ROCDL::ROCDLDialect>(attribute.getNameDialect());
85 if (dialect->getKernelAttrHelper().getName() == attribute.getName()) {
86 auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
89 " is only supported on `llvm.func` operations");
96 llvm::Function *llvmFunc =
97 moduleTranslation.lookupFunction(func.getName());
98 llvmFunc->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
99 if (!llvmFunc->hasFnAttribute(
"amdgpu-flat-work-group-size")) {
100 llvmFunc->addFnAttr(
"amdgpu-flat-work-group-size",
"1,256");
107 if (!llvmFunc->hasFnAttribute(
"uniform-work-group-size"))
108 llvmFunc->addFnAttr(
"uniform-work-group-size",
"true");
113 if (dialect->getMaxFlatWorkGroupSizeAttrHelper().getName() ==
114 attribute.getName()) {
115 auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
117 return op->
emitOpError(Twine(attribute.getName()) +
118 " is only supported on `llvm.func` operations");
119 auto value = dyn_cast<IntegerAttr>(attribute.getValue());
121 return op->
emitOpError(Twine(attribute.getName()) +
122 " must be an integer");
124 llvm::Function *llvmFunc =
125 moduleTranslation.lookupFunction(func.getName());
127 llvm::raw_svector_ostream attrValueStream(llvmAttrValue);
128 attrValueStream <<
"1," << value.getInt();
129 llvmFunc->addFnAttr(
"amdgpu-flat-work-group-size", llvmAttrValue);
131 if (dialect->getWavesPerEuAttrHelper().getName() == attribute.getName()) {
132 auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
134 return op->
emitOpError(Twine(attribute.getName()) +
135 " is only supported on `llvm.func` operations");
136 auto value = dyn_cast<IntegerAttr>(attribute.getValue());
138 return op->
emitOpError(Twine(attribute.getName()) +
139 " must be an integer");
141 llvm::Function *llvmFunc =
142 moduleTranslation.lookupFunction(func.getName());
144 llvm::raw_svector_ostream attrValueStream(llvmAttrValue);
145 attrValueStream << value.getInt();
146 llvmFunc->addFnAttr(
"amdgpu-waves-per-eu", llvmAttrValue);
148 if (dialect->getFlatWorkGroupSizeAttrHelper().getName() ==
149 attribute.getName()) {
150 auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
152 return op->
emitOpError(Twine(attribute.getName()) +
153 " is only supported on `llvm.func` operations");
154 auto value = dyn_cast<StringAttr>(attribute.getValue());
156 return op->
emitOpError(Twine(attribute.getName()) +
157 " must be a string");
159 llvm::Function *llvmFunc =
160 moduleTranslation.lookupFunction(func.getName());
162 llvmAttrValue.append(value.getValue());
163 llvmFunc->addFnAttr(
"amdgpu-flat-work-group-size", llvmAttrValue);
165 if (ROCDL::ROCDLDialect::getUniformWorkGroupSizeAttrName() ==
166 attribute.getName()) {
167 auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
169 return op->
emitOpError(Twine(attribute.getName()) +
170 " is only supported on `llvm.func` operations");
171 auto value = dyn_cast<BoolAttr>(attribute.getValue());
173 return op->
emitOpError(Twine(attribute.getName()) +
174 " must be a boolean");
175 llvm::Function *llvmFunc =
176 moduleTranslation.lookupFunction(func.getName());
177 llvmFunc->addFnAttr(
"uniform-work-group-size",
178 value.getValue() ?
"true" :
"false");
180 if (dialect->getUnsafeFpAtomicsAttrHelper().getName() ==
181 attribute.getName()) {
182 auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
184 return op->
emitOpError(Twine(attribute.getName()) +
185 " is only supported on `llvm.func` operations");
186 auto value = dyn_cast<BoolAttr>(attribute.getValue());
188 return op->
emitOpError(Twine(attribute.getName()) +
189 " must be a boolean");
190 llvm::Function *llvmFunc =
191 moduleTranslation.lookupFunction(func.getName());
192 llvmFunc->addFnAttr(
"amdgpu-unsafe-fp-atomics",
193 value.getValue() ?
"true" :
"false");
196 if (dialect->getReqdWorkGroupSizeAttrHelper().getName() ==
197 attribute.getName()) {
198 auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
200 return op->
emitOpError(Twine(attribute.getName()) +
201 " is only supported on `llvm.func` operations");
202 auto value = dyn_cast<DenseI32ArrayAttr>(attribute.getValue());
204 return op->
emitOpError(Twine(attribute.getName()) +
205 " must be a dense i32 array attribute");
206 llvm::LLVMContext &llvmContext = moduleTranslation.getLLVMContext();
209 for (int32_t i : value.asArrayRef()) {
213 llvm::Function *llvmFunc =
214 moduleTranslation.lookupFunction(func.getName());
216 llvmFunc->setMetadata(
"reqd_work_group_size", node);
224 registry.
insert<ROCDL::ROCDLDialect>();
226 dialect->addInterfaces<ROCDLDialectLLVMIRTranslationInterface>();
static llvm::Value * createDeviceFunctionCall(llvm::IRBuilderBase &builder, StringRef fnName, int parameter)
static llvm::Value * createIntrinsicCallWithRange(llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic, DenseI32ArrayAttr maybeRange)
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
Base class for dialect interfaces providing translation to LLVM IR.
LLVMTranslationDialectInterface(Dialect *dialect)
Implementation class for module translation.
MLIRContext is the top-level object for a collection of MLIR operations.
void appendDialectRegistry(const DialectRegistry ®istry)
Append the contents of the given dialect registry to the registry associated with this context.
NamedAttribute represents a combination of a name and an Attribute value.
Operation is the basic unit of execution within MLIR.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
llvm::CallInst * createIntrinsicCall(llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic, ArrayRef< llvm::Value * > args={}, ArrayRef< llvm::Type * > tys={})
Creates a call to an LLVM IR intrinsic function with the given arguments.
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
void registerROCDLDialectTranslation(DialectRegistry ®istry)
Register the ROCDL dialect and the translation from it to the LLVM IR in the given registry;.
Represents a range (offset, size, and stride) where each element of the triple may be dynamic or stat...