[mlir][gpu] Add pass for emulating unsupported types. by mshahneo · Pull Request #138087 · llvm/llvm-project (original) (raw)

@llvm/pr-subscribers-mlir-arith
@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-mlir-gpu

Author: Md Abdullah Shahneous Bari (mshahneo)

Changes

This pass imitates (bitcast/reinterpret_cast) unsupported types with supported types of same bitwidth. The imitation is done by bitcasting the unspported types to the supported types of same bitwidth. Therefore, the source type and destination type must have the same bitwidth. The imitation is done by using the following operations: arith.bitcast.

The imitation is often needed when the GPU target (dialect/IR) does not support a certain type but the underlying architecture does. Take SPIR-V for example, it does not support bf16, but an underlying architecture (e.g., intel pvc gpu) that uses SPIR-V for code-generation does. Therefore, bf16 is neither a valid data type to pass to gpu kernel, nor to be used inside the kernel. To use bf16 data type in a SPIR-V kernel (as a kernel parameter or inside the kernel), bf16 have to be bitcasted (similar to C++ reinterpret_cast) to a supported type (e.g., i16 for Intel GPUs). The SPIR-V kernel can then use the imitated type (i16) in the computation. However, i16 is not the same as bf16 (integer vs float), so the computation can not readily use the imitated type (i16).

Therefore, this transformation pass is intended to be used in conjuction with other transformation passes such as EmulateUnsupportedFloats and ExtendUnsupportedTypes that extend the bitwidth of bf16 to f32 and vice-versa.

Finally, usually, there are instructions available in the target (dialect/IR) that can take advantage of these generated patterns (bf16->i16->f32, f32->bf16->i16), and convert them to the supported types.
For example, Intel provides SPIR-V extension ops that can take imitated bf16 (i16) and convert them to f32 and vice-versa. https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/INTEL/SPV_INTEL_bfloat16_conversion.asciidoc https://mlir.llvm.org/docs/Dialects/SPIR-V/#spirvintelconvertbf16tof-spirvintelconvertbf16tofop https://mlir.llvm.org/docs/Dialects/SPIR-V/#spirvintelconvertftobf16-spirvintelconvertftobf16op


Patch is 48.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138087.diff

4 Files Affected:

diff --git a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.h b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.h index 6cd6f03253aea..0b7339a94b274 100644 --- a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.h +++ b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.h @@ -16,6 +16,8 @@ #include "mlir/Dialect/AMDGPU/Utils/Chipset.h" #include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/Dialect/GPU/Utils/GPUUtils.h" +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Pass/Pass.h" #include @@ -87,6 +89,24 @@ void populateGpuLowerClusteredSubgroupReduceToDPPPatterns( RewritePatternSet &patterns, unsigned subgroupSize, amdgpu::Chipset chipset, PatternBenefit benefit = 1);

+/// Set up a type converter to convert unsupported source types to +/// supported target types. +void populateImitateUnsupportedTypesTypeConverter(TypeConverter &typeConverter,

+def GpuImitateUnsupportedTypes : Pass<"imitate-unsupported-types", "::mlir::ModuleOp"> {

+} + + #endif // MLIR_DIALECT_GPU_PASSES diff --git a/mlir/lib/Dialect/GPU/Transforms/ImitateUnsupportedTypes.cpp b/mlir/lib/Dialect/GPU/Transforms/ImitateUnsupportedTypes.cpp new file mode 100644 index 0000000000000..c83e6bec568e0 --- /dev/null +++ b/mlir/lib/Dialect/GPU/Transforms/ImitateUnsupportedTypes.cpp @@ -0,0 +1,916 @@ +//===- ImitateUnsupportedTypes.cpp - Unsupported Type Imitation ----- C++ +//--===// +// +// 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 +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// +/// \file +/// This pass imitates (bitcast/reinterpret_cast) unsupported types +/// with supported types of same bitwidth. The imitation is done +/// by bitcasting the unspported types to the supported types of same bitwidth. +/// Therefore, the source type and destination type must have the same bitwidth. +/// The imitation is done by using the following operations: arith.bitcast. +/// +/// The imitation is often needed when the GPU target (dialect/IR) does not +/// support a certain type but the underlying architecture does. Take SPIR-V for +/// example, it does not support bf16, but an underlying architecture (e.g., +/// intel pvc gpu) that uses SPIR-V for code-generation does. +/// Therefore, bf16 is neither a valid data type to pass to gpu kernel, nor to +/// be used inside the kernel. To use bf16 data type in a SPIR-V kernel (as a +/// kernel parameter or inside the kernel), bf16 have to be bitcasted (similar +/// to C++ reinterpret_cast) to a supported type (e.g., i16 for Intel GPUs). The +/// SPIR-V kernel can then use the imitated type (i16) in the computation. +/// However, i16 is not the same as bf16 (integer vs float), so the computation +/// can not readily use the imitated type (i16). +/// +/// Therefore, this transformation pass is intended to be used in conjuction +/// with other transformation passes such as EmulateUnsupportedFloats and +/// ExtendUnsupportedTypes that extend the bitwidth of bf16 to f32 and +/// vice-versa. +/// +/// Finally, usually, there are instructions available in the target +/// (dialect/IR) that can take advantage of these generated patterns +/// (bf16->i16->f32, f32->bf16->i16), and convert them to the supported +/// types. +/// For example, Intel provides SPIR-V extension ops that can +/// take imitated bf16 (i16) and convert them to f32 and vice-versa. +/// https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/INTEL/SPV_INTEL_bfloat16_conversion.asciidoc +/// https://mlir.llvm.org/docs/Dialects/SPIR-V/#spirvintelconvertbf16tof-spirvintelconvertbf16tofop +/// https://mlir.llvm.org/docs/Dialects/SPIR-V/#spirvintelconvertftobf16-spirvintelconvertftobf16op +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/GPU/Transforms/Passes.h" + +#include "mlir/Dialect/Affine/IR/AffineOps.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Arith/Utils/Utils.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/GPU/IR/GPUDialect.h" +#include "mlir/Dialect/Math/IR/Math.h" +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/Dialect/Vector/IR/VectorOps.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Location.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/Transforms/DialectConversion.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" + +#include +#include +#include + +using namespace mlir; +using namespace mlir::gpu; + +namespace mlir { +#define GEN_PASS_DEF_GPUIMITATEUNSUPPORTEDTYPES +#include "mlir/Dialect/GPU/Transforms/Passes.h.inc" +} // namespace mlir + +//===----------------------------------------------------------------------===// +// Utility functions +//===----------------------------------------------------------------------===// + +APFloat bitcastAPIntToAPFloat(const APInt &intValue,