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,
256struct CountTrailingZerosPattern final
257 :
public OpConversionPattern<math::CountTrailingZerosOp> {
261 matchAndRewrite(math::CountTrailingZerosOp countOp, OpAdaptor adaptor,
262 ConversionPatternRewriter &rewriter)
const override {
266 Type type = getTypeConverter()->convertType(countOp.getType());
270 auto &typeConverter = *getTypeConverter<SPIRVTypeConverter>();
271 if (!typeConverter.getTargetEnv().allows(spirv::Capability::Shader))
272 return rewriter.notifyMatchFailure(countOp,
"requires Shader capability");
274 unsigned bitwidth = 0;
275 if (isa<IntegerType>(type))
277 else if (
auto vectorType = dyn_cast<VectorType>(type))
278 bitwidth = vectorType.getElementTypeBitWidth();
280 Location loc = countOp.getLoc();
281 Value input = adaptor.getOperand();
282 Value val0 = spirv::ConstantOp::getZero(type, loc, rewriter);
284 Attribute bwAttr = IntegerAttr::get(elemType, bitwidth);
285 if (
auto vecType = dyn_cast<VectorType>(type))
286 bwAttr = SplatElementsAttr::get(vecType, bwAttr);
287 Value valBitwidth = spirv::ConstantOp::create(rewriter, loc, type, bwAttr);
289 Value lsb = spirv::GLFindILsbOp::create(rewriter, loc, input);
290 Value isZero = spirv::IEqualOp::create(rewriter, loc, input, val0);
291 rewriter.replaceOpWithNewOp<spirv::SelectOp>(countOp, isZero, valBitwidth,
299struct CountTrailingZerosOpenCLPattern final
300 :
public OpConversionPattern<math::CountTrailingZerosOp> {
304 matchAndRewrite(math::CountTrailingZerosOp op, OpAdaptor adaptor,
305 ConversionPatternRewriter &rewriter)
const override {
309 auto &typeConverter = *getTypeConverter<SPIRVTypeConverter>();
310 if (!typeConverter.getTargetEnv().allows(spirv::Capability::Kernel))
311 return rewriter.notifyMatchFailure(op,
"requires Kernel capability");
312 Type type = typeConverter.convertType(op.getType());
316 Value input = adaptor.getOperand();
320 rewriter.replaceOpWithNewOp<spirv::LogicalNotOp>(op, type, input);
327 unsigned sourceWidth = sourceElementType.
isIndex()
330 if (sourceWidth < targetWidth) {
334 Attribute sentinel = IntegerAttr::get(
335 elementType, APInt::getOneBitSet(targetWidth, sourceWidth));
336 if (
auto vectorType = dyn_cast<VectorType>(type))
337 sentinel = SplatElementsAttr::get(vectorType, sentinel);
339 spirv::ConstantOp::create(rewriter, op.getLoc(), type, sentinel);
340 input = spirv::BitwiseOrOp::create(rewriter, op.getLoc(), input, mask);
342 rewriter.replaceOpWithNewOp<spirv::CLCtzOp>(op, type, input);
351template <
typename ExpOp>
352struct ExpM1OpPattern final :
public OpConversionPattern<math::ExpM1Op> {
356 matchAndRewrite(math::ExpM1Op operation, OpAdaptor adaptor,
357 ConversionPatternRewriter &rewriter)
const override {
358 assert(adaptor.getOperands().size() == 1);
363 Location loc = operation.getLoc();
364 Type type = this->getTypeConverter()->convertType(operation.getType());
368 Value exp = ExpOp::create(rewriter, loc, type, adaptor.getOperand());
369 auto one = spirv::ConstantOp::getOne(type, loc, rewriter);
370 rewriter.replaceOpWithNewOp<spirv::FSubOp>(operation, exp, one);
379template <
typename LogOp>
380struct Log1pOpPattern final :
public OpConversionPattern<math::Log1pOp> {
384 matchAndRewrite(math::Log1pOp operation, OpAdaptor adaptor,
385 ConversionPatternRewriter &rewriter)
const override {
386 assert(adaptor.getOperands().size() == 1);
391 Location loc = operation.getLoc();
392 Type type = this->getTypeConverter()->convertType(operation.getType());
396 auto one = spirv::ConstantOp::getOne(type, operation.getLoc(), rewriter);
398 spirv::FAddOp::create(rewriter, loc, one, adaptor.getOperand());
399 rewriter.replaceOpWithNewOp<LogOp>(operation, type, onePlus);
408struct Log10OpPattern final :
public OpConversionPattern<math::Log10Op> {
411 static constexpr double log10Reciprocal =
412 0.4342944819032518276511289189166050822943970058036665661144537832;
415 matchAndRewrite(math::Log10Op operation, OpAdaptor adaptor,
416 ConversionPatternRewriter &rewriter)
const override {
417 assert(adaptor.getOperands().size() == 1);
422 Location loc = operation.getLoc();
423 Type type = this->getTypeConverter()->convertType(operation.getType());
425 return rewriter.notifyMatchFailure(operation,
"type conversion failed");
427 auto getConstantValue = [&](
double value) {
428 if (
auto floatType = dyn_cast<FloatType>(type)) {
429 return spirv::ConstantOp::create(
430 rewriter, loc, type, rewriter.getFloatAttr(floatType, value));
432 if (
auto vectorType = dyn_cast<VectorType>(type)) {
433 Type elemType = vectorType.getElementType();
435 if (isa<FloatType>(elemType)) {
436 return spirv::ConstantOp::create(
439 vectorType, FloatAttr::get(elemType, value).getValue()));
442 llvm_unreachable(
"unimplemented type for log10");
445 Value constantValue = getConstantValue(log10Reciprocal);
446 Value log = spirv::GLLogOp::create(rewriter, loc, adaptor.getOperand());
447 rewriter.replaceOpWithNewOp<spirv::FMulOp>(operation, type, log,
454struct PowFOpPattern final :
public OpConversionPattern<math::PowFOp> {
458 matchAndRewrite(math::PowFOp powfOp, OpAdaptor adaptor,
459 ConversionPatternRewriter &rewriter)
const override {
463 Type dstType = getTypeConverter()->convertType(powfOp.getType());
467 Location loc = powfOp.getLoc();
468 Type operandType = adaptor.getRhs().getType();
473 auto isOdd = [](
const APFloat &v) {
476 v.convertToInteger(i, APFloat::rmTowardZero, &ignored);
480 SmallVector<bool> oddMask;
484 .Case([&](FloatAttr a) {
485 if (a.getValue().isInteger())
486 oddMask.push_back(isOdd(a.getValue()));
488 .Case([&](SplatElementsAttr a) {
490 if (splat.isInteger())
491 oddMask.push_back(isOdd(splat));
493 .Case([&](DenseElementsAttr a) {
494 SmallVector<bool> mask;
495 for (
const APFloat &elt : a.
getValues<APFloat>()) {
496 if (!elt.isInteger())
498 mask.push_back(isOdd(elt));
500 oddMask = std::move(mask);
504 if (oddMask.empty()) {
505 Value log = spirv::GLLogOp::create(rewriter, loc, adaptor.getLhs());
506 Value
mul = spirv::FMulOp::create(rewriter, loc, adaptor.getRhs(), log);
507 rewriter.replaceOpWithNewOp<spirv::GLExpOp>(powfOp,
mul);
513 Value
abs = spirv::GLFAbsOp::create(rewriter, loc, adaptor.getLhs());
514 Value pow = spirv::GLPowOp::create(rewriter, loc, abs, adaptor.getRhs());
517 if (llvm::none_of(oddMask, [](
bool b) {
return b; })) {
518 rewriter.replaceOp(powfOp, pow);
522 Value zero = spirv::ConstantOp::getZero(operandType, loc, rewriter);
524 spirv::FOrdLessThanOp::create(rewriter, loc, adaptor.getLhs(), zero);
525 Value negate = spirv::FNegateOp::create(rewriter, loc, pow);
528 if (llvm::all_equal(oddMask)) {
530 shouldNegate = lessThan;
534 auto vecType = cast<VectorType>(operandType);
535 auto maskType = VectorType::get(vecType.getShape(), rewriter.getI1Type());
536 Value oddConst = spirv::ConstantOp::create(
539 spirv::LogicalAndOp::create(rewriter, loc, lessThan, oddConst);
542 rewriter.replaceOpWithNewOp<spirv::SelectOp>(powfOp, shouldNegate, negate,
549struct PowIOpPattern final :
public OpConversionPattern<math::FPowIOp> {
553 matchAndRewrite(math::FPowIOp op, OpAdaptor adaptor,
554 ConversionPatternRewriter &rewriter)
const override {
558 Type dstType = getTypeConverter()->convertType(op.getType());
562 rewriter.replaceOpWithNewOp<spirv::CLPownOp>(op, dstType, adaptor.getLhs(),
572struct PowIOpGLPattern final :
public OpConversionPattern<math::FPowIOp> {
576 matchAndRewrite(math::FPowIOp op, OpAdaptor adaptor,
577 ConversionPatternRewriter &rewriter)
const override {
581 Type dstType = getTypeConverter()->convertType(op.getType());
585 Location loc = op.getLoc();
586 Value base = adaptor.getLhs();
587 Value power = adaptor.getRhs();
590 spirv::ConvertSToFOp::create(rewriter, loc, dstType, power);
591 Value
abs = spirv::GLFAbsOp::create(rewriter, loc, base);
592 Value pow = spirv::GLPowOp::create(rewriter, loc, abs, expFloat);
594 Value zeroF = spirv::ConstantOp::getZero(dstType, loc, rewriter);
595 Value lessThan = spirv::FOrdLessThanOp::create(rewriter, loc, base, zeroF);
597 Type powerType = power.
getType();
598 Value oneI = spirv::ConstantOp::getOne(powerType, loc, rewriter);
599 Value lowBit = spirv::BitwiseAndOp::create(rewriter, loc, power, oneI);
600 Value isOdd = spirv::IEqualOp::create(rewriter, loc, lowBit, oneI);
603 spirv::LogicalAndOp::create(rewriter, loc, lessThan, isOdd);
604 Value negate = spirv::FNegateOp::create(rewriter, loc, pow);
605 rewriter.replaceOpWithNewOp<spirv::SelectOp>(op, shouldNegate, negate, pow);
614template <
typename SinOp,
typename CosOp>
615struct SincosOpPattern final :
public OpConversionPattern<math::SincosOp> {
619 matchAndRewrite(math::SincosOp operation, OpAdaptor adaptor,
620 ConversionPatternRewriter &rewriter)
const override {
626 getTypeConverter()->convertType(operation.getOperand().getType());
630 Location loc = operation.getLoc();
631 Value sin = SinOp::create(rewriter, loc, type, adaptor.getOperand());
632 Value cos = CosOp::create(rewriter, loc, type, adaptor.getOperand());
633 rewriter.replaceOp(operation, {sin, cos});
639struct RoundOpPattern final :
public OpConversionPattern<math::RoundOp> {
643 matchAndRewrite(math::RoundOp roundOp, OpAdaptor adaptor,
644 ConversionPatternRewriter &rewriter)
const override {
648 Location loc = roundOp.getLoc();
649 auto ty = getTypeConverter()->convertType(adaptor.getOperand().getType());
651 return rewriter.notifyMatchFailure(
653 llvm::formatv(
"failed to convert type {0} for SPIR-V",
659 auto zero = spirv::ConstantOp::getZero(ty, loc, rewriter);
660 auto one = spirv::ConstantOp::getOne(ty, loc, rewriter);
662 if (VectorType vty = dyn_cast<VectorType>(ty)) {
663 half = spirv::ConstantOp::create(
666 rewriter.getFloatAttr(ety, 0.5).getValue()));
668 half = spirv::ConstantOp::create(rewriter, loc, ty,
669 rewriter.getFloatAttr(ety, 0.5));
672 auto abs = spirv::GLFAbsOp::create(rewriter, loc, adaptor.getOperand());
673 auto floor = spirv::GLFloorOp::create(rewriter, loc, abs);
674 auto sub = spirv::FSubOp::create(rewriter, loc, abs, floor);
676 spirv::FOrdGreaterThanEqualOp::create(rewriter, loc, sub, half);
677 auto select = spirv::SelectOp::create(rewriter, loc, greater, one, zero);
678 auto add = spirv::FAddOp::create(rewriter, loc, floor, select);
679 rewriter.replaceOpWithNewOp<math::CopySignOp>(roundOp,
add,
680 adaptor.getOperand());
695 .
add<CopySignPattern,
696 CheckedElementwiseOpPattern<math::CtPopOp, spirv::BitCountOp>,
697 CheckedElementwiseOpPattern<math::IsInfOp, spirv::IsInfOp>,
698 CheckedElementwiseOpPattern<math::IsNaNOp, spirv::IsNanOp>,
699 CheckedElementwiseOpPattern<math::IsFiniteOp, spirv::IsFiniteOp>,
700 CheckedElementwiseOpPattern<math::IsNormalOp, spirv::IsNormalOp>>(
705 .
add<CountLeadingZerosPattern, CountTrailingZerosPattern,
706 Log1pOpPattern<spirv::GLLogOp>, Log10OpPattern,
707 ExpM1OpPattern<spirv::GLExpOp>, PowFOpPattern, PowIOpGLPattern,
708 RoundOpPattern, SincosOpPattern<spirv::GLSinOp, spirv::GLCosOp>,
709 CheckedElementwiseOpPattern<math::AbsFOp, spirv::GLFAbsOp>,
710 CheckedElementwiseOpPattern<math::AbsIOp, spirv::GLSAbsOp>,
711 CheckedElementwiseOpPattern<math::AtanOp, spirv::GLAtanOp>,
712 CheckedElementwiseOpPattern<math::Atan2Op, spirv::GLAtan2Op>,
713 CheckedElementwiseOpPattern<math::CeilOp, spirv::GLCeilOp>,
714 CheckedElementwiseOpPattern<math::ClampFOp, spirv::GLFClampOp>,
715 CheckedElementwiseOpPattern<math::CosOp, spirv::GLCosOp>,
716 CheckedElementwiseOpPattern<math::ExpOp, spirv::GLExpOp>,
717 CheckedElementwiseOpPattern<math::Exp2Op, spirv::GLExp2Op>,
718 CheckedElementwiseOpPattern<math::FloorOp, spirv::GLFloorOp>,
719 CheckedElementwiseOpPattern<math::FmaOp, spirv::GLFmaOp>,
720 CheckedElementwiseOpPattern<math::LogOp, spirv::GLLogOp>,
721 CheckedElementwiseOpPattern<math::Log2Op, spirv::GLLog2Op>,
722 CheckedElementwiseOpPattern<math::RoundEvenOp, spirv::GLRoundEvenOp>,
723 CheckedElementwiseOpPattern<math::RsqrtOp, spirv::GLInverseSqrtOp>,
724 CheckedElementwiseOpPattern<math::SinOp, spirv::GLSinOp>,
725 CheckedElementwiseOpPattern<math::SqrtOp, spirv::GLSqrtOp>,
726 CheckedElementwiseOpPattern<math::TanhOp, spirv::GLTanhOp>,
727 CheckedElementwiseOpPattern<math::TanOp, spirv::GLTanOp>,
728 CheckedElementwiseOpPattern<math::TruncOp, spirv::GLTruncOp>,
729 CheckedElementwiseOpPattern<math::AsinOp, spirv::GLAsinOp>,
730 CheckedElementwiseOpPattern<math::AcosOp, spirv::GLAcosOp>,
731 CheckedElementwiseOpPattern<math::SinhOp, spirv::GLSinhOp>,
732 CheckedElementwiseOpPattern<math::CoshOp, spirv::GLCoshOp>,
733 CheckedElementwiseOpPattern<math::AsinhOp, spirv::GLAsinhOp>,
734 CheckedElementwiseOpPattern<math::AcoshOp, spirv::GLAcoshOp>,
735 CheckedElementwiseOpPattern<math::AtanhOp, spirv::GLAtanhOp>>(
740 Log1pOpPattern<spirv::CLLogOp>, ExpM1OpPattern<spirv::CLExpOp>,
741 SincosOpPattern<spirv::CLSinOp, spirv::CLCosOp>,
742 CheckedElementwiseOpPattern<math::AbsFOp, spirv::CLFAbsOp>,
743 CheckedElementwiseOpPattern<math::AbsIOp, spirv::CLSAbsOp>,
744 CheckedElementwiseOpPattern<math::CountLeadingZerosOp, spirv::CLClzOp>,
745 CountTrailingZerosOpenCLPattern,
746 CheckedElementwiseOpPattern<math::AtanOp, spirv::CLAtanOp>,
747 CheckedElementwiseOpPattern<math::Atan2Op, spirv::CLAtan2Op>,
748 CheckedElementwiseOpPattern<math::CbrtOp, spirv::CLCbrtOp>,
749 CheckedElementwiseOpPattern<math::CeilOp, spirv::CLCeilOp>,
750 CheckedElementwiseOpPattern<math::CopySignOp, spirv::CLCopysignOp>,
751 CheckedElementwiseOpPattern<math::CosOp, spirv::CLCosOp>,
752 CheckedElementwiseOpPattern<math::ErfOp, spirv::CLErfOp>,
753 CheckedElementwiseOpPattern<math::ErfcOp, spirv::CLErfcOp>,
754 CheckedElementwiseOpPattern<math::ExpOp, spirv::CLExpOp>,
755 CheckedElementwiseOpPattern<math::Exp2Op, spirv::CLExp2Op>,
756 CheckedElementwiseOpPattern<math::FloorOp, spirv::CLFloorOp>,
757 CheckedElementwiseOpPattern<math::FmaOp, spirv::CLFmaOp>,
758 CheckedElementwiseOpPattern<math::LogOp, spirv::CLLogOp>,
759 CheckedElementwiseOpPattern<math::Log2Op, spirv::CLLog2Op>,
760 CheckedElementwiseOpPattern<math::Log10Op, spirv::CLLog10Op>,
761 CheckedElementwiseOpPattern<math::PowFOp, spirv::CLPowOp>, PowIOpPattern,
762 CheckedElementwiseOpPattern<math::RoundEvenOp, spirv::CLRintOp>,
763 CheckedElementwiseOpPattern<math::RoundOp, spirv::CLRoundOp>,
764 CheckedElementwiseOpPattern<math::RsqrtOp, spirv::CLRsqrtOp>,
765 CheckedElementwiseOpPattern<math::SinOp, spirv::CLSinOp>,
766 CheckedElementwiseOpPattern<math::SqrtOp, spirv::CLSqrtOp>,
767 CheckedElementwiseOpPattern<math::TanhOp, spirv::CLTanhOp>,
768 CheckedElementwiseOpPattern<math::TanOp, spirv::CLTanOp>,
769 CheckedElementwiseOpPattern<math::TruncOp, spirv::CLTruncOp>,
770 CheckedElementwiseOpPattern<math::AsinOp, spirv::CLAsinOp>,
771 CheckedElementwiseOpPattern<math::AcosOp, spirv::CLAcosOp>,
772 CheckedElementwiseOpPattern<math::SinhOp, spirv::CLSinhOp>,
773 CheckedElementwiseOpPattern<math::CoshOp, spirv::CLCoshOp>,
774 CheckedElementwiseOpPattern<math::AsinhOp, spirv::CLAsinhOp>,
775 CheckedElementwiseOpPattern<math::AcoshOp, spirv::CLAcoshOp>,
776 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.