1995c3984SLei Zhang //===- MathToSPIRV.cpp - Math to SPIR-V Patterns --------------------------===//
2995c3984SLei Zhang //
3995c3984SLei Zhang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4995c3984SLei Zhang // See https://llvm.org/LICENSE.txt for license information.
5995c3984SLei Zhang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6995c3984SLei Zhang //
7995c3984SLei Zhang //===----------------------------------------------------------------------===//
8995c3984SLei Zhang //
9995c3984SLei Zhang // This file implements patterns to convert Math dialect to SPIR-V dialect.
10995c3984SLei Zhang //
11995c3984SLei Zhang //===----------------------------------------------------------------------===//
12995c3984SLei Zhang 
13a54f4eaeSMogball #include "../SPIRVCommon/Pattern.h"
14995c3984SLei Zhang #include "mlir/Dialect/Math/IR/Math.h"
15995c3984SLei Zhang #include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h"
16995c3984SLei Zhang #include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
17995c3984SLei Zhang #include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h"
18533ec929SLei Zhang #include "mlir/IR/BuiltinTypes.h"
19b9e642afSRobert Suderman #include "mlir/IR/TypeUtilities.h"
20cc020a22SLei Zhang #include "mlir/Transforms/DialectConversion.h"
21995c3984SLei Zhang #include "llvm/Support/Debug.h"
22995c3984SLei Zhang 
23995c3984SLei Zhang #define DEBUG_TYPE "math-to-spirv-pattern"
24995c3984SLei Zhang 
25995c3984SLei Zhang using namespace mlir;
26995c3984SLei Zhang 
27995c3984SLei Zhang //===----------------------------------------------------------------------===//
28cc020a22SLei Zhang // Utility functions
29cc020a22SLei Zhang //===----------------------------------------------------------------------===//
30cc020a22SLei Zhang 
31cc020a22SLei Zhang /// Creates a 32-bit scalar/vector integer constant. Returns nullptr if the
32cc020a22SLei Zhang /// given type is not a 32-bit scalar/vector type.
getScalarOrVectorI32Constant(Type type,int value,OpBuilder & builder,Location loc)33cc020a22SLei Zhang static Value getScalarOrVectorI32Constant(Type type, int value,
34cc020a22SLei Zhang                                           OpBuilder &builder, Location loc) {
35cc020a22SLei Zhang   if (auto vectorType = type.dyn_cast<VectorType>()) {
36cc020a22SLei Zhang     if (!vectorType.getElementType().isInteger(32))
37cc020a22SLei Zhang       return nullptr;
38cc020a22SLei Zhang     SmallVector<int> values(vectorType.getNumElements(), value);
39cc020a22SLei Zhang     return builder.create<spirv::ConstantOp>(loc, type,
40cc020a22SLei Zhang                                              builder.getI32VectorAttr(values));
41cc020a22SLei Zhang   }
42cc020a22SLei Zhang   if (type.isInteger(32))
43cc020a22SLei Zhang     return builder.create<spirv::ConstantOp>(loc, type,
44cc020a22SLei Zhang                                              builder.getI32IntegerAttr(value));
45cc020a22SLei Zhang 
46cc020a22SLei Zhang   return nullptr;
47cc020a22SLei Zhang }
48cc020a22SLei Zhang 
49cc020a22SLei Zhang //===----------------------------------------------------------------------===//
50995c3984SLei Zhang // Operation conversion
51995c3984SLei Zhang //===----------------------------------------------------------------------===//
52995c3984SLei Zhang 
53995c3984SLei Zhang // Note that DRR cannot be used for the patterns in this file: we may need to
54995c3984SLei Zhang // convert type along the way, which requires ConversionPattern. DRR generates
55995c3984SLei Zhang // normal RewritePattern.
56995c3984SLei Zhang 
57995c3984SLei Zhang namespace {
58533ec929SLei Zhang /// Converts math.copysign to SPIR-V ops.
59533ec929SLei Zhang class CopySignPattern final : public OpConversionPattern<math::CopySignOp> {
60533ec929SLei Zhang   using OpConversionPattern::OpConversionPattern;
61533ec929SLei Zhang 
62533ec929SLei Zhang   LogicalResult
matchAndRewrite(math::CopySignOp copySignOp,OpAdaptor adaptor,ConversionPatternRewriter & rewriter) const63533ec929SLei Zhang   matchAndRewrite(math::CopySignOp copySignOp, OpAdaptor adaptor,
64533ec929SLei Zhang                   ConversionPatternRewriter &rewriter) const override {
65533ec929SLei Zhang     auto type = getTypeConverter()->convertType(copySignOp.getType());
66533ec929SLei Zhang     if (!type)
67533ec929SLei Zhang       return failure();
68533ec929SLei Zhang 
69533ec929SLei Zhang     FloatType floatType;
70533ec929SLei Zhang     if (auto scalarType = copySignOp.getType().dyn_cast<FloatType>()) {
71533ec929SLei Zhang       floatType = scalarType;
72533ec929SLei Zhang     } else if (auto vectorType = copySignOp.getType().dyn_cast<VectorType>()) {
73533ec929SLei Zhang       floatType = vectorType.getElementType().cast<FloatType>();
74533ec929SLei Zhang     } else {
75533ec929SLei Zhang       return failure();
76533ec929SLei Zhang     }
77533ec929SLei Zhang 
78533ec929SLei Zhang     Location loc = copySignOp.getLoc();
79533ec929SLei Zhang     int bitwidth = floatType.getWidth();
80533ec929SLei Zhang     Type intType = rewriter.getIntegerType(bitwidth);
815f14aee3SStella Stamenova     uint64_t intValue = uint64_t(1) << (bitwidth - 1);
82533ec929SLei Zhang 
83533ec929SLei Zhang     Value signMask = rewriter.create<spirv::ConstantOp>(
845f14aee3SStella Stamenova         loc, intType, rewriter.getIntegerAttr(intType, intValue));
85533ec929SLei Zhang     Value valueMask = rewriter.create<spirv::ConstantOp>(
865f14aee3SStella Stamenova         loc, intType, rewriter.getIntegerAttr(intType, intValue - 1u));
87533ec929SLei Zhang 
88533ec929SLei Zhang     if (auto vectorType = copySignOp.getType().dyn_cast<VectorType>()) {
89533ec929SLei Zhang       assert(vectorType.getRank() == 1);
90533ec929SLei Zhang       int count = vectorType.getNumElements();
91533ec929SLei Zhang       intType = VectorType::get(count, intType);
92533ec929SLei Zhang 
93533ec929SLei Zhang       SmallVector<Value> signSplat(count, signMask);
94533ec929SLei Zhang       signMask =
95533ec929SLei Zhang           rewriter.create<spirv::CompositeConstructOp>(loc, intType, signSplat);
96533ec929SLei Zhang 
97533ec929SLei Zhang       SmallVector<Value> valueSplat(count, valueMask);
98533ec929SLei Zhang       valueMask = rewriter.create<spirv::CompositeConstructOp>(loc, intType,
99533ec929SLei Zhang                                                                valueSplat);
100533ec929SLei Zhang     }
101533ec929SLei Zhang 
102533ec929SLei Zhang     Value lhsCast =
103533ec929SLei Zhang         rewriter.create<spirv::BitcastOp>(loc, intType, adaptor.getLhs());
104533ec929SLei Zhang     Value rhsCast =
105533ec929SLei Zhang         rewriter.create<spirv::BitcastOp>(loc, intType, adaptor.getRhs());
106533ec929SLei Zhang 
107533ec929SLei Zhang     Value value = rewriter.create<spirv::BitwiseAndOp>(
108533ec929SLei Zhang         loc, intType, ValueRange{lhsCast, valueMask});
109533ec929SLei Zhang     Value sign = rewriter.create<spirv::BitwiseAndOp>(
110533ec929SLei Zhang         loc, intType, ValueRange{rhsCast, signMask});
111533ec929SLei Zhang 
112533ec929SLei Zhang     Value result = rewriter.create<spirv::BitwiseOrOp>(loc, intType,
113533ec929SLei Zhang                                                        ValueRange{value, sign});
114533ec929SLei Zhang     rewriter.replaceOpWithNewOp<spirv::BitcastOp>(copySignOp, type, result);
115533ec929SLei Zhang     return success();
116533ec929SLei Zhang   }
117533ec929SLei Zhang };
118533ec929SLei Zhang 
119cc020a22SLei Zhang /// Converts math.ctlz to SPIR-V ops.
120cc020a22SLei Zhang ///
121cc020a22SLei Zhang /// SPIR-V does not have a direct operations for counting leading zeros. If
122*52b630daSJakub Kuderski /// Shader capability is supported, we can leverage GL FindUMsb to calculate
123cc020a22SLei Zhang /// it.
124cc020a22SLei Zhang class CountLeadingZerosPattern final
125cc020a22SLei Zhang     : public OpConversionPattern<math::CountLeadingZerosOp> {
126cc020a22SLei Zhang   using OpConversionPattern::OpConversionPattern;
127cc020a22SLei Zhang 
128cc020a22SLei Zhang   LogicalResult
matchAndRewrite(math::CountLeadingZerosOp countOp,OpAdaptor adaptor,ConversionPatternRewriter & rewriter) const129cc020a22SLei Zhang   matchAndRewrite(math::CountLeadingZerosOp countOp, OpAdaptor adaptor,
130cc020a22SLei Zhang                   ConversionPatternRewriter &rewriter) const override {
131cc020a22SLei Zhang     auto type = getTypeConverter()->convertType(countOp.getType());
132cc020a22SLei Zhang     if (!type)
133cc020a22SLei Zhang       return failure();
134cc020a22SLei Zhang 
135cc020a22SLei Zhang     // We can only support 32-bit integer types for now.
136cc020a22SLei Zhang     unsigned bitwidth = 0;
137cc020a22SLei Zhang     if (type.isa<IntegerType>())
138cc020a22SLei Zhang       bitwidth = type.getIntOrFloatBitWidth();
139cc020a22SLei Zhang     if (auto vectorType = type.dyn_cast<VectorType>())
140cc020a22SLei Zhang       bitwidth = vectorType.getElementTypeBitWidth();
141cc020a22SLei Zhang     if (bitwidth != 32)
142cc020a22SLei Zhang       return failure();
143cc020a22SLei Zhang 
144cc020a22SLei Zhang     Location loc = countOp.getLoc();
1452320a4aeSLei Zhang     Value input = adaptor.getOperand();
1462320a4aeSLei Zhang     Value val1 = getScalarOrVectorI32Constant(type, 1, rewriter, loc);
147cc020a22SLei Zhang     Value val31 = getScalarOrVectorI32Constant(type, 31, rewriter, loc);
1482320a4aeSLei Zhang     Value val32 = getScalarOrVectorI32Constant(type, 32, rewriter, loc);
1492320a4aeSLei Zhang 
150*52b630daSJakub Kuderski     Value msb = rewriter.create<spirv::GLFindUMsbOp>(loc, input);
1512320a4aeSLei Zhang     // We need to subtract from 31 given that the index returned by GLSL
1522320a4aeSLei Zhang     // FindUMsb is counted from the least significant bit. Theoretically this
1532320a4aeSLei Zhang     // also gives the correct result even if the integer has all zero bits, in
154*52b630daSJakub Kuderski     // which case GL FindUMsb would return -1.
1552320a4aeSLei Zhang     Value subMsb = rewriter.create<spirv::ISubOp>(loc, val31, msb);
1562320a4aeSLei Zhang     // However, certain Vulkan implementations have driver bugs for the corner
1572320a4aeSLei Zhang     // case where the input is zero. And.. it can be smart to optimize a select
1582320a4aeSLei Zhang     // only involving the corner case. So separately compute the result when the
1592320a4aeSLei Zhang     // input is either zero or one.
1602320a4aeSLei Zhang     Value subInput = rewriter.create<spirv::ISubOp>(loc, val32, input);
1612320a4aeSLei Zhang     Value cmp = rewriter.create<spirv::ULessThanEqualOp>(loc, input, val1);
1622320a4aeSLei Zhang     rewriter.replaceOpWithNewOp<spirv::SelectOp>(countOp, cmp, subInput,
1632320a4aeSLei Zhang                                                  subMsb);
164cc020a22SLei Zhang     return success();
165cc020a22SLei Zhang   }
166cc020a22SLei Zhang };
167cc020a22SLei Zhang 
1683e746c6dSRob Suderman /// Converts math.expm1 to SPIR-V ops.
1693e746c6dSRob Suderman ///
1703e746c6dSRob Suderman /// SPIR-V does not have a direct operations for exp(x)-1. Explicitly lower to
1713e746c6dSRob Suderman /// these operations.
1723e746c6dSRob Suderman template <typename ExpOp>
173533ec929SLei Zhang struct ExpM1OpPattern final : public OpConversionPattern<math::ExpM1Op> {
174533ec929SLei Zhang   using OpConversionPattern::OpConversionPattern;
1753e746c6dSRob Suderman 
1763e746c6dSRob Suderman   LogicalResult
matchAndRewrite__anon99c81a7f0111::ExpM1OpPattern1773e746c6dSRob Suderman   matchAndRewrite(math::ExpM1Op operation, OpAdaptor adaptor,
1783e746c6dSRob Suderman                   ConversionPatternRewriter &rewriter) const override {
1793e746c6dSRob Suderman     assert(adaptor.getOperands().size() == 1);
1803e746c6dSRob Suderman     Location loc = operation.getLoc();
1813e746c6dSRob Suderman     auto type = this->getTypeConverter()->convertType(operation.getType());
1823e746c6dSRob Suderman     auto exp = rewriter.create<ExpOp>(loc, type, adaptor.getOperand());
1833e746c6dSRob Suderman     auto one = spirv::ConstantOp::getOne(type, loc, rewriter);
1843e746c6dSRob Suderman     rewriter.replaceOpWithNewOp<spirv::FSubOp>(operation, exp, one);
1853e746c6dSRob Suderman     return success();
1863e746c6dSRob Suderman   }
1873e746c6dSRob Suderman };
1883e746c6dSRob Suderman 
189995c3984SLei Zhang /// Converts math.log1p to SPIR-V ops.
190995c3984SLei Zhang ///
191995c3984SLei Zhang /// SPIR-V does not have a direct operations for log(1+x). Explicitly lower to
192995c3984SLei Zhang /// these operations.
19375a1bee0SButygin template <typename LogOp>
194533ec929SLei Zhang struct Log1pOpPattern final : public OpConversionPattern<math::Log1pOp> {
195533ec929SLei Zhang   using OpConversionPattern::OpConversionPattern;
196995c3984SLei Zhang 
197995c3984SLei Zhang   LogicalResult
matchAndRewrite__anon99c81a7f0111::Log1pOpPattern198b54c724bSRiver Riddle   matchAndRewrite(math::Log1pOp operation, OpAdaptor adaptor,
199995c3984SLei Zhang                   ConversionPatternRewriter &rewriter) const override {
200b54c724bSRiver Riddle     assert(adaptor.getOperands().size() == 1);
201995c3984SLei Zhang     Location loc = operation.getLoc();
2023e746c6dSRob Suderman     auto type = this->getTypeConverter()->convertType(operation.getType());
203995c3984SLei Zhang     auto one = spirv::ConstantOp::getOne(type, operation.getLoc(), rewriter);
204b54c724bSRiver Riddle     auto onePlus =
2053e746c6dSRob Suderman         rewriter.create<spirv::FAddOp>(loc, one, adaptor.getOperand());
20675a1bee0SButygin     rewriter.replaceOpWithNewOp<LogOp>(operation, type, onePlus);
207995c3984SLei Zhang     return success();
208995c3984SLei Zhang   }
209995c3984SLei Zhang };
21006c6758aSLei Zhang 
21106c6758aSLei Zhang /// Converts math.powf to SPIRV-Ops.
21206c6758aSLei Zhang struct PowFOpPattern final : public OpConversionPattern<math::PowFOp> {
21306c6758aSLei Zhang   using OpConversionPattern::OpConversionPattern;
21406c6758aSLei Zhang 
21506c6758aSLei Zhang   LogicalResult
matchAndRewrite__anon99c81a7f0111::PowFOpPattern21606c6758aSLei Zhang   matchAndRewrite(math::PowFOp powfOp, OpAdaptor adaptor,
21706c6758aSLei Zhang                   ConversionPatternRewriter &rewriter) const override {
21806c6758aSLei Zhang     auto dstType = getTypeConverter()->convertType(powfOp.getType());
21906c6758aSLei Zhang     if (!dstType)
22006c6758aSLei Zhang       return failure();
22106c6758aSLei Zhang 
222*52b630daSJakub Kuderski     // Per GL Pow extended instruction spec:
22306c6758aSLei Zhang     // "Result is undefined if x < 0. Result is undefined if x = 0 and y <= 0."
22406c6758aSLei Zhang     Location loc = powfOp.getLoc();
22506c6758aSLei Zhang     Value zero =
22606c6758aSLei Zhang         spirv::ConstantOp::getZero(adaptor.getLhs().getType(), loc, rewriter);
22706c6758aSLei Zhang     Value lessThan =
22806c6758aSLei Zhang         rewriter.create<spirv::FOrdLessThanOp>(loc, adaptor.getLhs(), zero);
229*52b630daSJakub Kuderski     Value abs = rewriter.create<spirv::GLFAbsOp>(loc, adaptor.getLhs());
230*52b630daSJakub Kuderski     Value pow = rewriter.create<spirv::GLPowOp>(loc, abs, adaptor.getRhs());
23106c6758aSLei Zhang     Value negate = rewriter.create<spirv::FNegateOp>(loc, pow);
23206c6758aSLei Zhang     rewriter.replaceOpWithNewOp<spirv::SelectOp>(powfOp, lessThan, negate, pow);
23306c6758aSLei Zhang     return success();
23406c6758aSLei Zhang   }
23506c6758aSLei Zhang };
23606c6758aSLei Zhang 
237b9e642afSRobert Suderman /// Converts math.round to GLSL SPIRV extended ops.
238b9e642afSRobert Suderman struct RoundOpPattern final : public OpConversionPattern<math::RoundOp> {
239b9e642afSRobert Suderman   using OpConversionPattern::OpConversionPattern;
240b9e642afSRobert Suderman 
241b9e642afSRobert Suderman   LogicalResult
matchAndRewrite__anon99c81a7f0111::RoundOpPattern242b9e642afSRobert Suderman   matchAndRewrite(math::RoundOp roundOp, OpAdaptor adaptor,
243b9e642afSRobert Suderman                   ConversionPatternRewriter &rewriter) const override {
244b9e642afSRobert Suderman     Location loc = roundOp.getLoc();
245b9e642afSRobert Suderman     auto operand = roundOp.getOperand();
246b9e642afSRobert Suderman     auto ty = operand.getType();
247b9e642afSRobert Suderman     auto ety = getElementTypeOrSelf(ty);
248b9e642afSRobert Suderman 
249b9e642afSRobert Suderman     auto zero = spirv::ConstantOp::getZero(ty, loc, rewriter);
250b9e642afSRobert Suderman     auto one = spirv::ConstantOp::getOne(ty, loc, rewriter);
251b9e642afSRobert Suderman     Value half;
252b9e642afSRobert Suderman     if (VectorType vty = ty.dyn_cast<VectorType>()) {
253b9e642afSRobert Suderman       half = rewriter.create<spirv::ConstantOp>(
254b9e642afSRobert Suderman           loc, vty,
255b9e642afSRobert Suderman           DenseElementsAttr::get(vty,
256b9e642afSRobert Suderman                                  rewriter.getFloatAttr(ety, 0.5).getValue()));
257b9e642afSRobert Suderman     } else {
258b9e642afSRobert Suderman       half = rewriter.create<spirv::ConstantOp>(
259b9e642afSRobert Suderman           loc, ty, rewriter.getFloatAttr(ety, 0.5));
260b9e642afSRobert Suderman     }
261b9e642afSRobert Suderman 
262*52b630daSJakub Kuderski     auto abs = rewriter.create<spirv::GLFAbsOp>(loc, operand);
263*52b630daSJakub Kuderski     auto floor = rewriter.create<spirv::GLFloorOp>(loc, abs);
264b9e642afSRobert Suderman     auto sub = rewriter.create<spirv::FSubOp>(loc, abs, floor);
265b9e642afSRobert Suderman     auto greater =
266b9e642afSRobert Suderman         rewriter.create<spirv::FOrdGreaterThanEqualOp>(loc, sub, half);
267b9e642afSRobert Suderman     auto select = rewriter.create<spirv::SelectOp>(loc, greater, one, zero);
268b9e642afSRobert Suderman     auto add = rewriter.create<spirv::FAddOp>(loc, floor, select);
269b9e642afSRobert Suderman     rewriter.replaceOpWithNewOp<math::CopySignOp>(roundOp, add, operand);
270b9e642afSRobert Suderman     return success();
271b9e642afSRobert Suderman   }
272b9e642afSRobert Suderman };
273b9e642afSRobert Suderman 
274995c3984SLei Zhang } // namespace
275995c3984SLei Zhang 
276995c3984SLei Zhang //===----------------------------------------------------------------------===//
277995c3984SLei Zhang // Pattern population
278995c3984SLei Zhang //===----------------------------------------------------------------------===//
279995c3984SLei Zhang 
280995c3984SLei Zhang namespace mlir {
populateMathToSPIRVPatterns(SPIRVTypeConverter & typeConverter,RewritePatternSet & patterns)281995c3984SLei Zhang void populateMathToSPIRVPatterns(SPIRVTypeConverter &typeConverter,
282995c3984SLei Zhang                                  RewritePatternSet &patterns) {
283533ec929SLei Zhang   // Core patterns
284533ec929SLei Zhang   patterns.add<CopySignPattern>(typeConverter, patterns.getContext());
28575a1bee0SButygin 
28675a1bee0SButygin   // GLSL patterns
287d9edc1a5SThomas Raoux   patterns
288*52b630daSJakub Kuderski       .add<CountLeadingZerosPattern, Log1pOpPattern<spirv::GLLogOp>,
289*52b630daSJakub Kuderski            ExpM1OpPattern<spirv::GLExpOp>, PowFOpPattern, RoundOpPattern,
290*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::AbsOp, spirv::GLFAbsOp>,
291*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::CeilOp, spirv::GLCeilOp>,
292*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::CosOp, spirv::GLCosOp>,
293*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::ExpOp, spirv::GLExpOp>,
294*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::FloorOp, spirv::GLFloorOp>,
295*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::FmaOp, spirv::GLFmaOp>,
296*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::LogOp, spirv::GLLogOp>,
297*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::RsqrtOp, spirv::GLInverseSqrtOp>,
298*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::SinOp, spirv::GLSinOp>,
299*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::SqrtOp, spirv::GLSqrtOp>,
300*52b630daSJakub Kuderski            spirv::ElementwiseOpPattern<math::TanhOp, spirv::GLTanhOp>>(
301995c3984SLei Zhang           typeConverter, patterns.getContext());
30275a1bee0SButygin 
30375a1bee0SButygin   // OpenCL patterns
3043930cc68SJakub Kuderski   patterns.add<Log1pOpPattern<spirv::CLLogOp>, ExpM1OpPattern<spirv::CLExpOp>,
3053930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::AbsOp, spirv::CLFAbsOp>,
3063930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::CeilOp, spirv::CLCeilOp>,
3073930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::CosOp, spirv::CLCosOp>,
3083930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::ErfOp, spirv::CLErfOp>,
3093930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::ExpOp, spirv::CLExpOp>,
3103930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::FloorOp, spirv::CLFloorOp>,
3113930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::FmaOp, spirv::CLFmaOp>,
3123930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::LogOp, spirv::CLLogOp>,
3133930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::PowFOp, spirv::CLPowOp>,
3143930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::RoundOp, spirv::CLRoundOp>,
3153930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::RsqrtOp, spirv::CLRsqrtOp>,
3163930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::SinOp, spirv::CLSinOp>,
3173930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::SqrtOp, spirv::CLSqrtOp>,
3183930cc68SJakub Kuderski                spirv::ElementwiseOpPattern<math::TanhOp, spirv::CLTanhOp>>(
31975a1bee0SButygin       typeConverter, patterns.getContext());
320995c3984SLei Zhang }
321995c3984SLei Zhang 
322995c3984SLei Zhang } // namespace mlir
323