blob: ae7b2fa682f4bcca05696568bc4e3c5e6c0e2148 [file] [log] [blame]
// 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
#include <cstdint>
#include <optional>
#include <vector>
#include "iree/compiler/dialects/iree_codegen.h"
#include "iree/compiler/dialects/iree_gpu.h"
#include "mlir-c/BuiltinAttributes.h"
#include "mlir-c/IR.h"
#include "mlir/Bindings/Python/PybindAdaptors.h"
static const char *kCodegenModuleImportPath =
MAKE_MLIR_PYTHON_QUALNAME("dialects.iree_codegen");
static const char *kGpuModuleImportPath =
MAKE_MLIR_PYTHON_QUALNAME("dialects.iree_gpu");
namespace py = pybind11;
using namespace mlir::python::adaptors;
static std::vector<MlirOperation>
ireeCodegenGetExecutableVariantOpsBinding(MlirModule module) {
size_t numOps = 0;
ireeCodegenGetExecutableVariantOps(module, &numOps, nullptr);
std::vector<MlirOperation> ops(numOps);
ireeCodegenGetExecutableVariantOps(module, &numOps, ops.data());
return ops;
}
static std::vector<py::object>
ireeCodegenQueryMMAIntrinsicsBinding(MlirOperation op) {
size_t numMMAs = 0;
ireeCodegenQueryMMAIntrinsics(op, &numMMAs, nullptr);
std::vector<uint32_t> mmaIntrinsics(numMMAs);
ireeCodegenQueryMMAIntrinsics(op, &numMMAs, mmaIntrinsics.data());
py::object mmaIntrinsicEnum =
py::module_::import(kGpuModuleImportPath).attr("MMAIntrinsic");
std::vector<py::object> mmaList(numMMAs);
for (size_t i = 0; i < numMMAs; ++i) {
mmaList[i] = mmaIntrinsicEnum(mmaIntrinsics[i]);
}
return mmaList;
}
PYBIND11_MODULE(_ireeCompilerDialects, m) {
m.doc() = "iree-compiler dialects python extension";
auto iree_codegen_module =
m.def_submodule("iree_codegen", "iree_codegen dialect bindings");
//===-------------------------------------------------------------------===//
// CodegenDispatchLoweringPassPipelineAttr
//===-------------------------------------------------------------------===//
mlir_attribute_subclass(
iree_codegen_module, "DispatchLoweringPassPipelineAttr",
ireeAttributeIsACodegenDispatchLoweringPassPipelineAttr,
ireeCodegenDispatchLoweringPassPipelineAttrGetTypeID)
.def_classmethod(
"get",
[](const py::object &, uint32_t value, MlirContext ctx) {
return ireeCodegenDispatchLoweringPassPipelineAttrGet(ctx, value);
},
"cls"_a, "value"_a, "ctx"_a = py::none(),
"Gets an #iree_codegen.dispatch_lowering_pass_pipeline from "
"parameters.")
.def_property_readonly(
"raw_value", ireeCodegenDispatchLoweringPassPipelineAttrGetValue)
.def_property_readonly("value", [](MlirAttribute self) -> py::object {
uint32_t rawValue =
ireeCodegenDispatchLoweringPassPipelineAttrGetValue(self);
return py::module_::import(kCodegenModuleImportPath)
.attr("DispatchLoweringPassPipeline")(rawValue);
});
//===-------------------------------------------------------------------===//
// CodegenTranslationInfoAttr
//===-------------------------------------------------------------------===//
mlir_attribute_subclass(iree_codegen_module, "TranslationInfoAttr",
ireeAttributeIsACodegenTranslationInfoAttr,
ireeCodegenTranslationInfoAttrGetTypeID)
.def_classmethod(
"get",
[](const py::object &, MlirAttribute passPipeline,
std::optional<MlirAttribute> codegenSpec,
std::optional<std::vector<int64_t>> workgroupSize,
std::optional<int64_t> subgroupSize,
std::optional<MlirAttribute> configuration, MlirContext ctx) {
ireeCodegenTranslationInfoParameters parameters = {};
parameters.passPipeline = passPipeline;
parameters.codegenSpec =
codegenSpec.value_or(mlirAttributeGetNull());
if (workgroupSize.has_value()) {
parameters.workgroupSize = workgroupSize->data();
parameters.numWorkgroupSizeElements = workgroupSize->size();
}
parameters.subgroupSize = subgroupSize.value_or(0);
parameters.configuration =
configuration.value_or(mlirAttributeGetNull());
return ireeCodegenTranslationInfoAttrGet(ctx, parameters);
},
"cls"_a, "pass_pipeline"_a, "codegen_spec"_a = py::none(),
"workgroup_size"_a = py::none(), "subgroup_size"_a = py::none(),
"configuration"_a = py::none(), py::kw_only(), "ctx"_a = py::none(),
"Gets an #iree_codegen.translation_info from parameters.")
.def_property_readonly(
"pass_pipeline",
[](MlirAttribute self) -> MlirAttribute {
auto parameters = ireeCodegenTranslationInfoAttrGetParameters(self);
return parameters.passPipeline;
})
.def_property_readonly(
"codegen_spec",
[](MlirAttribute self) -> std::optional<MlirAttribute> {
auto parameters = ireeCodegenTranslationInfoAttrGetParameters(self);
if (mlirAttributeIsNull(parameters.codegenSpec)) {
return std::nullopt;
}
return parameters.codegenSpec;
})
.def_property_readonly(
"workgroup_size",
[](MlirAttribute self) -> std::vector<int64_t> {
auto parameters = ireeCodegenTranslationInfoAttrGetParameters(self);
return {parameters.workgroupSize,
parameters.workgroupSize +
parameters.numWorkgroupSizeElements};
})
.def_property_readonly(
"subgroup_size",
[](MlirAttribute self) -> int64_t {
auto parameters = ireeCodegenTranslationInfoAttrGetParameters(self);
return parameters.subgroupSize;
})
.def_property_readonly(
"configuration",
[](MlirAttribute self) -> std::optional<MlirAttribute> {
auto parameters = ireeCodegenTranslationInfoAttrGetParameters(self);
if (mlirAttributeIsNull(parameters.configuration)) {
return std::nullopt;
}
return parameters.configuration;
});
//===-------------------------------------------------------------------===//
// CodegenCompilationInfoAttr
//===-------------------------------------------------------------------===//
mlir_attribute_subclass(iree_codegen_module, "CompilationInfoAttr",
ireeAttributeIsACodegenCompilationInfoAttr,
ireeCodegenCompilationInfoAttrGetTypeID)
.def_classmethod(
"get",
[](const py::object &, MlirAttribute loweringConfig,
MlirAttribute translationInfo, MlirContext ctx) {
ireeCodegenCompilationInfoParameters parameters = {};
parameters.loweringConfig = loweringConfig;
parameters.translationInfo = translationInfo;
return ireeCodegenCompilationInfoAttrGet(ctx, parameters);
},
"cls"_a, "lowering_config"_a, "translation_info"_a,
"ctx"_a = py::none(),
"Gets an #iree_codegen.compilation_info from parameters.")
.def_property_readonly(
"lowering_config",
[](MlirAttribute self) -> MlirAttribute {
auto parameters = ireeCodegenCompilationInfoAttrGetParameters(self);
return parameters.loweringConfig;
})
.def_property_readonly(
"translation_info", [](MlirAttribute self) -> MlirAttribute {
auto parameters = ireeCodegenCompilationInfoAttrGetParameters(self);
return parameters.translationInfo;
});
//===--------------------------------------------------------------------===//
auto iree_gpu_module =
m.def_submodule("iree_gpu", "iree_gpu dialect bindings");
//===-------------------------------------------------------------------===//
// GPUReorderWorkgroupsStrategyAttr
//===-------------------------------------------------------------------===//
mlir_attribute_subclass(iree_gpu_module, "ReorderWorkgroupsStrategyAttr",
ireeAttributeIsAGPUReorderWorkgroupsStrategyAttr,
ireeGPUReorderWorkgroupsStrategyAttrGetTypeID)
.def_classmethod(
"get",
[](const py::object &, uint32_t value, MlirContext ctx) {
return ireeGPUReorderWorkgroupsStrategyAttrGet(ctx, value);
},
"cls"_a, "value"_a, "ctx"_a = py::none(),
"Gets an #iree_gpu.reorder_workgroups_strategy from parameters.")
.def_property_readonly("raw_value",
ireeGPUReorderWorkgroupsStrategyAttrGetValue)
.def_property_readonly("value", [](MlirAttribute self) -> py::object {
uint32_t rawValue = ireeGPUReorderWorkgroupsStrategyAttrGetValue(self);
return py::module_::import(kGpuModuleImportPath)
.attr("ReorderWorkgroupsStrategy")(rawValue);
});
//===-------------------------------------------------------------------===//
// GPUPipelineOptionsAttr
//===-------------------------------------------------------------------===//
mlir_attribute_subclass(iree_gpu_module, "PipelineOptionsAttr",
ireeAttributeIsAGPUPipelineOptionsAttr,
ireeGPUPipelineOptionsAttrGetTypeID)
.def_classmethod(
"get",
[](const py::object &, std::optional<bool> prefetchSharedMemory,
std::optional<bool> noReduceSharedMemoryBankConflicts,
std::optional<bool> useIgemmConvolution,
std::optional<MlirAttribute> reorderWorkgroupsStrategy,
MlirContext ctx) {
return ireeGPUPipelineOptionsAttrGet(
ctx,
prefetchSharedMemory.has_value() ? &*prefetchSharedMemory
: nullptr,
noReduceSharedMemoryBankConflicts.has_value()
? &*noReduceSharedMemoryBankConflicts
: nullptr,
useIgemmConvolution.has_value() ? &*useIgemmConvolution
: nullptr,
reorderWorkgroupsStrategy.has_value()
? &*reorderWorkgroupsStrategy
: nullptr);
},
"cls"_a, "prefetch_shared_memory"_a = py::none(),
"no_reduce_shared_memory_bank_conflicts"_a = py::none(),
"use_igemm_convolution"_a = py::none(),
"reorder_workgroups_strategy"_a = py::none(), py::kw_only(),
"ctx"_a = py::none(),
"Gets an #iree_gpu.pipeline_options from parameters.")
.def_property_readonly(
"prefetch_shared_memory",
[](MlirAttribute self) -> std::optional<bool> {
auto attr = ireeGPUPipelineOptionsAttrGetPrefetchSharedMemory(self);
if (!mlirAttributeIsNull(attr))
return mlirBoolAttrGetValue(attr);
return std::nullopt;
})
.def_property_readonly(
"no_reduce_shared_memory_bank_conflicts",
[](MlirAttribute self) -> std::optional<bool> {
auto attr =
ireeGPUPipelineOptionsAttrGetNoReduceSharedMemoryBankConflicts(
self);
if (!mlirAttributeIsNull(attr))
return mlirBoolAttrGetValue(attr);
return std::nullopt;
})
.def_property_readonly(
"use_igemm_convolution",
[](MlirAttribute self) -> std::optional<bool> {
auto attr = ireeGPUPipelineOptionsAttrGetUseIgemmConvolution(self);
if (!mlirAttributeIsNull(attr))
return mlirBoolAttrGetValue(attr);
return std::nullopt;
})
.def_property_readonly(
"reorder_workgroups_strategy",
[](MlirAttribute self) -> std::optional<MlirAttribute> {
auto attr =
ireeGPUPipelineOptionsAttrGetReorderWorkgroupsStrategy(self);
if (!mlirAttributeIsNull(attr))
return attr;
return std::nullopt;
});
//===-------------------------------------------------------------------===//
// GPUMMAIntrinsicAttr
//===-------------------------------------------------------------------===//
mlir_attribute_subclass(iree_gpu_module, "MMAIntrinsicAttr",
ireeAttributeIsAGPUMMAIntrinsicAttr,
ireeGPUMMAIntrinsicAttrGetTypeID)
.def_classmethod(
"get",
[](const py::object &, uint32_t value, MlirContext ctx) {
return ireeGPUMMAIntrinsicAttrGet(ctx, value);
},
"cls"_a, "value"_a, "ctx"_a = py::none(),
"Gets an #iree_gpu.mma_intrinsic from parameters.")
.def_property_readonly("raw_value", ireeGPUMMAIntrinsicAttrGetValue)
.def_property_readonly("value",
[](MlirAttribute self) -> py::object {
uint32_t rawValue =
ireeGPUMMAIntrinsicAttrGetValue(self);
return py::module_::import(kGpuModuleImportPath)
.attr("MMAIntrinsic")(rawValue);
})
.def_property_readonly("mma", [](MlirAttribute self) -> MlirAttribute {
uint32_t value = ireeGPUMMAIntrinsicAttrGetValue(self);
return ireeGPUMMAAttrGet(mlirAttributeGetContext(self), value);
});
//===-------------------------------------------------------------------===//
// GPUMMAAttr
//===-------------------------------------------------------------------===//
mlir_attribute_subclass(iree_gpu_module, "MMAAttr",
ireeAttributeIsAGPUMMAAttr, ireeGPUMMAAttrGetTypeID)
.def_classmethod(
"get",
[](const py::object &, uint32_t value, MlirContext ctx) {
return ireeGPUMMAAttrGet(ctx, value);
},
"cls"_a, "value"_a, "ctx"_a = py::none(),
"Gets an #iree_gpu.mma from parameters.")
.def_property_readonly(
"abc_element_types",
[](MlirAttribute self) -> py::tuple {
ireeGPUMMAInfo info = ireeGPUMMAAttrGetInfo(self);
return py::make_tuple(info.aElementType, info.bElementType,
info.cElementType);
})
.def_property_readonly(
"abc_vector_types",
[](MlirAttribute self) -> py::tuple {
ireeGPUMMAInfo info = ireeGPUMMAAttrGetInfo(self);
return py::make_tuple(info.aVectorType, info.bVectorType,
info.cVectorType);
})
.def_property_readonly("mnk_shape", [](MlirAttribute self) -> py::tuple {
ireeGPUMMAInfo info = ireeGPUMMAAttrGetInfo(self);
return py::make_tuple(info.mElements, info.nElements, info.kElements);
});
//===-------------------------------------------------------------------===//
// GPULoweringConfigAttr
//===-------------------------------------------------------------------===//
mlir_attribute_subclass(iree_gpu_module, "LoweringConfigAttr",
ireeAttributeIsAGPULoweringConfigAttr,
ireeGPULoweringConfigAttrGetTypeID)
.def_classmethod(
"get",
[](const py::object &, MlirAttribute attributeDictionary,
MlirContext ctx) {
return ireeGPULoweringConfigAttrGet(ctx, attributeDictionary);
},
"cls"_a, "value"_a, "ctx"_a = py::none(),
"Gets an #iree_gpu.lowering_config from parameters.")
.def_property_readonly("attributes",
ireeGPULoweringConfigAttrGetAttributes)
.def_property_readonly(
"workgroup_tile_sizes",
[](MlirAttribute self) -> std::vector<int64_t> {
auto tilesizes = ireeGPULoweringConfigAttrGetTileSizes(self);
MlirAttribute workgroupAttr = tilesizes.workgroupAttr;
if (mlirAttributeIsNull(workgroupAttr)) {
return {};
}
size_t len = mlirArrayAttrGetNumElements(workgroupAttr);
std::vector<int64_t> workgroup(len);
for (size_t i = 0; i < len; ++i) {
MlirAttribute attr = mlirArrayAttrGetElement(workgroupAttr, i);
workgroup[i] = mlirIntegerAttrGetValueInt(attr);
}
return workgroup;
})
.def_property_readonly(
"reduction_tile_sizes",
[](MlirAttribute self) -> std::vector<int64_t> {
auto tilesizes = ireeGPULoweringConfigAttrGetTileSizes(self);
MlirAttribute reductionAttr = tilesizes.reductionAttr;
if (mlirAttributeIsNull(reductionAttr)) {
return {};
}
size_t len = mlirArrayAttrGetNumElements(reductionAttr);
std::vector<int64_t> reduction(len);
for (size_t i = 0; i < len; ++i) {
MlirAttribute attr = mlirArrayAttrGetElement(reductionAttr, i);
reduction[i] = mlirIntegerAttrGetValueInt(attr);
}
return reduction;
})
.def_property_readonly(
"subgroup_count_mn",
[](MlirAttribute self) -> py::tuple {
ireeGPUSubgroupCountInfo info =
ireeGPULoweringConfigAttrGetSubgroupCount(self);
MlirAttribute mCountAttr = info.subgroupMCountAttr;
MlirAttribute nCountAttr = info.subgroupNCountAttr;
std::optional<int64_t> mCount;
if (!mlirAttributeIsNull(mCountAttr)) {
mCount = mlirIntegerAttrGetValueInt(mCountAttr);
}
std::optional<int64_t> nCount;
if (!mlirAttributeIsNull(nCountAttr)) {
nCount = mlirIntegerAttrGetValueInt(nCountAttr);
}
return py::make_tuple(mCount, nCount);
})
.def_property_readonly(
"mma_kind", [](MlirAttribute self) -> std::optional<MlirAttribute> {
auto attr = ireeGPULoweringConfigAttrGetMmaKind(self);
if (!mlirAttributeIsNull(attr))
return attr;
return std::nullopt;
});
//===-------------------------------------------------------------------===//
// Binding to utility function getExecutableVariantOps
//===-------------------------------------------------------------------===//
iree_codegen_module.def(
"get_executable_variant_ops", &ireeCodegenGetExecutableVariantOpsBinding,
"Gets the executable variant operations from a module.",
py::arg("module"));
//===-------------------------------------------------------------------===//
// Binding to utility function queryMMAIntrinsics
//===-------------------------------------------------------------------===//
iree_codegen_module.def(
"query_mma_intrinsics", &ireeCodegenQueryMMAIntrinsicsBinding,
"Queries the MMA intrinsics from an executable variant op.",
py::arg("op"));
}