blob: c0dbc59399adb6a5496a2aad338c44d2ce3a4cb1 [file]
// Copyright 2024 The IREE Authors
//
// Licensed 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
#ifndef IREE_DIALECT_HAL_IR_HAL_ATTRS
#define IREE_DIALECT_HAL_IR_HAL_ATTRS
include "iree/compiler/Dialect/HAL/IR/HALBase.td"
include "iree/compiler/Dialect/HAL/IR/HALInterfaces.td"
include "iree/compiler/Dialect/Stream/IR/StreamInterfaces.td"
include "iree/compiler/Dialect/Util/IR/UtilInterfaces.td"
include "iree/compiler/Dialect/Util/IR/UtilTypes.td"
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/EnumAttr.td"
//===----------------------------------------------------------------------===//
// General enums
//===----------------------------------------------------------------------===//
// Wrapper over base I32EnumAttr to set common fields for HAL enums.
class HAL_I32Enum<string name, string description, list<I32EnumAttrCase> cases>
: I32EnumAttr<name, description, cases> {
let genSpecializedAttr = 0;
let cppNamespace = "::mlir::iree_compiler::IREE::HAL";
}
class HAL_I32EnumAttr<string name, string description, string mnemonic,
list<I32EnumAttrCase> cases>
: EnumAttr<HAL_Dialect, HAL_I32Enum<name, description, cases>, mnemonic> {
let assemblyFormat = "`<` $value `>`";
}
def HAL_MemoryModel_Unified : I32EnumAttrCase<"Unified", 0>;
def HAL_MemoryModel_Discrete : I32EnumAttrCase<"Discrete", 1>;
def HAL_MemoryModelAttr :
I32EnumAttr<"MemoryModel", "IREE HAL MemoryModel", [
HAL_MemoryModel_Unified,
HAL_MemoryModel_Discrete,
]> {
let cppNamespace = "::mlir::iree_compiler::IREE::HAL";
}
def HAL_MemoryType_None : I32BitEnumAttrCase<"None", 0x0000>; // ?
def HAL_MemoryType_Optimal : I32BitEnumAttrCase<"Optimal", 0x0001>; // !
def HAL_MemoryType_HostVisible : I32BitEnumAttrCase<"HostVisible", 0x0002>; // h
def HAL_MemoryType_HostCoherent : I32BitEnumAttrCase<"HostCoherent", 0x0004>; // c
def HAL_MemoryType_HostCached : I32BitEnumAttrCase<"HostCached", 0x0008>; // C
def HAL_MemoryType_HostLocal : I32BitEnumAttrCase<"HostLocal", 0x0046>; // H
def HAL_MemoryType_DeviceVisible : I32BitEnumAttrCase<"DeviceVisible", 0x0010>; // d
def HAL_MemoryType_DeviceLocal : I32BitEnumAttrCase<"DeviceLocal", 0x0030>; // D
def HAL_MemoryTypeBitfieldAttr :
I32BitEnumAttr<"MemoryTypeBitfield", "valid MemoryType", [
HAL_MemoryType_None,
HAL_MemoryType_Optimal,
HAL_MemoryType_HostVisible,
HAL_MemoryType_HostCoherent,
HAL_MemoryType_HostCached,
HAL_MemoryType_HostLocal,
HAL_MemoryType_DeviceVisible,
HAL_MemoryType_DeviceLocal,
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_MemoryAccess_None : I32BitEnumAttrCase<"None", 0x00000000>;
def HAL_MemoryAccess_Read : I32BitEnumAttrCase<"Read", 0x00000001>;
def HAL_MemoryAccess_Write : I32BitEnumAttrCase<"Write", 0x00000002>;
def HAL_MemoryAccess_Discard : I32BitEnumAttrCase<"Discard", 0x00000004>;
def HAL_MemoryAccess_MayAlias : I32BitEnumAttrCase<"MayAlias", 0x00000008>;
def HAL_MemoryAccess_Unaligned : I32BitEnumAttrCase<"Unaligned", 0x00000010>;
def HAL_MemoryAccess_Any : I32BitEnumAttrCase<"Any", 0x00000020>;
def HAL_MemoryAccessBitfieldAttr :
I32BitEnumAttr<"MemoryAccessBitfield", "valid MemoryAccess", [
HAL_MemoryAccess_None,
HAL_MemoryAccess_Read,
HAL_MemoryAccess_Write,
HAL_MemoryAccess_Discard,
HAL_MemoryAccess_MayAlias,
HAL_MemoryAccess_Unaligned,
HAL_MemoryAccess_Any,
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_BufferUsage_None : I32BitEnumAttrCase<"None", 0x00000000>;
def HAL_BufferUsage_TransferSource : I32BitEnumAttrCase<"TransferSource", 0x00000001>;
def HAL_BufferUsage_TransferTarget : I32BitEnumAttrCase<"TransferTarget", 0x00000002>;
def HAL_BufferUsage_Transfer : I32BitEnumAttrCase<"Transfer", 0x00000003>;
def HAL_BufferUsage_DispatchIndirectParams : I32BitEnumAttrCase<"DispatchIndirectParams", 0x00000100>;
def HAL_BufferUsage_DispatchUniformRead : I32BitEnumAttrCase<"DispatchUniformRead", 0x00000200>;
def HAL_BufferUsage_DispatchStorageRead : I32BitEnumAttrCase<"DispatchStorageRead", 0x00000400>;
def HAL_BufferUsage_DispatchStorageWrite : I32BitEnumAttrCase<"DispatchStorageWrite", 0x00000800>;
def HAL_BufferUsage_DispatchStorage : I32BitEnumAttrCase<"DispatchStorage", 0x00000C00>;
def HAL_BufferUsage_DispatchImageRead : I32BitEnumAttrCase<"DispatchImageRead", 0x00001000>;
def HAL_BufferUsage_DispatchImageWrite : I32BitEnumAttrCase<"DispatchImageWrite", 0x00002000>;
def HAL_BufferUsage_DispatchImage : I32BitEnumAttrCase<"DispatchImage", 0x00003000>;
def HAL_BufferUsage_SharingExport : I32BitEnumAttrCase<"SharingExport", 0x00010000>;
def HAL_BufferUsage_SharingReplicate : I32BitEnumAttrCase<"SharingReplicate", 0x00020000>;
def HAL_BufferUsage_SharingConcurrent : I32BitEnumAttrCase<"SharingConcurrent", 0x00040000>;
def HAL_BufferUsage_SharingImmutable : I32BitEnumAttrCase<"SharingImmutable", 0x00080000>;
def HAL_BufferUsage_MappingScoped : I32BitEnumAttrCase<"MappingScoped", 0x01000000>;
def HAL_BufferUsage_MappingPersistent : I32BitEnumAttrCase<"MappingPersistent", 0x02000000>;
def HAL_BufferUsage_MappingOptional : I32BitEnumAttrCase<"MappingOptional", 0x04000000>;
def HAL_BufferUsage_MappingAccessRandom : I32BitEnumAttrCase<"MappingAccessRandom", 0x08000000>;
def HAL_BufferUsage_MappingAccessSequentialWrite : I32BitEnumAttrCase<"MappingAccessSequentialWrite", 0x10000000>;
def HAL_BufferUsage_Mapping : I32BitEnumAttrCase<"Mapping", 0x09000000>;
def HAL_BufferUsageBitfieldAttr :
I32BitEnumAttr<"BufferUsageBitfield", "valid BufferUsage", [
HAL_BufferUsage_None,
HAL_BufferUsage_TransferSource,
HAL_BufferUsage_TransferTarget,
HAL_BufferUsage_Transfer,
HAL_BufferUsage_DispatchIndirectParams,
HAL_BufferUsage_DispatchUniformRead,
HAL_BufferUsage_DispatchStorageRead,
HAL_BufferUsage_DispatchStorageWrite,
HAL_BufferUsage_DispatchStorage,
HAL_BufferUsage_DispatchImageRead,
HAL_BufferUsage_DispatchImageWrite,
HAL_BufferUsage_DispatchImage,
HAL_BufferUsage_SharingExport,
HAL_BufferUsage_SharingReplicate,
HAL_BufferUsage_SharingConcurrent,
HAL_BufferUsage_SharingImmutable,
HAL_BufferUsage_MappingScoped,
HAL_BufferUsage_MappingPersistent,
HAL_BufferUsage_MappingOptional,
HAL_BufferUsage_MappingAccessRandom,
HAL_BufferUsage_MappingAccessSequentialWrite,
HAL_BufferUsage_Mapping,
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_CommandBufferMode_None : I32BitEnumAttrCase<"None", 0x0000>;
def HAL_CommandBufferMode_OneShot : I32BitEnumAttrCase<"OneShot", 0x0001>;
def HAL_CommandBufferMode_AllowInlineExecution : I32BitEnumAttrCase<"AllowInlineExecution", 0x0010>;
def HAL_CommandBufferModeBitfieldAttr :
I32BitEnumAttr<"CommandBufferModeBitfield", "valid CommandBufferMode", [
HAL_CommandBufferMode_None,
HAL_CommandBufferMode_OneShot,
HAL_CommandBufferMode_AllowInlineExecution,
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_CommandCategory_None : I32BitEnumAttrCase<"None", 0x0000>;
def HAL_CommandCategory_Transfer : I32BitEnumAttrCase<"Transfer", 0x0001>;
def HAL_CommandCategory_Dispatch : I32BitEnumAttrCase<"Dispatch", 0x0002>;
def HAL_CommandCategoryBitfieldAttr :
I32BitEnumAttr<"CommandCategoryBitfield", "valid CommandCategory", [
HAL_CommandCategory_None,
HAL_CommandCategory_Transfer,
HAL_CommandCategory_Dispatch,
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_DescriptorType_UniformBuffer : I32EnumAttrCase<"UniformBuffer", 6, "uniform_buffer">;
def HAL_DescriptorType_StorageBuffer : I32EnumAttrCase<"StorageBuffer", 7, "storage_buffer">;
def HAL_DescriptorTypeAttr :
HAL_I32EnumAttr<"DescriptorType", "valid DescriptorType", "descriptor_type", [
HAL_DescriptorType_UniformBuffer,
HAL_DescriptorType_StorageBuffer,
]>;
def HAL_DescriptorFlags_None : I32BitEnumAttrCase<"None", 0x0000>;
def HAL_DescriptorFlags_ReadOnly : I32BitEnumAttrCase<"ReadOnly", 0x0001>;
def HAL_DescriptorFlags_Indirect : I32BitEnumAttrCase<"Indirect", 0x0002>;
def HAL_DescriptorFlagsAttr :
I32BitEnumAttr<"DescriptorFlags", "valid Descriptor flags", [
HAL_DescriptorFlags_None,
HAL_DescriptorFlags_ReadOnly,
HAL_DescriptorFlags_Indirect,
]> {
let cppNamespace = "::mlir::iree_compiler::IREE::HAL";
}
def HAL_PipelineLayoutFlags_None : I32BitEnumAttrCase<"None", 0x0000>;
def HAL_PipelineLayoutFlags_Indirect : I32BitEnumAttrCase<"Indirect", 0x0001>;
def HAL_PipelineLayoutFlagsAttr :
I32BitEnumAttr<"PipelineLayoutFlags", "valid PipelineLayout flags", [
HAL_PipelineLayoutFlags_None,
HAL_PipelineLayoutFlags_Indirect,
]> {
let cppNamespace = "::mlir::iree_compiler::IREE::HAL";
}
def HAL_DispatchFlags_None : I64BitEnumAttrCase<"None", 0x0000>;
// HACK: workaround tblgen bug on enums that only have a None value. This can be
// repurposed for any use in the future as the runtime does not know about it.
def HAL_DispatchFlags_Reserved : I64BitEnumAttrCase<"Reserved", 0x0001>;
def HAL_DispatchFlagsAttr :
I64BitEnumAttr<"DispatchFlags", "valid dispatch flags", [
HAL_DispatchFlags_None,
HAL_DispatchFlags_Reserved,
]> {
let cppNamespace = "::mlir::iree_compiler::IREE::HAL";
}
def HAL_ExecutionStage_None : I32BitEnumAttrCase<"None", 0x0000>;
def HAL_ExecutionStage_CommandIssue : I32BitEnumAttrCase<"CommandIssue", 0x0001>;
def HAL_ExecutionStage_CommandProcess : I32BitEnumAttrCase<"CommandProcess", 0x0002>;
def HAL_ExecutionStage_Dispatch : I32BitEnumAttrCase<"Dispatch", 0x0004>;
def HAL_ExecutionStage_Transfer : I32BitEnumAttrCase<"Transfer", 0x0008>;
def HAL_ExecutionStage_CommandRetire : I32BitEnumAttrCase<"CommandRetire", 0x0010>;
def HAL_ExecutionStage_Host : I32BitEnumAttrCase<"Host", 0x0020>;
def HAL_ExecutionStageBitfieldAttr :
I32BitEnumAttr<"ExecutionStageBitfield", "valid ExecutionStage", [
HAL_ExecutionStage_None,
HAL_ExecutionStage_CommandIssue,
HAL_ExecutionStage_CommandProcess,
HAL_ExecutionStage_Dispatch,
HAL_ExecutionStage_Transfer,
HAL_ExecutionStage_CommandRetire,
HAL_ExecutionStage_Host
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_ExecutionBarrierFlag_None : I32BitEnumAttrCase<"None", 0x0000>;
def HAL_ExecutionBarrierFlag_Reserved : I32BitEnumAttrCase<"Reserved", 0x0001>;
def HAL_ExecutionBarrierFlagBitfieldAttr :
I32BitEnumAttr<"ExecutionBarrierFlagBitfield", "valid ExecutionBarrierFlag", [
HAL_ExecutionBarrierFlag_None,
HAL_ExecutionBarrierFlag_Reserved,
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_FenceFlag_None : I32BitEnumAttrCase<"None", 0x0000>;
def HAL_FenceFlag_Reserved : I32BitEnumAttrCase<"Reserved", 0x0001>;
def HAL_FenceFlagBitfieldAttr :
I32BitEnumAttr<"FenceFlagBitfield", "valid FenceFlag", [
HAL_FenceFlag_None,
HAL_FenceFlag_Reserved,
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_AccessScope_None : I32BitEnumAttrCase<"None", 0x0000>;
def HAL_AccessScope_IndirectCommandRead : I32BitEnumAttrCase<"IndirectCommandRead", 0x0001>;
def HAL_AccessScope_ConstantRead : I32BitEnumAttrCase<"ConstantRead", 0x0002>;
def HAL_AccessScope_DispatchRead : I32BitEnumAttrCase<"DispatchRead", 0x0004>;
def HAL_AccessScope_DispatchWrite : I32BitEnumAttrCase<"DispatchWrite", 0x0008>;
def HAL_AccessScope_TransferRead : I32BitEnumAttrCase<"TransferRead", 0x0010>;
def HAL_AccessScope_TransferWrite : I32BitEnumAttrCase<"TransferWrite", 0x0020>;
def HAL_AccessScope_HostRead : I32BitEnumAttrCase<"HostRead", 0x0040>;
def HAL_AccessScope_HostWrite : I32BitEnumAttrCase<"HostWrite", 0x0080>;
def HAL_AccessScope_MemoryRead : I32BitEnumAttrCase<"MemoryRead", 0x0100>;
def HAL_AccessScope_MemoryWrite : I32BitEnumAttrCase<"MemoryWrite", 0x0200>;
def HAL_AccessScopeBitfieldAttr :
I32BitEnumAttr<"AccessScopeBitfield", "valid AccessScope", [
HAL_AccessScope_None,
HAL_AccessScope_IndirectCommandRead,
HAL_AccessScope_ConstantRead,
HAL_AccessScope_DispatchRead,
HAL_AccessScope_DispatchWrite,
HAL_AccessScope_TransferRead,
HAL_AccessScope_TransferWrite,
HAL_AccessScope_HostRead,
HAL_AccessScope_HostWrite,
HAL_AccessScope_MemoryRead,
HAL_AccessScope_MemoryWrite
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_CallingConvention_Default : I32EnumAttrCase<"Default", 0>;
def HAL_CallingConventionAttr :
I32EnumAttr<
"CallingConvention",
"Calling conversions for linked functions",[
HAL_CallingConvention_Default,
]>{
let cppNamespace = "::mlir::iree_compiler::IREE::HAL";
}
//===----------------------------------------------------------------------===//
// #hal.collective<*>
//===----------------------------------------------------------------------===//
def HAL_CollectiveKind_AllGather : I32EnumAttrCase<"AllGather", 0, "all_gather">;
def HAL_CollectiveKind_AllReduce : I32EnumAttrCase<"AllReduce", 1, "all_reduce">;
def HAL_CollectiveKind_AllToAll : I32EnumAttrCase<"AllToAll", 2, "all_to_all">;
def HAL_CollectiveKind_Broadcast : I32EnumAttrCase<"Broadcast", 3, "broadcast">;
def HAL_CollectiveKind_Reduce : I32EnumAttrCase<"Reduce", 4, "reduce">;
def HAL_CollectiveKind_ReduceScatter : I32EnumAttrCase<"ReduceScatter", 5, "reduce_scatter">;
def HAL_CollectiveKind_Send : I32EnumAttrCase<"Send", 6, "send">;
def HAL_CollectiveKind_Recv : I32EnumAttrCase<"Recv", 7, "recv">;
def HAL_CollectiveKind_SendRecv: I32EnumAttrCase<"SendRecv", 8, "send_recv">;
def HAL_CollectiveKindAttr :
I32EnumAttr<"CollectiveKind", "valid CollectiveKind", [
HAL_CollectiveKind_AllGather,
HAL_CollectiveKind_AllReduce,
HAL_CollectiveKind_AllToAll,
HAL_CollectiveKind_Broadcast,
HAL_CollectiveKind_Reduce,
HAL_CollectiveKind_ReduceScatter,
HAL_CollectiveKind_Send,
HAL_CollectiveKind_Recv,
HAL_CollectiveKind_SendRecv,
]> {
let cppNamespace = "::mlir::iree_compiler::IREE::HAL";
}
def HAL_CollectiveReductionOp_None : I32EnumAttrCase<"None", 0, "none">;
def HAL_CollectiveReductionOp_ReductionSum : I32EnumAttrCase<"ReductionSum", 1, "sum">;
def HAL_CollectiveReductionOp_ReductionProduct : I32EnumAttrCase<"ReductionProduct", 2, "product">;
def HAL_CollectiveReductionOp_ReductionMinimum : I32EnumAttrCase<"ReductionMinimum", 3, "minimum">;
def HAL_CollectiveReductionOp_ReductionMaximum : I32EnumAttrCase<"ReductionMaximum", 4, "maximum">;
def HAL_CollectiveReductionOp_ReductionAverage : I32EnumAttrCase<"ReductionAverage", 5, "average">;
def HAL_CollectiveReductionOpAttr :
I32EnumAttr<"CollectiveReductionOp", "valid CollectiveReductionOp", [
HAL_CollectiveReductionOp_None,
HAL_CollectiveReductionOp_ReductionSum,
HAL_CollectiveReductionOp_ReductionProduct,
HAL_CollectiveReductionOp_ReductionMinimum,
HAL_CollectiveReductionOp_ReductionMaximum,
HAL_CollectiveReductionOp_ReductionAverage,
]> {
let cppNamespace = "mlir::iree_compiler::IREE::HAL";
}
def HAL_CollectiveElementType_Sint8 : I32EnumAttrCase<"Sint8", 0, "si8">;
def HAL_CollectiveElementType_Uint8 : I32EnumAttrCase<"Uint8", 1, "ui8">;
def HAL_CollectiveElementType_Sint16 : I32EnumAttrCase<"Sint16", 2, "si16">;
def HAL_CollectiveElementType_Uint16 : I32EnumAttrCase<"Uint16", 3, "ui16">;
def HAL_CollectiveElementType_Sint32 : I32EnumAttrCase<"Sint32", 4, "si32">;
def HAL_CollectiveElementType_Uint32 : I32EnumAttrCase<"Uint32", 5, "ui32">;
def HAL_CollectiveElementType_Sint64 : I32EnumAttrCase<"Sint64", 6, "si64">;
def HAL_CollectiveElementType_Uint64 : I32EnumAttrCase<"Uint64", 7, "ui64">;
def HAL_CollectiveElementType_Float16 : I32EnumAttrCase<"Float16", 8, "f16">;
def HAL_CollectiveElementType_Float32 : I32EnumAttrCase<"Float32", 9, "f32">;
def HAL_CollectiveElementType_Float64 : I32EnumAttrCase<"Float64", 10, "f64">;
def HAL_CollectiveElementType_BFloat16 : I32EnumAttrCase<"BFloat16", 11, "bf16">;
def HAL_CollectiveElementType_Float8E5M2 : I32EnumAttrCase<"Float8E5M2", 12, "f8E5M2">;
def HAL_CollectiveElementType_Float8E4M3 : I32EnumAttrCase<"Float8E4M3", 13, "f8E4M3">;
def HAL_CollectiveElementType_Float8E5M2FNUZ : I32EnumAttrCase<"Float8E5M2FNUZ", 14, "f8E5M2FNUZ">;
def HAL_CollectiveElementType_Float8E4M3FNUZ : I32EnumAttrCase<"Float8E4M3FNUZ", 15, "f8E4M3FNUZ">;
def HAL_CollectiveElementTypeAttr :
I32EnumAttr<"CollectiveElementType", "valid CollectiveElementType", [
HAL_CollectiveElementType_Sint8,
HAL_CollectiveElementType_Uint8,
HAL_CollectiveElementType_Sint16,
HAL_CollectiveElementType_Uint16,
HAL_CollectiveElementType_Sint32,
HAL_CollectiveElementType_Uint32,
HAL_CollectiveElementType_Sint64,
HAL_CollectiveElementType_Uint64,
HAL_CollectiveElementType_Float16,
HAL_CollectiveElementType_Float32,
HAL_CollectiveElementType_Float64,
HAL_CollectiveElementType_BFloat16,
HAL_CollectiveElementType_Float8E5M2,
HAL_CollectiveElementType_Float8E4M3,
HAL_CollectiveElementType_Float8E5M2FNUZ,
HAL_CollectiveElementType_Float8E4M3FNUZ
]> {
let cppNamespace = "::mlir::iree_compiler::IREE::HAL";
}
def HAL_CollectiveAttr :
AttrDef<HAL_Dialect, "Collective", []> {
let mnemonic = "collective";
let summary = [{collective operation and specification}];
let description = [{
Specifies the collective operation to perform and any mode bits required.
}];
let parameters = (ins
AttrParameter<"CollectiveKind", "">:$kind,
OptionalParameter<"std::optional<CollectiveReductionOp>">:$reduction,
AttrParameter<"CollectiveElementType", "">:$element_type
);
let assemblyFormat = [{
`<` $kind (`with` $reduction^)? `:` $element_type `>`
}];
let extraClassDeclaration = [{
// Returns the runtime encoding of the collective attribute.
uint32_t getEncodedValue() const;
}];
}
//===----------------------------------------------------------------------===//
// hal.pipeline.binding<*>
//===----------------------------------------------------------------------===//
def HAL_PipelineBindingAttr :
AttrDef<HAL_Dialect, "PipelineBinding", []> {
let mnemonic = "pipeline.binding";
let summary = [{pipeline binding specification}];
let description = [{
Specifies a single binding within a pipeline layout.
}];
let parameters = (ins
AttrParameter<"DescriptorType", "">:$type,
OptionalParameter<"DescriptorFlags", "DescriptorFlags::None">:$flags
);
let assemblyFormat = [{
`<` $type (`,` $flags^)? `>`
}];
}
//===----------------------------------------------------------------------===//
// hal.pipeline.layout<*>
//===----------------------------------------------------------------------===//
def HAL_PipelineLayoutAttr :
AttrDef<HAL_Dialect, "PipelineLayout", []> {
let mnemonic = "pipeline.layout";
let summary = [{executable entry point layout specification}];
let description = [{
Specifies the layout information used for interacting with executable
functions. This allows host code to correctly map parameters to the
lower-level target-specific argument passing behavior.
}];
let parameters = (ins
ArrayRefParameter<"PipelineBindingAttr", "">:$bindings,
OptionalParameter<"int64_t", "0">:$constants,
OptionalParameter<"std::optional<PipelineLayoutFlags>">:$flags
);
let assemblyFormat = [{
`<`
(`constants` `=` $constants^ `,` ` `)?
`bindings` `=` `[` qualified($bindings) `]`
(`,` `flags` `=` $flags^)?
`>`
}];
let extraClassDeclaration = [{
IREE::HAL::PipelineBindingAttr getBinding(int64_t ordinal) const;
IREE::HAL::PipelineBindingAttr getBinding(APInt ordinal) const {
return getBinding(ordinal.getSExtValue());
}
}];
}
//===----------------------------------------------------------------------===//
// #hal.executable.target<*>
//===----------------------------------------------------------------------===//
def HAL_ExecutableTargetAttr :
AttrDef<HAL_Dialect, "ExecutableTarget"> {
let mnemonic = "executable.target";
let summary = [{generic executable target specification}];
let description = [{
Specifies how to compile an executable for a specific target backend.
A backend is used to translate and serialize the executable into the final
form passed to the runtime. The format of the executable is a
target-specific value indicating the required runtime support to load the
deployed artifact. An optionally provided configuration dictionary overrides
backend-specific defaults.
Example:
```mlir
// Produce a system-native ELF for x86-64 systems using the LLVM backend:
#hal.executable.target<"llvm-cpu", "system-elf-x86_64", {
triple = "x86_64-unknown-linux-elf",
cpu = "host",
cpu_features = "host",
abi = "lp32",
...
}>
```
The same compilation backend may be used to translate executables for
several different runtime devices. Likewise the same runtime device may use
one of many different executable targets. Assume an N:M mapping between the
two in all cases.
}];
let parameters = (ins
AttrParameter<"StringAttr", "">:$backend,
AttrParameter<"StringAttr", "">:$format,
AttrParameter<"DictionaryAttr", "">:$configuration
);
let builders = [
AttrBuilder<(ins "StringRef":$backend, "StringRef":$format)>,
];
let extraClassDeclaration = [{
// Returns a symbol-compatible name that pseudo-uniquely identifies this
// target. Callers must perform deduplication when required.
std::string getSymbolNameFragment() const;
// Returns true if there's an attribute with the given name in the
// configuration dictionary.
bool hasConfigurationAttr(StringRef name);
// Returns true if this attribute is a generic version of |specificAttr|.
// A more generic version will match with many specific versions.
bool isGenericOf(IREE::HAL::ExecutableTargetAttr specificAttr);
// Returns the executable target configuration for the given operation.
// This will recursively walk parent operations until one with the
// `hal.executable.target` attribute is found or a `hal.executable.variant`
// specifies a value. Returns nullptr if no target specification can be found.
static IREE::HAL::ExecutableTargetAttr lookup(Operation *op);
}];
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// #hal.executable.object<*>
//===----------------------------------------------------------------------===//
def HAL_ExecutableObjectAttr : AttrDef<HAL_Dialect, "ExecutableObject"> {
let mnemonic = "executable.object";
let summary = [{object file reference}];
let description = [{
Defines an object file that can be linked into executables.
Today this is only supported for external file references with paths the
compiler can successfully resolve from its current working directory.
Inlined data can optionally be provided to avoid the need for file system
access and ensure the data source is attached to the IR as it makes its way
through multiple compiler stages or reproducers.
Future revisions may change this to an interface that allows both internal
and external resources to define the object contents. Linking needs to be
updated to support various object compositions and certain backends may
require additional infrastructure support.
In the long term the goal is to allow combinations of declared objects and
generated code in order to give control of linking behavior to frontends.
Instead of needing global command line flags to link in additional blobs
the frontend can emit executables with the dependencies already defined per
variant without needing to reach into the IREE compiler code.
Example:
```mlir
#hal.executable.object<{path = "some/file.obj"}>
#hal.executable.object<{
path = "some/embedded/file.obj",
data = dense<[...]> : vector<2048xi8>
}>
```
}];
let parameters = (ins
AttrParameter<"StringAttr", "">:$path,
OptionalParameter<"IREE::Util::SerializableAttrInterface", "">:$data
);
let hasCustomAssemblyFormat = 1;
let extraClassDeclaration = [{
// Returns a list of all objects with a path matching one of the provided
// file extensions.
static void filterObjects(
ArrayAttr objectAttrs, ArrayRef<StringRef> extensions,
SmallVectorImpl<ExecutableObjectAttr> &filteredAttrs);
// Returns the absolute path of the referenced object file if it exists.
FailureOr<std::string> getAbsolutePath();
// Returns the contents of the object file or None if loading failed.
// TODO(benvanik): better return type to support mapping/etc? eh
std::optional<std::string> loadData();
}];
}
def HAL_ExecutableObjectArrayAttr :
TypedArrayAttrBase<HAL_ExecutableObjectAttr,
"HAL executable object references">;
//===----------------------------------------------------------------------===//
// #hal.executable.objects<*>
//===----------------------------------------------------------------------===//
def HAL_ExecutableObjectsAttr : AttrDef<HAL_Dialect, "ExecutableObjects"> {
let mnemonic = "executable.objects";
let summary = [{target-specific object file references}];
let description = [{
A dictionary mapping executable target specifications to a list of objects.
This is used to allow layers of the stack that support multi-targeting to
specify information used during lowering into each particular target.
The key attributes are matched against each target variant based on the
backend and format as well as any configuration data provided. When
comparing the configuration only fields present in both the key and
target variant will be checked and must match. This allows specification of
generic sets ("all x86_64 targets get these objects") as well as specific
ones ("only x86_64 targets with vector_size = 64 get these objects").
Example:
```mlir
#hal.executable.objects<{
#hal.executable.target<"llvm-cpu", "embedded-elf-arm_64"> = [
#hal.executable.object<{path = "some/file_arm_64.obj"}>
],
#hal.executable.target<"llvm-cpu", "embedded-elf-x86_64"> = [
#hal.executable.object<{path = "some/file_x86_64.obj"}>
]
}>
```
}];
let parameters = (ins
AttrParameter<"ArrayAttr", "">:$targets,
AttrParameter<"ArrayAttr", "">:$targetObjects
);
let genVerifyDecl = 1;
let hasCustomAssemblyFormat = 1;
let extraClassDeclaration = [{
// Returns the objects specified for the given generic target.
std::optional<ArrayAttr> getApplicableObjects(
IREE::HAL::ExecutableTargetAttr specificTargetAttr);
}];
}
//===----------------------------------------------------------------------===//
// #hal.device.alias<*>
//===----------------------------------------------------------------------===//
def HAL_DeviceAliasAttr : AttrDef<HAL_Dialect, "DeviceAlias", [
TypedAttrInterface,
]> {
let mnemonic = "device.alias";
let summary = [{device target named alias}];
let description = [{
Specifies a device target by named alias whose configuration will be
expanded based on compiler configuration and flags. Any configuration
provided will override any defaults provided by the configuration.
Example:
```mlir
// Default `vulkan` device:
#hal.device.alias<"vulkan"> : !hal.device
// Default `vulkan` device with configuration overrides:
#hal.device.alias<"vulkan", {
device_config = 123 : index
}> : !hal.device
// The 3rd default `vulkan` device detected at runtime (ordinal = 3):
#hal.device.alias<"vulkan"[3]> : !hal.device
```
}];
let parameters = (ins
AttributeSelfTypeParameter<"">:$type,
AttrParameter<"StringAttr", "">:$deviceID,
OptionalParameter<"std::optional<int64_t>", "">:$ordinal,
OptionalParameter<"DictionaryAttr", "">:$configuration
);
let builders = [
AttrBuilder<(ins "StringRef":$deviceID)>,
];
let assemblyFormat = [{
`<`
$deviceID
`` (`[` $ordinal^ `]`)?
(`,` $configuration^)?
`>`
}];
let extraClassDeclaration = [{
Type getType() { return IREE::HAL::DeviceType::get(getContext()); }
}];
}
//===----------------------------------------------------------------------===//
// #hal.device.target<*>
//===----------------------------------------------------------------------===//
def HAL_DeviceTargetAttr : AttrDef<HAL_Dialect, "DeviceTarget", [
DeclareAttrInterfaceMethods<HAL_DeviceInitializationAttrInterface>,
]> {
let mnemonic = "device.target";
let summary = [{generic device target specification}];
let description = [{
Specifies the properties of a target runtime device.
Target devices are specified with a canonical identifier matching those used
by the runtime (such as `cpu`, `vulkan`, etc). Target devices may support
several target executable formats specified with `#hal.executable.target`.
An optional configuration dictionary allows for overriding backend defaults.
If used to initialize a device global returns the first device matching the
target requirements or null if no devices match. An optional `ordinal`
index may be provided that selects the N-th matching device and is used to
select between multiple homogeneous devices.
Example:
```mlir
#hal.device.target<"local", {
device_configuration = ...
}, [
#hal.executable.target<"llvm-cpu", "embedded-elf-arm_32">,
#hal.executable.target<"llvm-cpu", "embedded-elf-arm_64">,
]> : !hal.device
```
}];
let parameters = (ins
AttrParameter<"StringAttr", "">:$deviceID,
AttrParameter<"DictionaryAttr", "">:$configuration,
ArrayRefParameter<"ExecutableTargetAttr", "">:$executable_targets
);
let builders = [
AttrBuilder<(ins "StringRef":$deviceID)>,
];
let extraClassDeclaration = [{
Type getType() { return IREE::HAL::DeviceType::get(getContext()); }
// Returns a symbol-compatible name that pseudo-uniquely identifies this
// target. Callers must perform deduplication when required.
std::string getSymbolNameFragment();
// Returns true if there's an attribute with the given name in the
// configuration dictionary.
bool hasConfigurationAttr(StringRef name);
// Returns the configuration attribute with the given name if found.
Attribute getConfigurationAttr(StringRef name);
// Returns zero or more executable targets that this device supports.
void getExecutableTargets(
SetVector<IREE::HAL::ExecutableTargetAttr> &resultAttrs);
// Builds an expression that returns an i1 indicating whether the given
// |device| matches the device ID string pattern and executable target
// requirements.
static Value buildDeviceIDAndExecutableFormatsMatch(
Location loc, Value device, StringRef deviceIDPattern,
ArrayRef<IREE::HAL::ExecutableTargetAttr> executableTargetAttrs,
OpBuilder &builder);
// Builds a match expression that returns an i1 indicating whether the given
// |device| supports any one of the |executableTargetAttrs|.
static Value buildExecutableFormatMatch(
Location loc, Value device,
ArrayRef<IREE::HAL::ExecutableTargetAttr> executableTargetAttrs,
OpBuilder &builder);
}];
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// #hal.device.ordinal<*>
//===----------------------------------------------------------------------===//
def HAL_DeviceOrdinalAttr : AttrDef<HAL_Dialect, "DeviceOrdinal", [
DeclareAttrInterfaceMethods<HAL_DeviceInitializationAttrInterface>,
]> {
let mnemonic = "device.ordinal";
let summary = [{specifies a device by runtime registration ordinal}];
let description = [{
Represents the device registered with the runtime in the order it was
registered with ordinal 0 being the first registered. Returns null during
initialization if the device ordinal is out of range.
}];
let parameters = (ins
AttributeSelfTypeParameter<"">:$type,
AttrParameter<"int64_t", "">:$ordinal
);
let assemblyFormat = [{
`<` $ordinal `>`
}];
}
//===----------------------------------------------------------------------===//
// #hal.device.fallback<*>
//===----------------------------------------------------------------------===//
def HAL_DeviceFallbackAttr : AttrDef<HAL_Dialect, "DeviceFallback", [
DeclareAttrInterfaceMethods<HAL_DeviceInitializationAttrInterface>,
]> {
let mnemonic = "device.fallback";
let summary = [{specifies a reference to another device}];
let description = [{
Specifies by symbol a device that has already been initialized.
Returns null during initialization if the device specified as a fallback is
null.
}];
let parameters = (ins
AttributeSelfTypeParameter<"">:$type,
AttrParameter<"FlatSymbolRefAttr", "">:$name
);
let assemblyFormat = [{
`<` $name `>`
}];
}
//===----------------------------------------------------------------------===//
// #hal.device.select<*>
//===----------------------------------------------------------------------===//
def HAL_DeviceSelectAttr : AttrDef<HAL_Dialect, "DeviceSelect", [
DeclareAttrInterfaceMethods<HAL_DeviceInitializationAttrInterface>,
]> {
let mnemonic = "device.select";
let summary = [{selects a device from one or more options}];
let description = [{
Selects a HAL device at runtime by either enumerating and querying for
target support or matching the given existing device by affinity.
Devices are selected in the order listed. Fails during initialization if no
device can be selected.
Examples:
```mlir
// Selects a single device matching the given target.
#hal.device.select<[
#hal.device.target<"..."> : !hal.device
]> : !hal.device
// Selects a specific device with the given symbol.
#hal.device.select<[
#hal.device.fallback<@device_0> : !hal.device
]> : !hal.device
// Selects a specific device by ordinal as registered at runtime.
#hal.device.select<[
#hal.device.ordinal<0> : !hal.device
]> : !hal.device
// Selects an optional device if available and otherwise @fallback.
#hal.device.select<[
#hal.device.target<"some_optional_device"> : !hal.device,
#hal.device.fallback<@fallback> : !hal.device
]> : !hal.device
```
}];
let parameters = (ins
AttributeSelfTypeParameter<"">:$type,
AttrParameter<"ArrayAttr", "">:$devices
);
let builders = [
AttrBuilder<(ins
"ArrayRef<Attribute>":$values
)>,
];
let assemblyFormat = [{
`<` $devices `>`
}];
let genVerifyDecl = 1;
}
//===----------------------------------------------------------------------===//
// #hal.device.affinity<*>
//===----------------------------------------------------------------------===//
def HAL_DeviceAffinityAttr : AttrDef<HAL_Dialect, "DeviceAffinity", [
DeclareAttrInterfaceMethods<Stream_AffinityAttr, [
"isExecutableWith",
"joinOR",
"joinAND",
]>,
Util_HoistableAttrInterface,
DeclareAttrInterfaceMethods<Util_InliningPolicyAttrInterface, [
"isLegalToInline",
]>,
]> {
let mnemonic = "device.affinity";
let summary = [{specifies a named device and optional queue affinity}];
let description = [{
Specifies that an annotated operation or scope is only allowed to execute on
a specific device and optionally a set of queues (0-64) provided.
Operations will not run on other queues. If the queue mask is omitted then
any queue on the device is allowed to execute the specified operations.
Example:
```mlir
// Any queue on @device_a.
#hal.device.affinity<@device_a>
// Queues 4 and 5 on @device_b.
#hal.device.affinity<@device_b, [4, 5]>
```
}];
let parameters = (ins
AttrParameter<"SymbolRefAttr", "">:$device,
AttrParameter<"int64_t", "">:$queue_mask
);
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// #hal.device.promise<*>
//===----------------------------------------------------------------------===//
def HAL_DevicePromiseAttr : AttrDef<HAL_Dialect, "DevicePromise", [
DeclareAttrInterfaceMethods<Stream_AffinityAttr, [
"isExecutableWith",
"joinOR",
"joinAND",
]>,
DeclareAttrInterfaceMethods<Util_InliningPolicyAttrInterface, [
"isLegalToInline",
]>,
]> {
let mnemonic = "device.promise";
let summary = [{promises a named device and optional queue affinity}];
let description = [{
Specifies that an annotated operation or scope is only allowed to execute on
a specific device that has not yet been declared and optionally a set of
queues (0-64) provided. Operations will not run on other queues. If the
queue mask is omitted then any queue on the device is allowed to execute the
specified operations.
This is used in input programs to assign operations to particular devices
prior to the devices being declared. This allows device categories to be
referenced in the program as produced from the frontend and for those
device specifications to be provided later on during compilation.
Verification is performed as part of the ResolveDevicePromisesPass.
Example:
```mlir
// Any queue on whatever @device_a will be after declaration.
#hal.device.promise<@device_a>
// Queues 4 and 5 on whatever @device_b will be after declaration.
#hal.device.promise<@device_b, [4, 5]>
```
}];
let parameters = (ins
AttrParameter<"StringAttr", "">:$device,
AttrParameter<"int64_t", "">:$queue_mask
);
let hasCustomAssemblyFormat = 1;
}
#endif // IREE_DIALECT_HAL_IR_HAL_ATTRS