MLIR 24.0.0git
MathToROCDL.cpp
Go to the documentation of this file.
1//===-- MathToROCDL.cpp - conversion from Math to rocdl calls -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
23#include "mlir/Pass/Pass.h"
25#include "llvm/Support/DebugLog.h"
26
29
30namespace mlir {
31#define GEN_PASS_DEF_CONVERTMATHTOROCDL
32#include "mlir/Conversion/Passes.h.inc"
33} // namespace mlir
34
35using namespace mlir;
36
37#define DEBUG_TYPE "math-to-rocdl"
38
39template <typename OpTy>
40static void populateOpPatterns(const LLVMTypeConverter &converter,
41 RewritePatternSet &patterns, StringRef f32Func,
42 StringRef f64Func, StringRef f16Func,
43 StringRef f32ApproxFunc = "") {
44 patterns.add<ScalarizeVectorOpLowering<OpTy>>(converter);
45 patterns.add<OpToFuncCallLowering<OpTy>>(converter, f32Func, f64Func,
46 f32ApproxFunc, f16Func);
47}
48
50 : public ConvertOpToLLVMPattern<math::ClampFOp> {
52
53 LogicalResult
54 matchAndRewrite(math::ClampFOp op, OpAdaptor adaptor,
55 ConversionPatternRewriter &rewriter) const override {
56 // Only f16 and f32 types are supported by fmed3
57 Type opTy = op.getType();
58 Type resultType = getTypeConverter()->convertType(opTy);
59
60 if (auto vectorType = dyn_cast<VectorType>(opTy))
61 opTy = vectorType.getElementType();
62
63 if (!isa<Float16Type, Float32Type>(opTy))
64 return rewriter.notifyMatchFailure(
65 op, "fmed3 only supports f16 and f32 types");
66
67 // Handle multi-dimensional vectors (converted to LLVM arrays)
68 if (auto arrayType = dyn_cast<LLVM::LLVMArrayType>(resultType))
70 op.getOperation(), adaptor.getOperands(), *getTypeConverter(),
71 [&](Type llvm1DVectorTy, ValueRange operands) -> Value {
72 math::ClampFOp::Adaptor adaptor(operands);
73 return ROCDL::FMed3Op::create(rewriter, op.getLoc(), llvm1DVectorTy,
74 adaptor.getValue(), adaptor.getMin(),
75 adaptor.getMax());
76 },
77 rewriter);
78
79 // Handle 1D vectors and scalars directly
80 rewriter.replaceOpWithNewOp<ROCDL::FMed3Op>(op, op.getType(), op.getValue(),
81 op.getMin(), op.getMax());
82 return success();
83 }
84};
85
87 const LLVMTypeConverter &converter, RewritePatternSet &patterns,
88 std::optional<amdgpu::Chipset> chipset) {
89 // Handled by mathToLLVM: math::AbsIOp
90 // Handled by mathToLLVM: math::AbsFOp
91 // Handled by mathToLLVM: math::CopySignOp
92 // Handled by mathToLLVM: math::CountLeadingZerosOp
93 // Handled by mathToLLVM: math::CountTrailingZerosOp
94 // Handled by mathToLLVM: math::CgPopOp
95 // Handled by mathToLLVM: math::ExpOp (32-bit only)
96 // Handled by mathToLLVM: math::FmaOp
97 // Handled by mathToLLVM: math::LogOp (32-bit only)
98 // FIXME: math::IPowIOp
99 // Handled by mathToLLVM: math::RoundEvenOp
100 // Handled by mathToLLVM: math::RoundOp
101 // Handled by mathToLLVM: math::SqrtOp
102 // Handled by mathToLLVM: math::TruncOp
103 populateOpPatterns<math::AcosOp>(converter, patterns, "__ocml_acos_f32",
104 "__ocml_acos_f64", "__ocml_acos_f16");
105 populateOpPatterns<math::AcoshOp>(converter, patterns, "__ocml_acosh_f32",
106 "__ocml_acosh_f64", "__ocml_acosh_f16");
107 populateOpPatterns<math::AsinOp>(converter, patterns, "__ocml_asin_f32",
108 "__ocml_asin_f64", "__ocml_asin_f16");
109 populateOpPatterns<math::AsinhOp>(converter, patterns, "__ocml_asinh_f32",
110 "__ocml_asinh_f64", "__ocml_asinh_f16");
111 populateOpPatterns<math::AtanOp>(converter, patterns, "__ocml_atan_f32",
112 "__ocml_atan_f64", "__ocml_atan_f16");
113 populateOpPatterns<math::AtanhOp>(converter, patterns, "__ocml_atanh_f32",
114 "__ocml_atanh_f64", "__ocml_atanh_f16");
115 populateOpPatterns<math::Atan2Op>(converter, patterns, "__ocml_atan2_f32",
116 "__ocml_atan2_f64", "__ocml_atan2_f16");
117 populateOpPatterns<math::CbrtOp>(converter, patterns, "__ocml_cbrt_f32",
118 "__ocml_cbrt_f64", "__ocml_cbrt_f16");
119 populateOpPatterns<math::CeilOp>(converter, patterns, "__ocml_ceil_f32",
120 "__ocml_ceil_f64", "__ocml_ceil_f16");
121 populateOpPatterns<math::CosOp>(converter, patterns, "__ocml_cos_f32",
122 "__ocml_cos_f64", "__ocml_cos_f16");
123 populateOpPatterns<math::CoshOp>(converter, patterns, "__ocml_cosh_f32",
124 "__ocml_cosh_f64", "__ocml_cosh_f16");
125 populateOpPatterns<math::SinhOp>(converter, patterns, "__ocml_sinh_f32",
126 "__ocml_sinh_f64", "__ocml_sinh_f16");
127 populateOpPatterns<math::ExpOp>(converter, patterns, "", "__ocml_exp_f64",
128 "__ocml_exp_f16");
129 populateOpPatterns<math::Exp2Op>(converter, patterns, "__ocml_exp2_f32",
130 "__ocml_exp2_f64", "__ocml_exp2_f16");
131 populateOpPatterns<math::ExpM1Op>(converter, patterns, "__ocml_expm1_f32",
132 "__ocml_expm1_f64", "__ocml_expm1_f16");
133 populateOpPatterns<math::FloorOp>(converter, patterns, "__ocml_floor_f32",
134 "__ocml_floor_f64", "__ocml_floor_f16");
135 populateOpPatterns<math::LogOp>(converter, patterns, "", "__ocml_log_f64",
136 "__ocml_log_f16");
137 populateOpPatterns<math::Log10Op>(converter, patterns, "__ocml_log10_f32",
138 "__ocml_log10_f64", "__ocml_log10_f16");
139 populateOpPatterns<math::Log1pOp>(converter, patterns, "__ocml_log1p_f32",
140 "__ocml_log1p_f64", "__ocml_log1p_f16");
141 populateOpPatterns<math::Log2Op>(converter, patterns, "__ocml_log2_f32",
142 "__ocml_log2_f64", "__ocml_log2_f16");
143 populateOpPatterns<math::PowFOp>(converter, patterns, "__ocml_pow_f32",
144 "__ocml_pow_f64", "__ocml_pow_f16");
145 populateOpPatterns<math::RsqrtOp>(converter, patterns, "__ocml_rsqrt_f32",
146 "__ocml_rsqrt_f64", "__ocml_rsqrt_f16");
147 populateOpPatterns<math::SinOp>(converter, patterns, "__ocml_sin_f32",
148 "__ocml_sin_f64", "__ocml_sin_f16");
149 populateOpPatterns<math::TanhOp>(converter, patterns, "__ocml_tanh_f32",
150 "__ocml_tanh_f64", "__ocml_tanh_f16");
151 populateOpPatterns<math::TanOp>(converter, patterns, "__ocml_tan_f32",
152 "__ocml_tan_f64", "__ocml_tan_f16");
153 populateOpPatterns<math::ErfOp>(converter, patterns, "__ocml_erf_f32",
154 "__ocml_erf_f64", "__ocml_erf_f16");
155 populateOpPatterns<math::ErfcOp>(converter, patterns, "__ocml_erfc_f32",
156 "__ocml_erfc_f64", "__ocml_erfc_f16");
157 populateOpPatterns<math::FPowIOp>(converter, patterns, "__ocml_pown_f32",
158 "__ocml_pown_f64", "__ocml_pown_f16");
159 // Single arith pattern that needs a ROCDL call, probably not
160 // worth creating a separate pass for it.
161 populateOpPatterns<arith::RemFOp>(converter, patterns, "__ocml_fmod_f32",
162 "__ocml_fmod_f64", "__ocml_fmod_f16");
163
164 if (chipset.has_value() && chipset->majorVersion >= 9) {
165 patterns.add<ClampFOpConversion>(converter);
166 } else {
167 LDBG() << "Chipset dependent patterns were not added";
168 }
169}
170
172 : impl::ConvertMathToROCDLBase<ConvertMathToROCDLPass> {
173 using impl::ConvertMathToROCDLBase<
174 ConvertMathToROCDLPass>::ConvertMathToROCDLBase;
175
176 void runOnOperation() override;
177};
178
180 auto m = getOperation();
181 MLIRContext *ctx = m.getContext();
182
183 RewritePatternSet patterns(&getContext());
185 LLVMTypeConverter converter(ctx, options);
186
187 FailureOr<amdgpu::Chipset> maybeChipset;
188 if (!chipset.empty()) {
189 maybeChipset = amdgpu::Chipset::parse(chipset);
190 if (failed(maybeChipset))
191 return signalPassFailure();
192 }
194 converter, patterns,
195 succeeded(maybeChipset) ? std::optional(*maybeChipset) : std::nullopt);
196
198 target
199 .addLegalDialect<BuiltinDialect, func::FuncDialect, vector::VectorDialect,
200 LLVM::LLVMDialect, ROCDL::ROCDLDialect>();
201 target.addIllegalOp<LLVM::CosOp, LLVM::ExpOp, LLVM::Exp2Op, LLVM::FAbsOp,
202 LLVM::FCeilOp, LLVM::FFloorOp, LLVM::FRemOp, LLVM::LogOp,
203 LLVM::Log10Op, LLVM::Log2Op, LLVM::PowOp, LLVM::SinOp,
204 LLVM::SqrtOp>();
205 if (failed(applyPartialConversion(m, target, std::move(patterns))))
206 signalPassFailure();
207}
return success()
b getContext())
static void populateOpPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, StringRef f32Func, StringRef f64Func, StringRef f16Func, StringRef f32ApproxFunc="")
static llvm::ManagedStatic< PassManagerOptions > options
ConvertOpToLLVMPattern(const LLVMTypeConverter &typeConverter, PatternBenefit benefit=1)
Definition Pattern.h:239
typename math::ClampFOp::Adaptor OpAdaptor
Definition Pattern.h:235
const LLVMTypeConverter * getTypeConverter() const
Definition Pattern.cpp:29
The main mechanism for performing data layout queries.
Conversion from types to the LLVM IR dialect.
Options to control the LLVM lowering.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
LogicalResult handleMultidimensionalVectors(Operation *op, ValueRange operands, const LLVMTypeConverter &typeConverter, std::function< Value(Type, ValueRange)> createOperand, ConversionPatternRewriter &rewriter)
Include the generated interface declarations.
void populateMathToROCDLConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, std::optional< amdgpu::Chipset > chipset)
Populate the given list with patterns that convert from Math to ROCDL calls.
ConvertOpToLLVMPattern(const LLVMTypeConverter &typeConverter, PatternBenefit benefit=1)
Definition Pattern.h:239
LogicalResult matchAndRewrite(math::ClampFOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
void runOnOperation() override
Rewriting that replaces SourceOp with a CallOp to f32Func or f64Func or f32ApproxFunc or f16Func or i...
Unrolls SourceOp to array/vector elements.
static FailureOr< Chipset > parse(StringRef name)
Parses the chipset version string and returns the chipset on success, and failure otherwise.
Definition Chipset.cpp:14