21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/TypeSwitch.h"
23#include "llvm/Support/FormatVariadic.h"
25#define DEBUG_TYPE "math-to-spirv-pattern"
37 if (
auto vectorType = dyn_cast<VectorType>(type)) {
38 if (!vectorType.getElementType().isInteger(32))
41 return spirv::ConstantOp::create(builder, loc, type,
45 return spirv::ConstantOp::create(builder, loc, type,
58 if (
auto vecTy = dyn_cast<VectorType>(originalType)) {
59 if (!vecTy.getElementType().isIntOrIndexOrFloat())
61 if (vecTy.isScalable())
63 if (vecTy.getRank() > 1)
80 for (
Type ty : allTypes) {
82 return rewriter.notifyMatchFailure(
85 "unsupported source type for Math to SPIR-V conversion: {0}",
104template <
typename Op,
typename SPIRVOp>
105struct CheckedElementwiseOpPattern final
107 using BasePattern =
typename spirv::ElementwiseOpPattern<Op, SPIRVOp>;
108 using BasePattern::BasePattern;
111 matchAndRewrite(Op op,
typename Op::Adaptor adaptor,
112 ConversionPatternRewriter &rewriter)
const override {
116 return BasePattern::matchAndRewrite(op, adaptor, rewriter);
121struct CopySignPattern final :
public OpConversionPattern<math::CopySignOp> {
125 matchAndRewrite(math::CopySignOp copySignOp, OpAdaptor adaptor,
126 ConversionPatternRewriter &rewriter)
const override {
132 auto &typeConverter = *getTypeConverter<SPIRVTypeConverter>();
133 if (typeConverter.getTargetEnv().allows(spirv::Capability::Kernel))
134 return rewriter.notifyMatchFailure(copySignOp,
135 "Kernel target has native CL op");
137 Type type = getTypeConverter()->convertType(copySignOp.getType());
142 if (
auto scalarType = dyn_cast<FloatType>(copySignOp.getType())) {
143 floatType = scalarType;
144 }
else if (
auto vectorType = dyn_cast<VectorType>(copySignOp.getType())) {
145 floatType = cast<FloatType>(vectorType.getElementType());
150 Location loc = copySignOp.getLoc();
151 int bitwidth = floatType.getWidth();
152 Type intType = rewriter.getIntegerType(bitwidth);
153 uint64_t intValue = uint64_t(1) << (bitwidth - 1);
155 Value signMask = spirv::ConstantOp::create(
156 rewriter, loc, intType, rewriter.getIntegerAttr(intType, intValue));
157 Value valueMask = spirv::ConstantOp::create(
158 rewriter, loc, intType,
159 rewriter.getIntegerAttr(intType, intValue - 1u));
161 if (
auto vectorType = dyn_cast<VectorType>(type)) {
162 assert(vectorType.getRank() == 1);
163 int count = vectorType.getNumElements();
164 intType = VectorType::get(count, intType);
166 Repeated<Value> signSplat(count, signMask);
167 signMask = spirv::CompositeConstructOp::create(rewriter, loc, intType,
170 Repeated<Value> valueSplat(count, valueMask);
171 valueMask = spirv::CompositeConstructOp::create(rewriter, loc, intType,
176 spirv::BitcastOp::create(rewriter, loc, intType, adaptor.getLhs());
178 spirv::BitcastOp::create(rewriter, loc, intType, adaptor.getRhs());
180 Value value = spirv::BitwiseAndOp::create(rewriter, loc, intType,
182 Value sign = spirv::BitwiseAndOp::create(rewriter, loc, intType,
185 Value
result = spirv::BitwiseOrOp::create(rewriter, loc, intType,
187 rewriter.replaceOpWithNewOp<spirv::BitcastOp>(copySignOp, type,
result);
200struct CountLeadingZerosPattern final
201 :
public OpConversionPattern<math::CountLeadingZerosOp> {
205 matchAndRewrite(math::CountLeadingZerosOp countOp, OpAdaptor adaptor,
206 ConversionPatternRewriter &rewriter)
const override {
210 Type type = getTypeConverter()->convertType(countOp.getType());
214 auto &typeConverter = *getTypeConverter<SPIRVTypeConverter>();
215 if (!typeConverter.getTargetEnv().allows(spirv::Capability::Shader))
216 return rewriter.notifyMatchFailure(countOp,
"requires Shader capability");
219 unsigned bitwidth = 0;
220 if (isa<IntegerType>(type))
222 if (
auto vectorType = dyn_cast<VectorType>(type))
223 bitwidth = vectorType.getElementTypeBitWidth();
227 Location loc = countOp.getLoc();
228 Value input = adaptor.getOperand();
233 Value msb = spirv::GLFindUMsbOp::create(rewriter, loc, input);
238 Value subMsb = spirv::ISubOp::create(rewriter, loc, val31, msb);
243 Value subInput = spirv::ISubOp::create(rewriter, loc, val32, input);
244 Value cmp = spirv::ULessThanEqualOp::create(rewriter, loc, input, val1);
245 rewriter.replaceOpWithNewOp<spirv::SelectOp>(countOp, cmp, subInput,
254struct CountTrailingZerosPattern final
255 :
public OpConversionPattern<math::CountTrailingZerosOp> {
259 matchAndRewrite(math::CountTrailingZerosOp countOp, OpAdaptor adaptor,
260 ConversionPatternRewriter &rewriter)
const override {
264 Type type = getTypeConverter()->convertType(countOp.getType());
268 auto &typeConverter = *getTypeConverter<SPIRVTypeConverter>();
269 if (!typeConverter.getTargetEnv().allows(spirv::Capability::Shader))
270 return rewriter.notifyMatchFailure(countOp,
"requires Shader capability");
272 unsigned bitwidth = 0;
273 if (isa<IntegerType>(type))
275 else if (
auto vectorType = dyn_cast<VectorType>(type))
276 bitwidth = vectorType.getElementTypeBitWidth();
278 Location loc = countOp.getLoc();
279 Value input = adaptor.getOperand();
280 Value val0 = spirv::ConstantOp::getZero(type, loc, rewriter);
282 Attribute bwAttr = IntegerAttr::get(elemType, bitwidth);
283 if (
auto vecType = dyn_cast<VectorType>(type))
284 bwAttr = SplatElementsAttr::get(vecType, bwAttr);
285 Value valBitwidth = spirv::ConstantOp::create(rewriter, loc, type, bwAttr);
287 Value lsb = spirv::GLFindILsbOp::create(rewriter, loc, input);
288 Value isZero = spirv::IEqualOp::create(rewriter, loc, input, val0);
289 rewriter.replaceOpWithNewOp<spirv::SelectOp>(countOp, isZero, valBitwidth,
299template <
typename ExpOp>
300struct ExpM1OpPattern final :
public OpConversionPattern<math::ExpM1Op> {
304 matchAndRewrite(math::ExpM1Op operation, OpAdaptor adaptor,
305 ConversionPatternRewriter &rewriter)
const override {
306 assert(adaptor.getOperands().size() == 1);
311 Location loc = operation.getLoc();
312 Type type = this->getTypeConverter()->convertType(operation.getType());
316 Value exp = ExpOp::create(rewriter, loc, type, adaptor.getOperand());
317 auto one = spirv::ConstantOp::getOne(type, loc, rewriter);
318 rewriter.replaceOpWithNewOp<spirv::FSubOp>(operation, exp, one);
327template <
typename LogOp>
328struct Log1pOpPattern final :
public OpConversionPattern<math::Log1pOp> {
332 matchAndRewrite(math::Log1pOp operation, OpAdaptor adaptor,
333 ConversionPatternRewriter &rewriter)
const override {
334 assert(adaptor.getOperands().size() == 1);
339 Location loc = operation.getLoc();
340 Type type = this->getTypeConverter()->convertType(operation.getType());
344 auto one = spirv::ConstantOp::getOne(type, operation.getLoc(), rewriter);
346 spirv::FAddOp::create(rewriter, loc, one, adaptor.getOperand());
347 rewriter.replaceOpWithNewOp<LogOp>(operation, type, onePlus);
356struct Log10OpPattern final :
public OpConversionPattern<math::Log10Op> {
359 static constexpr double log10Reciprocal =
360 0.4342944819032518276511289189166050822943970058036665661144537832;
363 matchAndRewrite(math::Log10Op operation, OpAdaptor adaptor,
364 ConversionPatternRewriter &rewriter)
const override {
365 assert(adaptor.getOperands().size() == 1);
370 Location loc = operation.getLoc();
371 Type type = this->getTypeConverter()->convertType(operation.getType());
373 return rewriter.notifyMatchFailure(operation,
"type conversion failed");
375 auto getConstantValue = [&](
double value) {
376 if (
auto floatType = dyn_cast<FloatType>(type)) {
377 return spirv::ConstantOp::create(
378 rewriter, loc, type, rewriter.getFloatAttr(floatType, value));
380 if (
auto vectorType = dyn_cast<VectorType>(type)) {
381 Type elemType = vectorType.getElementType();
383 if (isa<FloatType>(elemType)) {
384 return spirv::ConstantOp::create(
387 vectorType, FloatAttr::get(elemType, value).getValue()));
390 llvm_unreachable(
"unimplemented type for log10");
393 Value constantValue = getConstantValue(log10Reciprocal);
394 Value log = spirv::GLLogOp::create(rewriter, loc, adaptor.getOperand());
395 rewriter.replaceOpWithNewOp<spirv::FMulOp>(operation, type, log,
402struct PowFOpPattern final :
public OpConversionPattern<math::PowFOp> {
406 matchAndRewrite(math::PowFOp powfOp, OpAdaptor adaptor,
407 ConversionPatternRewriter &rewriter)
const override {
411 Type dstType = getTypeConverter()->convertType(powfOp.getType());
415 Location loc = powfOp.getLoc();
416 Type operandType = adaptor.getRhs().getType();
421 auto isOdd = [](
const APFloat &v) {
424 v.convertToInteger(i, APFloat::rmTowardZero, &ignored);
428 SmallVector<bool> oddMask;
432 .Case([&](FloatAttr a) {
433 if (a.getValue().isInteger())
434 oddMask.push_back(isOdd(a.getValue()));
436 .Case([&](SplatElementsAttr a) {
438 if (splat.isInteger())
439 oddMask.push_back(isOdd(splat));
441 .Case([&](DenseElementsAttr a) {
442 SmallVector<bool> mask;
443 for (
const APFloat &elt : a.
getValues<APFloat>()) {
444 if (!elt.isInteger())
446 mask.push_back(isOdd(elt));
448 oddMask = std::move(mask);
452 if (oddMask.empty()) {
453 Value log = spirv::GLLogOp::create(rewriter, loc, adaptor.getLhs());
454 Value
mul = spirv::FMulOp::create(rewriter, loc, adaptor.getRhs(), log);
455 rewriter.replaceOpWithNewOp<spirv::GLExpOp>(powfOp,
mul);
461 Value
abs = spirv::GLFAbsOp::create(rewriter, loc, adaptor.getLhs());
462 Value pow = spirv::GLPowOp::create(rewriter, loc, abs, adaptor.getRhs());
465 if (llvm::none_of(oddMask, [](
bool b) {
return b; })) {
466 rewriter.replaceOp(powfOp, pow);
470 Value zero = spirv::ConstantOp::getZero(operandType, loc, rewriter);
472 spirv::FOrdLessThanOp::create(rewriter, loc, adaptor.getLhs(), zero);
473 Value negate = spirv::FNegateOp::create(rewriter, loc, pow);
476 if (llvm::all_equal(oddMask)) {
478 shouldNegate = lessThan;
482 auto vecType = cast<VectorType>(operandType);
483 auto maskType = VectorType::get(vecType.getShape(), rewriter.getI1Type());
484 Value oddConst = spirv::ConstantOp::create(
487 spirv::LogicalAndOp::create(rewriter, loc, lessThan, oddConst);
490 rewriter.replaceOpWithNewOp<spirv::SelectOp>(powfOp, shouldNegate, negate,
497struct PowIOpPattern final :
public OpConversionPattern<math::FPowIOp> {
501 matchAndRewrite(math::FPowIOp op, OpAdaptor adaptor,
502 ConversionPatternRewriter &rewriter)
const override {
506 Type dstType = getTypeConverter()->convertType(op.getType());
510 rewriter.replaceOpWithNewOp<spirv::CLPownOp>(op, dstType, adaptor.getLhs(),
520struct PowIOpGLPattern final :
public OpConversionPattern<math::FPowIOp> {
524 matchAndRewrite(math::FPowIOp op, OpAdaptor adaptor,
525 ConversionPatternRewriter &rewriter)
const override {
529 Type dstType = getTypeConverter()->convertType(op.getType());
533 Location loc = op.getLoc();
534 Value base = adaptor.getLhs();
535 Value power = adaptor.getRhs();
538 spirv::ConvertSToFOp::create(rewriter, loc, dstType, power);
539 Value
abs = spirv::GLFAbsOp::create(rewriter, loc, base);
540 Value pow = spirv::GLPowOp::create(rewriter, loc, abs, expFloat);
542 Value zeroF = spirv::ConstantOp::getZero(dstType, loc, rewriter);
543 Value lessThan = spirv::FOrdLessThanOp::create(rewriter, loc, base, zeroF);
545 Type powerType = power.
getType();
546 Value oneI = spirv::ConstantOp::getOne(powerType, loc, rewriter);
547 Value lowBit = spirv::BitwiseAndOp::create(rewriter, loc, power, oneI);
548 Value isOdd = spirv::IEqualOp::create(rewriter, loc, lowBit, oneI);
551 spirv::LogicalAndOp::create(rewriter, loc, lessThan, isOdd);
552 Value negate = spirv::FNegateOp::create(rewriter, loc, pow);
553 rewriter.replaceOpWithNewOp<spirv::SelectOp>(op, shouldNegate, negate, pow);
562template <
typename SinOp,
typename CosOp>
563struct SincosOpPattern final :
public OpConversionPattern<math::SincosOp> {
567 matchAndRewrite(math::SincosOp operation, OpAdaptor adaptor,
568 ConversionPatternRewriter &rewriter)
const override {
574 getTypeConverter()->convertType(operation.getOperand().getType());
578 Location loc = operation.getLoc();
579 Value sin = SinOp::create(rewriter, loc, type, adaptor.getOperand());
580 Value cos = CosOp::create(rewriter, loc, type, adaptor.getOperand());
581 rewriter.replaceOp(operation, {sin, cos});
587struct RoundOpPattern final :
public OpConversionPattern<math::RoundOp> {
591 matchAndRewrite(math::RoundOp roundOp, OpAdaptor adaptor,
592 ConversionPatternRewriter &rewriter)
const override {
596 Location loc = roundOp.getLoc();
597 auto ty = getTypeConverter()->convertType(adaptor.getOperand().getType());
599 return rewriter.notifyMatchFailure(
601 llvm::formatv(
"failed to convert type {0} for SPIR-V",
607 auto zero = spirv::ConstantOp::getZero(ty, loc, rewriter);
608 auto one = spirv::ConstantOp::getOne(ty, loc, rewriter);
610 if (VectorType vty = dyn_cast<VectorType>(ty)) {
611 half = spirv::ConstantOp::create(
614 rewriter.getFloatAttr(ety, 0.5).getValue()));
616 half = spirv::ConstantOp::create(rewriter, loc, ty,
617 rewriter.getFloatAttr(ety, 0.5));
620 auto abs = spirv::GLFAbsOp::create(rewriter, loc, adaptor.getOperand());
621 auto floor = spirv::GLFloorOp::create(rewriter, loc, abs);
622 auto sub = spirv::FSubOp::create(rewriter, loc, abs, floor);
624 spirv::FOrdGreaterThanEqualOp::create(rewriter, loc, sub, half);
625 auto select = spirv::SelectOp::create(rewriter, loc, greater, one, zero);
626 auto add = spirv::FAddOp::create(rewriter, loc, floor, select);
627 rewriter.replaceOpWithNewOp<math::CopySignOp>(roundOp,
add,
628 adaptor.getOperand());
644 .
add<CopySignPattern,
645 CheckedElementwiseOpPattern<math::CtPopOp, spirv::BitCountOp>,
646 CheckedElementwiseOpPattern<math::IsInfOp, spirv::IsInfOp>,
647 CheckedElementwiseOpPattern<math::IsNaNOp, spirv::IsNanOp>,
648 CheckedElementwiseOpPattern<math::IsFiniteOp, spirv::IsFiniteOp>,
649 CheckedElementwiseOpPattern<math::IsNormalOp, spirv::IsNormalOp>>(
654 .
add<CountLeadingZerosPattern, CountTrailingZerosPattern,
655 Log1pOpPattern<spirv::GLLogOp>, Log10OpPattern,
656 ExpM1OpPattern<spirv::GLExpOp>, PowFOpPattern, PowIOpGLPattern,
657 RoundOpPattern, SincosOpPattern<spirv::GLSinOp, spirv::GLCosOp>,
658 CheckedElementwiseOpPattern<math::AbsFOp, spirv::GLFAbsOp>,
659 CheckedElementwiseOpPattern<math::AbsIOp, spirv::GLSAbsOp>,
660 CheckedElementwiseOpPattern<math::AtanOp, spirv::GLAtanOp>,
661 CheckedElementwiseOpPattern<math::Atan2Op, spirv::GLAtan2Op>,
662 CheckedElementwiseOpPattern<math::CeilOp, spirv::GLCeilOp>,
663 CheckedElementwiseOpPattern<math::ClampFOp, spirv::GLFClampOp>,
664 CheckedElementwiseOpPattern<math::CosOp, spirv::GLCosOp>,
665 CheckedElementwiseOpPattern<math::ExpOp, spirv::GLExpOp>,
666 CheckedElementwiseOpPattern<math::Exp2Op, spirv::GLExp2Op>,
667 CheckedElementwiseOpPattern<math::FloorOp, spirv::GLFloorOp>,
668 CheckedElementwiseOpPattern<math::FmaOp, spirv::GLFmaOp>,
669 CheckedElementwiseOpPattern<math::LogOp, spirv::GLLogOp>,
670 CheckedElementwiseOpPattern<math::Log2Op, spirv::GLLog2Op>,
671 CheckedElementwiseOpPattern<math::RoundEvenOp, spirv::GLRoundEvenOp>,
672 CheckedElementwiseOpPattern<math::RsqrtOp, spirv::GLInverseSqrtOp>,
673 CheckedElementwiseOpPattern<math::SinOp, spirv::GLSinOp>,
674 CheckedElementwiseOpPattern<math::SqrtOp, spirv::GLSqrtOp>,
675 CheckedElementwiseOpPattern<math::TanhOp, spirv::GLTanhOp>,
676 CheckedElementwiseOpPattern<math::TanOp, spirv::GLTanOp>,
677 CheckedElementwiseOpPattern<math::TruncOp, spirv::GLTruncOp>,
678 CheckedElementwiseOpPattern<math::AsinOp, spirv::GLAsinOp>,
679 CheckedElementwiseOpPattern<math::AcosOp, spirv::GLAcosOp>,
680 CheckedElementwiseOpPattern<math::SinhOp, spirv::GLSinhOp>,
681 CheckedElementwiseOpPattern<math::CoshOp, spirv::GLCoshOp>,
682 CheckedElementwiseOpPattern<math::AsinhOp, spirv::GLAsinhOp>,
683 CheckedElementwiseOpPattern<math::AcoshOp, spirv::GLAcoshOp>,
684 CheckedElementwiseOpPattern<math::AtanhOp, spirv::GLAtanhOp>>(
689 Log1pOpPattern<spirv::CLLogOp>, ExpM1OpPattern<spirv::CLExpOp>,
690 SincosOpPattern<spirv::CLSinOp, spirv::CLCosOp>,
691 CheckedElementwiseOpPattern<math::AbsFOp, spirv::CLFAbsOp>,
692 CheckedElementwiseOpPattern<math::AbsIOp, spirv::CLSAbsOp>,
693 CheckedElementwiseOpPattern<math::CountLeadingZerosOp, spirv::CLClzOp>,
694 CheckedElementwiseOpPattern<math::AtanOp, spirv::CLAtanOp>,
695 CheckedElementwiseOpPattern<math::Atan2Op, spirv::CLAtan2Op>,
696 CheckedElementwiseOpPattern<math::CbrtOp, spirv::CLCbrtOp>,
697 CheckedElementwiseOpPattern<math::CeilOp, spirv::CLCeilOp>,
698 CheckedElementwiseOpPattern<math::CopySignOp, spirv::CLCopysignOp>,
699 CheckedElementwiseOpPattern<math::CosOp, spirv::CLCosOp>,
700 CheckedElementwiseOpPattern<math::ErfOp, spirv::CLErfOp>,
701 CheckedElementwiseOpPattern<math::ErfcOp, spirv::CLErfcOp>,
702 CheckedElementwiseOpPattern<math::ExpOp, spirv::CLExpOp>,
703 CheckedElementwiseOpPattern<math::Exp2Op, spirv::CLExp2Op>,
704 CheckedElementwiseOpPattern<math::FloorOp, spirv::CLFloorOp>,
705 CheckedElementwiseOpPattern<math::FmaOp, spirv::CLFmaOp>,
706 CheckedElementwiseOpPattern<math::LogOp, spirv::CLLogOp>,
707 CheckedElementwiseOpPattern<math::Log2Op, spirv::CLLog2Op>,
708 CheckedElementwiseOpPattern<math::Log10Op, spirv::CLLog10Op>,
709 CheckedElementwiseOpPattern<math::PowFOp, spirv::CLPowOp>, PowIOpPattern,
710 CheckedElementwiseOpPattern<math::RoundEvenOp, spirv::CLRintOp>,
711 CheckedElementwiseOpPattern<math::RoundOp, spirv::CLRoundOp>,
712 CheckedElementwiseOpPattern<math::RsqrtOp, spirv::CLRsqrtOp>,
713 CheckedElementwiseOpPattern<math::SinOp, spirv::CLSinOp>,
714 CheckedElementwiseOpPattern<math::SqrtOp, spirv::CLSqrtOp>,
715 CheckedElementwiseOpPattern<math::TanhOp, spirv::CLTanhOp>,
716 CheckedElementwiseOpPattern<math::TanOp, spirv::CLTanOp>,
717 CheckedElementwiseOpPattern<math::TruncOp, spirv::CLTruncOp>,
718 CheckedElementwiseOpPattern<math::AsinOp, spirv::CLAsinOp>,
719 CheckedElementwiseOpPattern<math::AcosOp, spirv::CLAcosOp>,
720 CheckedElementwiseOpPattern<math::SinhOp, spirv::CLSinhOp>,
721 CheckedElementwiseOpPattern<math::CoshOp, spirv::CLCoshOp>,
722 CheckedElementwiseOpPattern<math::AsinhOp, spirv::CLAsinhOp>,
723 CheckedElementwiseOpPattern<math::AcoshOp, spirv::CLAcoshOp>,
724 CheckedElementwiseOpPattern<math::AtanhOp, spirv::CLAtanhOp>>(
static LogicalResult checkSourceOpTypes(ConversionPatternRewriter &rewriter, Operation *sourceOp)
Check if all sourceOp types are supported by math-to-spirv conversion.
static bool isSupportedSourceType(Type originalType)
Check if the type is supported by math-to-spirv conversion.
static Value getScalarOrVectorI32Constant(Type type, int value, OpBuilder &builder, Location loc)
Creates a 32-bit scalar/vector integer constant.
IntegerAttr getI32IntegerAttr(int32_t value)
DenseIntElementsAttr getI32VectorAttr(ArrayRef< int32_t > values)
auto getValues() const
Return the held element values as a range of the given type.
std::enable_if_t<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T > getSplatValue() const
Return the splat value for this attribute.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
static DenseFPElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseFPElementsAttr with the given arguments.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
operand_type_range getOperandTypes()
result_type_range getResultTypes()
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Type conversion from builtin types to SPIR-V types for shader interface.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isIntOrIndexOrFloat() const
Return true if this is an integer (of any signedness), index, or float type.
bool isInteger() const
Return true if this is an integer type (with the specified width).
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
DynamicAPInt floor(const Fraction &f)
Fraction abs(const Fraction &f)
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
void populateMathToSPIRVPatterns(const SPIRVTypeConverter &typeConverter, RewritePatternSet &patterns)
Appends to a pattern list additional patterns for translating Math ops to SPIR-V ops.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
llvm::TypeSwitch< T, ResultT > TypeSwitch
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
Converts elementwise unary, binary and ternary standard operations to SPIR-V operations.