//===-- CompilationAttrs.td - GPU compilation attributes ---*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines GPU compilation related attributes. // //===----------------------------------------------------------------------===// #ifndef GPU_COMPILATION_ATTRS #define GPU_COMPILATION_ATTRS include "mlir/Dialect/GPU/IR/GPUBase.td" include "mlir/Dialect/GPU/IR/CompilationAttrInterfaces.td" //===----------------------------------------------------------------------===// // GPU kernel metadata attribute //===----------------------------------------------------------------------===// def GPU_KernelMetadataAttr : GPU_Attr<"KernelMetadata", "kernel_metadata"> { let description = [{ GPU attribute for storing metadata related to a compiled kernel. The attribute contains the name and arguments type of the kernel. The attribute also contains optional parameters for storing the arguments attributes as well as a dictionary for additional metadata, like occupancy information or other function attributes. Note: The `arg_attrs` parameter is expected to follow all the constraints imposed by the `mlir::FunctionOpInterface` interface. Examples: ```mlir #gpu.kernel_metadata<@kernel1, (i32) -> (), arg_attrs = [...], metadata = {reg_count = 255, ...}> #gpu.kernel_metadata<@kernel2, (i32, f64) -> ()> ``` }]; let parameters = (ins "StringAttr":$name, "Type":$function_type, OptionalParameter<"ArrayAttr", "arguments attributes">:$arg_attrs, OptionalParameter<"DictionaryAttr", "metadata dictionary">:$metadata ); let assemblyFormat = [{ `<` $name `,` $function_type (`,` struct($arg_attrs, $metadata)^)? `>` }]; let builders = [ AttrBuilderWithInferredContext<(ins "StringAttr":$name, "Type":$functionType, CArg<"ArrayAttr", "nullptr">:$argAttrs, CArg<"DictionaryAttr", "nullptr">:$metadata), [{ assert(name && "invalid name"); return $_get(name.getContext(), name, functionType, argAttrs, metadata); }]>, AttrBuilderWithInferredContext<(ins "FunctionOpInterface":$kernel, CArg<"DictionaryAttr", "nullptr">:$metadata)> ]; let genVerifyDecl = 1; let extraClassDeclaration = [{ /// Compare two kernels based on the name. bool operator<(const KernelMetadataAttr& other) const { return getName().getValue() < other.getName().getValue(); } /// Returns the metadata attribute corresponding to `key` or `nullptr` /// if missing. Attribute getAttr(StringRef key) const { DictionaryAttr attrs = getMetadata(); return attrs ? attrs.get(key) : nullptr; } template ConcreteAttr getAttr(StringRef key) const { return llvm::dyn_cast_or_null(getAttr(key)); } Attribute getAttr(StringAttr key) const { DictionaryAttr attrs = getMetadata(); return attrs ? attrs.get(key) : nullptr; } template ConcreteAttr getAttr(StringAttr key) const { return llvm::dyn_cast_or_null(getAttr(key)); } /// Returns the attribute dictionary at position `index`. DictionaryAttr getArgAttrDict(unsigned index) { ArrayAttr argArray = getArgAttrs(); return argArray ? llvm::cast(argArray[index]) : nullptr; } /// Return the specified attribute, if present, for the argument at 'index', /// null otherwise. Attribute getArgAttr(unsigned index, StringAttr name) { DictionaryAttr argDict = getArgAttrDict(index); return argDict ? argDict.get(name) : nullptr; } Attribute getArgAttr(unsigned index, StringRef name) { DictionaryAttr argDict = getArgAttrDict(index); return argDict ? argDict.get(name) : nullptr; } /// Returns a new KernelMetadataAttr that contains `attrs` in the metadata dictionary. KernelMetadataAttr appendMetadata(ArrayRef attrs) const; }]; } //===----------------------------------------------------------------------===// // GPU kernel table attribute //===----------------------------------------------------------------------===// def GPU_KernelTableAttr : GPU_Attr<"KernelTable", "kernel_table"> { let description = [{ GPU attribute representing a list of `#gpu.kernel_metadata` attributes. This attribute supports searching kernels by name. All kernels in the table must have an unique name. Examples: ```mlir // Empty table. #gpu.kernel_table<> // Table with a single kernel. #gpu.kernel_table<[#gpu.kernel_metadata () >]> // Table with multiple kernels. #gpu.kernel_table<[ #gpu.kernel_metadata<"kernel0", (i32, f32) -> (), metadata = {sgpr_count = 255}>, #gpu.kernel_metadata<"kernel1", (i32) -> ()> ]> ``` }]; let parameters = (ins OptionalArrayRefParameter<"KernelMetadataAttr", "array of kernels">:$kernel_table ); let assemblyFormat = [{ `<` (`[` qualified($kernel_table)^ `]`)? `>` }]; let builders = [ AttrBuilder<(ins "ArrayRef":$kernels, CArg<"bool", "false">:$isSorted)> ]; let skipDefaultBuilders = 1; let genVerifyDecl = 1; let extraClassDeclaration = [{ llvm::ArrayRef::iterator begin() const { return getKernelTable().begin(); } llvm::ArrayRef::iterator end() const { return getKernelTable().end(); } size_t size() const { return getKernelTable().size(); } bool empty() const { return getKernelTable().empty(); } /// Returns the kernel with name `key` or `nullptr` if not present. KernelMetadataAttr lookup(StringRef key) const; KernelMetadataAttr lookup(StringAttr key) const; }]; } //===----------------------------------------------------------------------===// // GPU object attribute. //===----------------------------------------------------------------------===// // For documentation on this enum cases, see the `GPU_ObjectAttr` docs. def GPU_ObjectOffload : I32EnumAttrCase<"Offload", 1, "offload">; def GPU_ObjectISA : I32EnumAttrCase<"Assembly", 2, "assembly">; def GPU_ObjectBinary : I32EnumAttrCase<"Binary", 3, "bin">; def GPU_ObjectFatbin : I32EnumAttrCase<"Fatbin", 4, "fatbin">; def GPU_CompilationTargetEnum : GPU_I32Enum< "CompilationTarget", "GPU compilation format", [ GPU_ObjectOffload, GPU_ObjectISA, GPU_ObjectBinary, GPU_ObjectFatbin ]>; def GPU_ObjectAttr : GPU_Attr<"Object", "object"> { let description = [{ A GPU object attribute glues together a GPU target, the object kind, a binary string with the object, the object properties, and kernel metadata, encapsulating how the object was generated and its properties with the object itself. There are four object formats: 1. `Offload`: represents generic objects not described by the other three formats, and its meaning is target-dependent. For example, on the NVPTX and AMDGPU targets, this format is associated with LLVM bitcode. 2. `Assembly`: represents GPU assembly code. For example, in the NVPTX target, assembly is PTX code, which can be JITted at runtime. 3. `Binary`: represents executable code for a GPU single architecture. For example, PTX code that was compiled for a specific compute capability. Note that this format is likely to throw an error if there is an architecture mismatch between the compiled and running architecture. 4. `Fatbin`: represents a GPU fat binary with executable code for multiple architectures. This format is the default; thus, it gets elided inassembly code. Object properties are specified through the `properties` dictionary attribute and can be used to define additional information. Kernel metadata is specified through the `kernels` parameter, and can be used to specify additional information on a kernel by kernel basis. The target attribute must implement or promise the `TargetAttrInterface` interface. ``` #gpu.object<#rocdl.target, offload = "..."> // An offload object. #gpu.object<#nvvm.target, properties = {O = 3 : i32}, assembly = "..."> // An assembly object with additional properties. #gpu.object<#rocdl.target, bin = "..."> // A binary object. #gpu.object<#nvvm.target, "..."> // A fatbin object. #gpu.object<#nvvm.target, kernels = #gpu.kernel_table<...>, "..."> // An object with a kernel table. ``` }]; let parameters = (ins "Attribute":$target, DefaultValuedParameter<"CompilationTarget", "CompilationTarget::Fatbin">:$format, "StringAttr":$object, OptionalParameter<"DictionaryAttr">:$properties, OptionalParameter<"KernelTableAttr">:$kernels ); let builders = [ AttrBuilderWithInferredContext<(ins "Attribute":$target, "CompilationTarget":$format, "StringAttr":$object, CArg<"DictionaryAttr", "nullptr">:$properties, CArg<"KernelTableAttr", "nullptr">:$kernels), [{ assert(target && "invalid target"); return $_get(target.getContext(), target, format, object, properties, kernels); }]> ]; let assemblyFormat = [{ `<` $target `,` (`properties` `=` $properties^ `,`)? (`kernels` `=` $kernels^ `,`)? custom($format, $object) `>` }]; let genVerifyDecl = 1; } def GPUObjectArrayAttr : TypedArrayAttrBase; //===----------------------------------------------------------------------===// // GPU offloading LLVM translation handler attributes. //===----------------------------------------------------------------------===// def GPU_SelectObjectAttr : GPU_Attr<"SelectObject", "select_object", [ OffloadingTranslationAttrTrait ]> { let description = [{ This GPU offloading handler selects a single GPU object for embedding. The object is selected based on the `target` parameter, this parameter can be either a number -i.e. selects the ith-target, or the target itself -i.e. searches for the specified target in the object array. The first object in a `gpu.binary` operation is selected if no target is specified. }]; let parameters = (ins OptionalParameter<"Attribute", "Target to select for embedding.">:$target ); let assemblyFormat = [{ (`<` $target^ `>`)? }]; let genVerifyDecl = 1; } #endif // GPU_COMPILATION_ATTRS