32#include "llvm/ADT/APFloat.h"
33#include "llvm/IR/LLVMContext.h"
34#include "llvm/Support/Casting.h"
46 assert(rank > 0 &&
"0-D vector corner case should have been handled already");
48 auto idxType = rewriter.getIndexType();
49 auto constant = LLVM::ConstantOp::create(
50 rewriter, loc, typeConverter.convertType(idxType),
51 rewriter.getIntegerAttr(idxType, pos));
52 return LLVM::InsertElementOp::create(rewriter, loc, llvmType, val1, val2,
55 return LLVM::InsertValueOp::create(rewriter, loc, val1, val2, pos);
63 auto idxType = rewriter.getIndexType();
64 auto constant = LLVM::ConstantOp::create(
65 rewriter, loc, typeConverter.convertType(idxType),
66 rewriter.getIntegerAttr(idxType, pos));
67 return LLVM::ExtractElementOp::create(rewriter, loc, llvmType, val,
70 return LLVM::ExtractValueOp::create(rewriter, loc, val, pos);
75 VectorType vectorType,
unsigned &align) {
76 Type convertedVectorTy = typeConverter.convertType(vectorType);
77 if (!convertedVectorTy)
80 llvm::LLVMContext llvmContext;
90 MemRefType memrefType,
unsigned &align) {
91 Type elementTy = typeConverter.convertType(memrefType.getElementType());
97 llvm::LLVMContext llvmContext;
110 VectorType vectorType,
111 MemRefType memrefType,
unsigned &align,
112 bool useVectorAlignment) {
113 if (useVectorAlignment) {
128 if (!memRefType.isLastDimUnitStride())
138 MemRefType memRefType,
Value llvmMemref,
Value base,
141 "unsupported memref type");
142 assert(vectorType.getRank() == 1 &&
"expected a 1-d vector type");
146 vectorType.getScalableDims()[0]);
147 return LLVM::GEPOp::create(
148 rewriter, loc, ptrsType,
149 typeConverter.convertType(memRefType.getElementType()), base,
index);
156 if (
auto attr = dyn_cast<Attribute>(foldResult)) {
157 auto intAttr = cast<IntegerAttr>(attr);
158 return LLVM::ConstantOp::create(builder, loc, intAttr).getResult();
161 return cast<Value>(foldResult);
167using VectorScaleOpConversion =
171class VectorBitCastOpConversion
174 using ConvertOpToLLVMPattern<vector::BitCastOp>::ConvertOpToLLVMPattern;
177 matchAndRewrite(vector::BitCastOp bitCastOp, OpAdaptor adaptor,
178 ConversionPatternRewriter &rewriter)
const override {
180 VectorType resultTy = bitCastOp.getResultVectorType();
181 if (resultTy.getRank() > 1)
183 Type newResultTy = typeConverter->convertType(resultTy);
184 rewriter.replaceOpWithNewOp<LLVM::BitcastOp>(bitCastOp, newResultTy,
185 adaptor.getOperands()[0]);
193static void replaceLoadOrStoreOp(vector::LoadOp loadOp,
194 vector::LoadOpAdaptor adaptor,
195 VectorType vectorTy,
Value ptr,
unsigned align,
196 ConversionPatternRewriter &rewriter) {
197 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(loadOp, vectorTy,
ptr, align,
199 loadOp.getNontemporal());
202static void replaceLoadOrStoreOp(vector::MaskedLoadOp loadOp,
203 vector::MaskedLoadOpAdaptor adaptor,
204 VectorType vectorTy,
Value ptr,
unsigned align,
205 ConversionPatternRewriter &rewriter) {
206 rewriter.replaceOpWithNewOp<LLVM::MaskedLoadOp>(
207 loadOp, vectorTy,
ptr, adaptor.getMask(), adaptor.getPassThru(), align);
210static void replaceLoadOrStoreOp(vector::StoreOp storeOp,
211 vector::StoreOpAdaptor adaptor,
212 VectorType vectorTy,
Value ptr,
unsigned align,
213 ConversionPatternRewriter &rewriter) {
214 rewriter.replaceOpWithNewOp<LLVM::StoreOp>(storeOp, adaptor.getValueToStore(),
216 storeOp.getNontemporal());
219static void replaceLoadOrStoreOp(vector::MaskedStoreOp storeOp,
220 vector::MaskedStoreOpAdaptor adaptor,
221 VectorType vectorTy,
Value ptr,
unsigned align,
222 ConversionPatternRewriter &rewriter) {
223 rewriter.replaceOpWithNewOp<LLVM::MaskedStoreOp>(
224 storeOp, adaptor.getValueToStore(),
ptr, adaptor.getMask(), align);
229template <
class LoadOrStoreOp>
232 explicit VectorLoadStoreConversion(
const LLVMTypeConverter &typeConv,
234 bool enableGEPInboundsNuw)
235 : ConvertOpToLLVMPattern<LoadOrStoreOp>(typeConv),
236 useVectorAlignment(useVectorAlign),
237 enableGEPInboundsNuw(enableGEPInboundsNuw) {}
240 matchAndRewrite(LoadOrStoreOp loadOrStoreOp,
241 typename LoadOrStoreOp::Adaptor adaptor,
242 ConversionPatternRewriter &rewriter)
const override {
244 VectorType vectorTy = loadOrStoreOp.getVectorType();
245 if (vectorTy.getRank() > 1)
248 auto loc = loadOrStoreOp->getLoc();
249 MemRefType memRefTy = loadOrStoreOp.getMemRefType();
253 unsigned align = loadOrStoreOp.getAlignment().value_or(0);
256 memRefTy, align, useVectorAlignment)))
257 return rewriter.notifyMatchFailure(loadOrStoreOp,
258 "could not resolve alignment");
266 LLVM::GEPNoWrapFlags noWrapFlags = LLVM::GEPNoWrapFlags::none;
267 if constexpr (std::is_same_v<LoadOrStoreOp, vector::LoadOp> ||
268 std::is_same_v<LoadOrStoreOp, vector::StoreOp>) {
272 auto [strides, offset] = memRefTy.getStridesAndOffset();
273 assert((strides.empty() || strides.back() == 1) &&
274 "vector.load/store requires unit trailing memref stride");
275 if (enableGEPInboundsNuw) {
276 noWrapFlags = noWrapFlags | LLVM::GEPNoWrapFlags::inbounds;
281 "Invalid MemRef type - should have been rejected by Op verifier.");
282 noWrapFlags = noWrapFlags | LLVM::GEPNoWrapFlags::nuw;
285 auto vtype = cast<VectorType>(
286 this->typeConverter->convertType(loadOrStoreOp.getVectorType()));
289 adaptor.getIndices(), noWrapFlags);
290 replaceLoadOrStoreOp(loadOrStoreOp, adaptor, vtype, dataPtr, align,
300 const bool useVectorAlignment;
301 const bool enableGEPInboundsNuw;
305class VectorGatherOpConversion
308 explicit VectorGatherOpConversion(
const LLVMTypeConverter &typeConv,
310 : ConvertOpToLLVMPattern<vector::GatherOp>(typeConv),
311 useVectorAlignment(useVectorAlign) {}
312 using ConvertOpToLLVMPattern<vector::GatherOp>::ConvertOpToLLVMPattern;
315 matchAndRewrite(vector::GatherOp gather, OpAdaptor adaptor,
316 ConversionPatternRewriter &rewriter)
const override {
317 Location loc = gather->getLoc();
318 MemRefType memRefType = dyn_cast<MemRefType>(gather.getBaseType());
319 assert(memRefType &&
"The base should be bufferized");
323 return rewriter.notifyMatchFailure(gather,
"memref type not supported");
325 VectorType vType = gather.getVectorType();
326 if (vType.getRank() > 1) {
327 return rewriter.notifyMatchFailure(
328 gather,
"only 1-D vectors can be lowered to LLVM");
333 unsigned align = gather.getAlignment().value_or(0);
336 memRefType, align, useVectorAlignment)))
337 return rewriter.notifyMatchFailure(gather,
"could not resolve alignment");
341 adaptor.getBase(), adaptor.getOffsets());
342 Value base = adaptor.getBase();
344 getIndexedPtrs(rewriter, loc, *this->getTypeConverter(), memRefType,
345 base, ptr, adaptor.getIndices(), vType);
348 rewriter.replaceOpWithNewOp<LLVM::masked_gather>(
349 gather, typeConverter->convertType(vType), ptrs, adaptor.getMask(),
350 adaptor.getPassThru(), rewriter.getI32IntegerAttr(align));
359 const bool useVectorAlignment;
363class VectorScatterOpConversion
366 explicit VectorScatterOpConversion(
const LLVMTypeConverter &typeConv,
368 : ConvertOpToLLVMPattern<vector::ScatterOp>(typeConv),
369 useVectorAlignment(useVectorAlign) {}
371 using ConvertOpToLLVMPattern<vector::ScatterOp>::ConvertOpToLLVMPattern;
374 matchAndRewrite(vector::ScatterOp scatter, OpAdaptor adaptor,
375 ConversionPatternRewriter &rewriter)
const override {
376 auto loc = scatter->getLoc();
377 auto memRefType = dyn_cast<MemRefType>(scatter.getBaseType());
378 assert(memRefType &&
"The base should be bufferized");
382 return rewriter.notifyMatchFailure(scatter,
"memref type not supported");
384 VectorType vType = scatter.getVectorType();
385 if (vType.getRank() > 1) {
386 return rewriter.notifyMatchFailure(
387 scatter,
"only 1-D vectors can be lowered to LLVM");
392 unsigned align = scatter.getAlignment().value_or(0);
395 memRefType, align, useVectorAlignment)))
396 return rewriter.notifyMatchFailure(scatter,
397 "could not resolve alignment");
401 adaptor.getBase(), adaptor.getOffsets());
403 getIndexedPtrs(rewriter, loc, *this->getTypeConverter(), memRefType,
404 adaptor.getBase(), ptr, adaptor.getIndices(), vType);
407 rewriter.replaceOpWithNewOp<LLVM::masked_scatter>(
408 scatter, adaptor.getValueToStore(), ptrs, adaptor.getMask(),
409 rewriter.getI32IntegerAttr(align));
418 const bool useVectorAlignment;
422class VectorExpandLoadOpConversion
425 using ConvertOpToLLVMPattern<vector::ExpandLoadOp>::ConvertOpToLLVMPattern;
428 matchAndRewrite(vector::ExpandLoadOp expand, OpAdaptor adaptor,
429 ConversionPatternRewriter &rewriter)
const override {
430 auto loc = expand->getLoc();
431 MemRefType memRefType = expand.getMemRefType();
434 auto vtype = typeConverter->convertType(expand.getVectorType());
436 adaptor.getBase(), adaptor.getIndices());
441 uint64_t alignment = expand.getAlignment().value_or(1);
443 rewriter.replaceOpWithNewOp<LLVM::masked_expandload>(
444 expand, vtype, ptr, adaptor.getMask(), adaptor.getPassThru(),
451class VectorCompressStoreOpConversion
454 using ConvertOpToLLVMPattern<vector::CompressStoreOp>::ConvertOpToLLVMPattern;
457 matchAndRewrite(vector::CompressStoreOp compress, OpAdaptor adaptor,
458 ConversionPatternRewriter &rewriter)
const override {
459 auto loc = compress->getLoc();
460 MemRefType memRefType = compress.getMemRefType();
464 adaptor.getBase(), adaptor.getIndices());
469 uint64_t alignment = compress.getAlignment().value_or(1);
471 rewriter.replaceOpWithNewOp<LLVM::masked_compressstore>(
472 compress, adaptor.getValueToStore(), ptr, adaptor.getMask(), alignment);
478class ReductionNeutralZero {};
479class ReductionNeutralIntOne {};
480class ReductionNeutralFPOne {};
481class ReductionNeutralAllOnes {};
482class ReductionNeutralSIntMin {};
483class ReductionNeutralUIntMin {};
484class ReductionNeutralSIntMax {};
485class ReductionNeutralUIntMax {};
486class ReductionNeutralFPMin {};
487class ReductionNeutralFPMax {};
491 ConversionPatternRewriter &rewriter,
493 return LLVM::ConstantOp::create(rewriter, loc, llvmType,
494 rewriter.getZeroAttr(llvmType));
499 ConversionPatternRewriter &rewriter,
501 return LLVM::ConstantOp::create(rewriter, loc, llvmType,
502 rewriter.getIntegerAttr(llvmType, 1));
507 ConversionPatternRewriter &rewriter,
509 return LLVM::ConstantOp::create(rewriter, loc, llvmType,
510 rewriter.getFloatAttr(llvmType, 1.0));
515 ConversionPatternRewriter &rewriter,
517 return LLVM::ConstantOp::create(
518 rewriter, loc, llvmType,
519 rewriter.getIntegerAttr(
525 ConversionPatternRewriter &rewriter,
527 return LLVM::ConstantOp::create(
528 rewriter, loc, llvmType,
529 rewriter.getIntegerAttr(llvmType, llvm::APInt::getSignedMinValue(
535 ConversionPatternRewriter &rewriter,
537 return LLVM::ConstantOp::create(
538 rewriter, loc, llvmType,
539 rewriter.getIntegerAttr(llvmType, llvm::APInt::getMinValue(
545 ConversionPatternRewriter &rewriter,
547 return LLVM::ConstantOp::create(
548 rewriter, loc, llvmType,
549 rewriter.getIntegerAttr(llvmType, llvm::APInt::getSignedMaxValue(
555 ConversionPatternRewriter &rewriter,
557 return LLVM::ConstantOp::create(
558 rewriter, loc, llvmType,
559 rewriter.getIntegerAttr(llvmType, llvm::APInt::getMaxValue(
565 ConversionPatternRewriter &rewriter,
567 auto floatType = cast<FloatType>(llvmType);
568 return LLVM::ConstantOp::create(
569 rewriter, loc, llvmType,
570 rewriter.getFloatAttr(
571 llvmType, llvm::APFloat::getQNaN(floatType.getFloatSemantics(),
577 ConversionPatternRewriter &rewriter,
579 auto floatType = cast<FloatType>(llvmType);
580 return LLVM::ConstantOp::create(
581 rewriter, loc, llvmType,
582 rewriter.getFloatAttr(
583 llvmType, llvm::APFloat::getQNaN(floatType.getFloatSemantics(),
589template <
class ReductionNeutral>
590static Value getOrCreateAccumulator(ConversionPatternRewriter &rewriter,
603static Value createVectorLengthValue(ConversionPatternRewriter &rewriter,
605 VectorType vType = cast<VectorType>(llvmType);
606 auto vShape = vType.getShape();
607 assert(vShape.size() == 1 &&
"Unexpected multi-dim vector type");
609 Value baseVecLength = LLVM::ConstantOp::create(
610 rewriter, loc, rewriter.getI32Type(),
611 rewriter.getIntegerAttr(rewriter.getI32Type(), vShape[0]));
613 if (!vType.getScalableDims()[0])
614 return baseVecLength;
617 Value vScale = vector::VectorScaleOp::create(rewriter, loc);
619 arith::IndexCastOp::create(rewriter, loc, rewriter.getI32Type(), vScale);
620 Value scalableVecLength =
621 arith::MulIOp::create(rewriter, loc, baseVecLength, vScale);
622 return scalableVecLength;
629template <
class LLVMRedIntrinOp,
class ScalarOp>
630static Value createIntegerReductionArithmeticOpLowering(
631 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
635 LLVMRedIntrinOp::create(rewriter, loc, llvmType, vectorOperand);
638 result = ScalarOp::create(rewriter, loc, accumulator,
result);
646template <
class LLVMRedIntrinOp>
647static Value createIntegerReductionComparisonOpLowering(
648 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
649 Value vectorOperand,
Value accumulator, LLVM::ICmpPredicate predicate) {
651 LLVMRedIntrinOp::create(rewriter, loc, llvmType, vectorOperand);
654 LLVM::ICmpOp::create(rewriter, loc, predicate, accumulator,
result);
655 result = LLVM::SelectOp::create(rewriter, loc, cmp, accumulator,
result);
661template <
typename Source>
662struct VectorToScalarMapper;
664struct VectorToScalarMapper<
LLVM::vector_reduce_fmaximum> {
665 using Type = LLVM::MaximumOp;
668struct VectorToScalarMapper<
LLVM::vector_reduce_fminimum> {
669 using Type = LLVM::MinimumOp;
672struct VectorToScalarMapper<
LLVM::vector_reduce_fmax> {
673 using Type = LLVM::MaxNumOp;
676struct VectorToScalarMapper<
LLVM::vector_reduce_fmin> {
677 using Type = LLVM::MinNumOp;
681template <
class LLVMRedIntrinOp>
682static Value createFPReductionComparisonOpLowering(
683 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
684 Value vectorOperand,
Value accumulator, LLVM::FastmathFlagsAttr fmf) {
686 LLVMRedIntrinOp::create(rewriter, loc, llvmType, vectorOperand, fmf);
689 result = VectorToScalarMapper<LLVMRedIntrinOp>::Type::create(
690 rewriter, loc,
result, accumulator);
697class MaskNeutralFMaximum {};
698class MaskNeutralFMinimum {};
702getMaskNeutralValue(MaskNeutralFMaximum,
703 const llvm::fltSemantics &floatSemantics) {
704 return llvm::APFloat::getSmallest(floatSemantics,
true);
708getMaskNeutralValue(MaskNeutralFMinimum,
709 const llvm::fltSemantics &floatSemantics) {
710 return llvm::APFloat::getLargest(floatSemantics,
false);
714template <
typename MaskNeutral>
715static Value createMaskNeutralValue(ConversionPatternRewriter &rewriter,
718 const auto &floatSemantics = cast<FloatType>(llvmType).getFloatSemantics();
719 auto value = getMaskNeutralValue(MaskNeutral{}, floatSemantics);
721 return LLVM::ConstantOp::create(rewriter, loc, vectorType, denseValue);
728template <
class LLVMRedIntrinOp,
class MaskNeutral>
730lowerMaskedReductionWithRegular(ConversionPatternRewriter &rewriter,
733 Value mask, LLVM::FastmathFlagsAttr fmf) {
734 const Value vectorMaskNeutral = createMaskNeutralValue<MaskNeutral>(
735 rewriter, loc, llvmType, vectorOperand.
getType());
736 const Value selectedVectorByMask = LLVM::SelectOp::create(
737 rewriter, loc, mask, vectorOperand, vectorMaskNeutral);
738 return createFPReductionComparisonOpLowering<LLVMRedIntrinOp>(
739 rewriter, loc, llvmType, selectedVectorByMask, accumulator, fmf);
742template <
class LLVMRedIntrinOp,
class ReductionNeutral>
744lowerReductionWithStartValue(ConversionPatternRewriter &rewriter,
Location loc,
746 Value accumulator, LLVM::FastmathFlagsAttr fmf) {
747 accumulator = getOrCreateAccumulator<ReductionNeutral>(rewriter, loc,
748 llvmType, accumulator);
749 return LLVMRedIntrinOp::create(rewriter, loc, llvmType,
750 accumulator, vectorOperand,
757template <
class LLVMVPRedIntrinOp,
class ReductionNeutral>
759lowerPredicatedReductionWithStartValue(ConversionPatternRewriter &rewriter,
762 accumulator = getOrCreateAccumulator<ReductionNeutral>(rewriter, loc,
763 llvmType, accumulator);
764 return LLVMVPRedIntrinOp::create(rewriter, loc, llvmType,
765 accumulator, vectorOperand);
768template <
class LLVMVPRedIntrinOp,
class ReductionNeutral>
769static Value lowerPredicatedReductionWithStartValue(
770 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
772 accumulator = getOrCreateAccumulator<ReductionNeutral>(rewriter, loc,
773 llvmType, accumulator);
775 createVectorLengthValue(rewriter, loc, vectorOperand.
getType());
776 return LLVMVPRedIntrinOp::create(rewriter, loc, llvmType,
777 accumulator, vectorOperand,
781template <
class LLVMIntVPRedIntrinOp,
class IntReductionNeutral,
782 class LLVMFPVPRedIntrinOp,
class FPReductionNeutral>
783static Value lowerPredicatedReductionWithStartValue(
784 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
787 return lowerPredicatedReductionWithStartValue<LLVMIntVPRedIntrinOp,
788 IntReductionNeutral>(
789 rewriter, loc, llvmType, vectorOperand, accumulator, mask);
792 return lowerPredicatedReductionWithStartValue<LLVMFPVPRedIntrinOp,
794 rewriter, loc, llvmType, vectorOperand, accumulator, mask);
798class VectorReductionOpConversion
801 explicit VectorReductionOpConversion(
const LLVMTypeConverter &typeConv,
802 bool reassociateFPRed)
803 : ConvertOpToLLVMPattern<vector::ReductionOp>(typeConv),
804 reassociateFPReductions(reassociateFPRed) {}
807 matchAndRewrite(vector::ReductionOp reductionOp, OpAdaptor adaptor,
808 ConversionPatternRewriter &rewriter)
const override {
809 auto kind = reductionOp.getKind();
810 Type eltType = reductionOp.getDest().getType();
811 Type llvmType = typeConverter->convertType(eltType);
812 Value operand = adaptor.getVector();
813 Value acc = adaptor.getAcc();
814 Location loc = reductionOp.getLoc();
820 case vector::CombiningKind::ADD:
822 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_add,
824 rewriter, loc, llvmType, operand, acc);
826 case vector::CombiningKind::MUL:
828 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_mul,
830 rewriter, loc, llvmType, operand, acc);
832 case vector::CombiningKind::MINUI:
833 result = createIntegerReductionComparisonOpLowering<
834 LLVM::vector_reduce_umin>(rewriter, loc, llvmType, operand, acc,
835 LLVM::ICmpPredicate::ule);
837 case vector::CombiningKind::MINSI:
838 result = createIntegerReductionComparisonOpLowering<
839 LLVM::vector_reduce_smin>(rewriter, loc, llvmType, operand, acc,
840 LLVM::ICmpPredicate::sle);
842 case vector::CombiningKind::MAXUI:
843 result = createIntegerReductionComparisonOpLowering<
844 LLVM::vector_reduce_umax>(rewriter, loc, llvmType, operand, acc,
845 LLVM::ICmpPredicate::uge);
847 case vector::CombiningKind::MAXSI:
848 result = createIntegerReductionComparisonOpLowering<
849 LLVM::vector_reduce_smax>(rewriter, loc, llvmType, operand, acc,
850 LLVM::ICmpPredicate::sge);
852 case vector::CombiningKind::AND:
854 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_and,
856 rewriter, loc, llvmType, operand, acc);
858 case vector::CombiningKind::OR:
860 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_or,
862 rewriter, loc, llvmType, operand, acc);
864 case vector::CombiningKind::XOR:
866 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_xor,
868 rewriter, loc, llvmType, operand, acc);
873 rewriter.replaceOp(reductionOp,
result);
878 if (!isa<FloatType>(eltType))
881 arith::FastMathFlagsAttr fMFAttr = reductionOp.getFastMathFlagsAttr();
882 LLVM::FastmathFlagsAttr fmf = LLVM::FastmathFlagsAttr::get(
883 reductionOp.getContext(),
885 fmf = LLVM::FastmathFlagsAttr::get(
886 reductionOp.getContext(),
887 fmf.getValue() | (reassociateFPReductions ? LLVM::FastmathFlags::reassoc
888 : LLVM::FastmathFlags::none));
892 if (kind == vector::CombiningKind::ADD) {
893 result = lowerReductionWithStartValue<LLVM::vector_reduce_fadd,
894 ReductionNeutralZero>(
895 rewriter, loc, llvmType, operand, acc, fmf);
896 }
else if (kind == vector::CombiningKind::MUL) {
897 result = lowerReductionWithStartValue<LLVM::vector_reduce_fmul,
898 ReductionNeutralFPOne>(
899 rewriter, loc, llvmType, operand, acc, fmf);
900 }
else if (kind == vector::CombiningKind::MINIMUMF) {
902 createFPReductionComparisonOpLowering<LLVM::vector_reduce_fminimum>(
903 rewriter, loc, llvmType, operand, acc, fmf);
904 }
else if (kind == vector::CombiningKind::MAXIMUMF) {
906 createFPReductionComparisonOpLowering<LLVM::vector_reduce_fmaximum>(
907 rewriter, loc, llvmType, operand, acc, fmf);
908 }
else if (kind == vector::CombiningKind::MINNUMF) {
909 result = createFPReductionComparisonOpLowering<LLVM::vector_reduce_fmin>(
910 rewriter, loc, llvmType, operand, acc, fmf);
911 }
else if (kind == vector::CombiningKind::MAXNUMF) {
912 result = createFPReductionComparisonOpLowering<LLVM::vector_reduce_fmax>(
913 rewriter, loc, llvmType, operand, acc, fmf);
918 rewriter.replaceOp(reductionOp,
result);
923 const bool reassociateFPReductions;
934template <
class MaskedOp>
935class VectorMaskOpConversionBase
938 using ConvertOpToLLVMPattern<vector::MaskOp>::ConvertOpToLLVMPattern;
941 matchAndRewrite(vector::MaskOp maskOp, OpAdaptor adaptor,
942 ConversionPatternRewriter &rewriter)
const final {
944 auto maskedOp = llvm::dyn_cast_or_null<MaskedOp>(maskOp.getMaskableOp());
947 return matchAndRewriteMaskableOp(maskOp, maskedOp, rewriter);
951 virtual LogicalResult
952 matchAndRewriteMaskableOp(vector::MaskOp maskOp,
953 vector::MaskableOpInterface maskableOp,
954 ConversionPatternRewriter &rewriter)
const = 0;
957class MaskedReductionOpConversion
958 :
public VectorMaskOpConversionBase<vector::ReductionOp> {
961 using VectorMaskOpConversionBase<
962 vector::ReductionOp>::VectorMaskOpConversionBase;
964 LogicalResult matchAndRewriteMaskableOp(
965 vector::MaskOp maskOp, MaskableOpInterface maskableOp,
966 ConversionPatternRewriter &rewriter)
const override {
967 auto reductionOp = cast<ReductionOp>(maskableOp.getOperation());
968 auto kind = reductionOp.getKind();
969 Type eltType = reductionOp.getDest().getType();
970 Type llvmType = typeConverter->convertType(eltType);
971 Value operand = reductionOp.getVector();
972 Value acc = reductionOp.getAcc();
973 Location loc = reductionOp.getLoc();
975 arith::FastMathFlagsAttr fMFAttr = reductionOp.getFastMathFlagsAttr();
976 LLVM::FastmathFlagsAttr fmf = LLVM::FastmathFlagsAttr::get(
977 reductionOp.getContext(),
982 case vector::CombiningKind::ADD:
983 result = lowerPredicatedReductionWithStartValue<
984 LLVM::VPReduceAddOp, ReductionNeutralZero, LLVM::VPReduceFAddOp,
985 ReductionNeutralZero>(rewriter, loc, llvmType, operand, acc,
988 case vector::CombiningKind::MUL:
989 result = lowerPredicatedReductionWithStartValue<
990 LLVM::VPReduceMulOp, ReductionNeutralIntOne, LLVM::VPReduceFMulOp,
991 ReductionNeutralFPOne>(rewriter, loc, llvmType, operand, acc,
994 case vector::CombiningKind::MINUI:
995 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceUMinOp,
996 ReductionNeutralUIntMax>(
997 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
999 case vector::CombiningKind::MINSI:
1000 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceSMinOp,
1001 ReductionNeutralSIntMax>(
1002 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1004 case vector::CombiningKind::MAXUI:
1005 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceUMaxOp,
1006 ReductionNeutralUIntMin>(
1007 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1009 case vector::CombiningKind::MAXSI:
1010 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceSMaxOp,
1011 ReductionNeutralSIntMin>(
1012 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1014 case vector::CombiningKind::AND:
1015 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceAndOp,
1016 ReductionNeutralAllOnes>(
1017 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1019 case vector::CombiningKind::OR:
1020 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceOrOp,
1021 ReductionNeutralZero>(
1022 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1024 case vector::CombiningKind::XOR:
1025 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceXorOp,
1026 ReductionNeutralZero>(
1027 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1029 case vector::CombiningKind::MINNUMF:
1030 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceFMinOp,
1031 ReductionNeutralFPMax>(
1032 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1034 case vector::CombiningKind::MAXNUMF:
1035 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceFMaxOp,
1036 ReductionNeutralFPMin>(
1037 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1039 case CombiningKind::MAXIMUMF:
1040 result = lowerMaskedReductionWithRegular<LLVM::vector_reduce_fmaximum,
1041 MaskNeutralFMaximum>(
1042 rewriter, loc, llvmType, operand, acc, maskOp.getMask(), fmf);
1044 case CombiningKind::MINIMUMF:
1045 result = lowerMaskedReductionWithRegular<LLVM::vector_reduce_fminimum,
1046 MaskNeutralFMinimum>(
1047 rewriter, loc, llvmType, operand, acc, maskOp.getMask(), fmf);
1052 rewriter.replaceOp(maskOp,
result);
1057class VectorShuffleOpConversion
1060 using ConvertOpToLLVMPattern<vector::ShuffleOp>::ConvertOpToLLVMPattern;
1063 matchAndRewrite(vector::ShuffleOp shuffleOp, OpAdaptor adaptor,
1064 ConversionPatternRewriter &rewriter)
const override {
1065 auto loc = shuffleOp->getLoc();
1066 auto v1Type = shuffleOp.getV1VectorType();
1067 auto v2Type = shuffleOp.getV2VectorType();
1068 auto vectorType = shuffleOp.getResultVectorType();
1069 Type llvmType = typeConverter->convertType(vectorType);
1070 ArrayRef<int64_t> mask = shuffleOp.getMask();
1077 int64_t rank = vectorType.getRank();
1079 bool wellFormed0DCase =
1080 v1Type.getRank() == 0 && v2Type.getRank() == 0 && rank == 1;
1081 bool wellFormedNDCase =
1082 v1Type.getRank() == rank && v2Type.getRank() == rank;
1083 assert((wellFormed0DCase || wellFormedNDCase) &&
"op is not well-formed");
1088 if (rank <= 1 && v1Type == v2Type) {
1089 Value llvmShuffleOp = LLVM::ShuffleVectorOp::create(
1090 rewriter, loc, adaptor.getV1(), adaptor.getV2(),
1091 llvm::to_vector_of<int32_t>(mask));
1092 rewriter.replaceOp(shuffleOp, llvmShuffleOp);
1097 int64_t v1Dim = v1Type.getDimSize(0);
1099 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(llvmType))
1100 eltType = arrayType.getElementType();
1102 eltType = cast<VectorType>(llvmType).getElementType();
1103 Value insert = LLVM::PoisonOp::create(rewriter, loc, llvmType);
1105 for (int64_t extPos : mask) {
1106 Value value = adaptor.getV1();
1107 if (extPos >= v1Dim) {
1109 value = adaptor.getV2();
1111 Value extract =
extractOne(rewriter, *getTypeConverter(), loc, value,
1112 eltType, rank, extPos);
1113 insert =
insertOne(rewriter, *getTypeConverter(), loc, insert, extract,
1114 llvmType, rank, insPos++);
1116 rewriter.replaceOp(shuffleOp, insert);
1121class VectorExtractOpConversion
1124 using ConvertOpToLLVMPattern<vector::ExtractOp>::ConvertOpToLLVMPattern;
1127 matchAndRewrite(vector::ExtractOp extractOp, OpAdaptor adaptor,
1128 ConversionPatternRewriter &rewriter)
const override {
1129 auto loc = extractOp->getLoc();
1130 auto resultType = extractOp.getResult().getType();
1131 auto llvmResultType = typeConverter->convertType(resultType);
1133 if (!llvmResultType)
1137 adaptor.getStaticPosition(), adaptor.getDynamicPosition(), rewriter);
1151 bool extractsAggregate = extractOp.getSourceVectorType().getRank() >= 2;
1155 bool extractsScalar =
static_cast<int64_t
>(positionVec.size()) ==
1156 extractOp.getSourceVectorType().getRank();
1160 if (extractOp.getSourceVectorType().getRank() == 0) {
1161 Type idxType = typeConverter->convertType(rewriter.getIndexType());
1162 positionVec.push_back(rewriter.getZeroAttr(idxType));
1165 Value extracted = adaptor.getSource();
1166 if (extractsAggregate) {
1167 ArrayRef<OpFoldResult> position(positionVec);
1168 if (extractsScalar) {
1172 position = position.drop_back();
1175 if (!llvm::all_of(position, llvm::IsaPred<Attribute>)) {
1178 extracted = LLVM::ExtractValueOp::create(rewriter, loc, extracted,
1182 if (extractsScalar) {
1183 extracted = LLVM::ExtractElementOp::create(
1184 rewriter, loc, extracted,
1188 rewriter.replaceOp(extractOp, extracted);
1209 using ConvertOpToLLVMPattern<vector::FMAOp>::ConvertOpToLLVMPattern;
1212 matchAndRewrite(vector::FMAOp fmaOp, OpAdaptor adaptor,
1213 ConversionPatternRewriter &rewriter)
const override {
1214 VectorType vType = fmaOp.getVectorType();
1215 if (vType.getRank() > 1)
1218 rewriter.replaceOpWithNewOp<LLVM::FMulAddOp>(
1219 fmaOp, adaptor.getLhs(), adaptor.getRhs(), adaptor.getAcc());
1224class VectorInsertOpConversion
1227 using ConvertOpToLLVMPattern<vector::InsertOp>::ConvertOpToLLVMPattern;
1230 matchAndRewrite(vector::InsertOp insertOp, OpAdaptor adaptor,
1231 ConversionPatternRewriter &rewriter)
const override {
1232 auto loc = insertOp->getLoc();
1233 auto destVectorType = insertOp.getDestVectorType();
1234 auto llvmResultType = typeConverter->convertType(destVectorType);
1236 if (!llvmResultType)
1240 adaptor.getStaticPosition(), adaptor.getDynamicPosition(), rewriter);
1262 bool isNestedAggregate = isa<LLVM::LLVMArrayType>(llvmResultType);
1264 bool insertIntoInnermostDim =
1265 static_cast<int64_t
>(positionVec.size()) == destVectorType.getRank();
1267 ArrayRef<OpFoldResult> positionOf1DVectorWithinAggregate(
1268 positionVec.begin(),
1269 insertIntoInnermostDim ? positionVec.size() - 1 : positionVec.size());
1270 OpFoldResult positionOfScalarWithin1DVector;
1271 if (destVectorType.getRank() == 0) {
1274 Type idxType = typeConverter->convertType(rewriter.getIndexType());
1275 positionOfScalarWithin1DVector = rewriter.getZeroAttr(idxType);
1276 }
else if (insertIntoInnermostDim) {
1277 positionOfScalarWithin1DVector = positionVec.back();
1283 Value sourceAggregate = adaptor.getValueToStore();
1284 if (insertIntoInnermostDim) {
1287 if (isNestedAggregate) {
1290 if (!llvm::all_of(positionOf1DVectorWithinAggregate,
1291 llvm::IsaPred<Attribute>)) {
1295 sourceAggregate = LLVM::ExtractValueOp::create(
1296 rewriter, loc, adaptor.getDest(),
1301 sourceAggregate = adaptor.getDest();
1304 sourceAggregate = LLVM::InsertElementOp::create(
1305 rewriter, loc, sourceAggregate.
getType(), sourceAggregate,
1306 adaptor.getValueToStore(),
1310 Value
result = sourceAggregate;
1311 if (isNestedAggregate) {
1312 if (!llvm::all_of(positionOf1DVectorWithinAggregate,
1313 llvm::IsaPred<Attribute>)) {
1317 result = LLVM::InsertValueOp::create(
1318 rewriter, loc, adaptor.getDest(), sourceAggregate,
1322 rewriter.replaceOp(insertOp,
result);
1328struct VectorScalableInsertOpLowering
1330 using ConvertOpToLLVMPattern<
1331 vector::ScalableInsertOp>::ConvertOpToLLVMPattern;
1334 matchAndRewrite(vector::ScalableInsertOp insOp, OpAdaptor adaptor,
1335 ConversionPatternRewriter &rewriter)
const override {
1336 rewriter.replaceOpWithNewOp<LLVM::vector_insert>(
1337 insOp, adaptor.getDest(), adaptor.getValueToStore(), adaptor.getPos());
1343struct VectorScalableExtractOpLowering
1345 using ConvertOpToLLVMPattern<
1346 vector::ScalableExtractOp>::ConvertOpToLLVMPattern;
1349 matchAndRewrite(vector::ScalableExtractOp extOp, OpAdaptor adaptor,
1350 ConversionPatternRewriter &rewriter)
const override {
1351 rewriter.replaceOpWithNewOp<LLVM::vector_extract>(
1352 extOp, typeConverter->convertType(extOp.getResultVectorType()),
1353 adaptor.getSource(), adaptor.getPos());
1386 setHasBoundedRewriteRecursion();
1389 LogicalResult matchAndRewrite(FMAOp op,
1390 PatternRewriter &rewriter)
const override {
1391 auto vType = op.getVectorType();
1392 if (vType.getRank() < 2)
1395 auto loc = op.getLoc();
1396 auto elemType = vType.getElementType();
1397 Value zero = arith::ConstantOp::create(rewriter, loc, elemType,
1399 Value desc = vector::BroadcastOp::create(rewriter, loc, vType, zero);
1400 for (int64_t i = 0, e = vType.getShape().front(); i != e; ++i) {
1401 Value extrLHS = ExtractOp::create(rewriter, loc, op.getLhs(), i);
1402 Value extrRHS = ExtractOp::create(rewriter, loc, op.getRhs(), i);
1403 Value extrACC = ExtractOp::create(rewriter, loc, op.getAcc(), i);
1404 Value fma = FMAOp::create(rewriter, loc, extrLHS, extrRHS, extrACC);
1405 desc = InsertOp::create(rewriter, loc, fma, desc, i);
1414static std::optional<SmallVector<int64_t, 4>>
1415computeContiguousStrides(MemRefType memRefType) {
1418 if (
failed(memRefType.getStridesAndOffset(strides, offset)))
1419 return std::nullopt;
1420 if (!strides.empty() && strides.back() != 1)
1421 return std::nullopt;
1423 if (memRefType.getLayout().isIdentity())
1430 auto sizes = memRefType.getShape();
1432 if (ShapedType::isDynamic(sizes[
index + 1]) ||
1433 ShapedType::isDynamic(strides[
index]) ||
1434 ShapedType::isDynamic(strides[
index + 1]))
1435 return std::nullopt;
1437 return std::nullopt;
1442class VectorTypeCastOpConversion
1445 using ConvertOpToLLVMPattern<vector::TypeCastOp>::ConvertOpToLLVMPattern;
1448 matchAndRewrite(vector::TypeCastOp castOp, OpAdaptor adaptor,
1449 ConversionPatternRewriter &rewriter)
const override {
1450 auto loc = castOp->getLoc();
1451 MemRefType sourceMemRefType =
1452 cast<MemRefType>(castOp.getOperand().getType());
1453 MemRefType targetMemRefType = castOp.getType();
1456 if (!sourceMemRefType.hasStaticShape() ||
1457 !targetMemRefType.hasStaticShape())
1460 auto llvmSourceDescriptorTy =
1461 dyn_cast<LLVM::LLVMStructType>(adaptor.getOperands()[0].getType());
1462 if (!llvmSourceDescriptorTy)
1464 MemRefDescriptor sourceMemRef(adaptor.getOperands()[0]);
1466 auto llvmTargetDescriptorTy = dyn_cast_or_null<LLVM::LLVMStructType>(
1467 typeConverter->convertType(targetMemRefType));
1468 if (!llvmTargetDescriptorTy)
1472 auto sourceStrides = computeContiguousStrides(sourceMemRefType);
1475 auto targetStrides = computeContiguousStrides(targetMemRefType);
1479 if (llvm::any_of(*targetStrides, ShapedType::isDynamic))
1482 auto int64Ty = IntegerType::get(rewriter.getContext(), 64);
1485 auto desc = MemRefDescriptor::poison(rewriter, loc, llvmTargetDescriptorTy);
1487 Value allocated = sourceMemRef.allocatedPtr(rewriter, loc);
1488 desc.setAllocatedPtr(rewriter, loc, allocated);
1491 Value ptr = sourceMemRef.alignedPtr(rewriter, loc);
1492 desc.setAlignedPtr(rewriter, loc, ptr);
1494 auto attr = rewriter.getIntegerAttr(rewriter.getIndexType(), 0);
1495 auto zero = LLVM::ConstantOp::create(rewriter, loc, int64Ty, attr);
1496 desc.setOffset(rewriter, loc, zero);
1499 for (
const auto &indexedSize :
1500 llvm::enumerate(targetMemRefType.getShape())) {
1501 int64_t index = indexedSize.index();
1503 rewriter.getIntegerAttr(rewriter.getIndexType(), indexedSize.value());
1504 auto size = LLVM::ConstantOp::create(rewriter, loc, int64Ty, sizeAttr);
1505 desc.setSize(rewriter, loc, index, size);
1506 auto strideAttr = rewriter.getIntegerAttr(rewriter.getIndexType(),
1507 (*targetStrides)[index]);
1509 LLVM::ConstantOp::create(rewriter, loc, int64Ty, strideAttr);
1510 desc.setStride(rewriter, loc, index, stride);
1513 rewriter.replaceOp(castOp, {desc});
1520class VectorCreateMaskOpConversion
1521 :
public OpConversionPattern<vector::CreateMaskOp> {
1523 explicit VectorCreateMaskOpConversion(MLIRContext *context,
1524 bool enableIndexOpt)
1525 : OpConversionPattern<vector::CreateMaskOp>(context),
1526 force32BitVectorIndices(enableIndexOpt) {}
1529 matchAndRewrite(vector::CreateMaskOp op, OpAdaptor adaptor,
1530 ConversionPatternRewriter &rewriter)
const override {
1531 auto dstType = op.getType();
1532 if (dstType.getRank() != 1 || !cast<VectorType>(dstType).isScalable())
1534 IntegerType idxType =
1535 force32BitVectorIndices ? rewriter.getI32Type() : rewriter.getI64Type();
1536 auto loc = op->getLoc();
1537 Value
indices = LLVM::StepVectorOp::create(
1541 Value maskBound = adaptor.getOperands()[0];
1548 if (force32BitVectorIndices) {
1551 maskBound = arith::MinSIOp::create(rewriter, loc, maskBound, maxBound);
1555 Value bounds = BroadcastOp::create(rewriter, loc,
indices.getType(), bound);
1556 Value comp = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
1558 rewriter.replaceOp(op, comp);
1563 const bool force32BitVectorIndices;
1567 SymbolTableCollection *symbolTables =
nullptr;
1570 explicit VectorPrintOpConversion(
1571 const LLVMTypeConverter &typeConverter,
1572 SymbolTableCollection *symbolTables =
nullptr)
1573 : ConvertOpToLLVMPattern<vector::PrintOp>(typeConverter),
1574 symbolTables(symbolTables) {}
1590 matchAndRewrite(vector::PrintOp
printOp, OpAdaptor adaptor,
1591 ConversionPatternRewriter &rewriter)
const override {
1592 auto parent =
printOp->getParentOfType<ModuleOp>();
1598 if (
auto value = adaptor.getSource()) {
1600 if (isa<VectorType>(printType)) {
1604 if (
failed(emitScalarPrint(rewriter, parent, loc, printType, value)))
1608 auto punct =
printOp.getPunctuation();
1609 if (
auto stringLiteral =
printOp.getStringLiteral()) {
1612 *stringLiteral, *getTypeConverter(),
1614 if (createResult.failed())
1617 }
else if (punct != PrintPunctuation::NoPunctuation) {
1618 FailureOr<LLVM::LLVMFuncOp> op = [&]() {
1620 case PrintPunctuation::Close:
1623 case PrintPunctuation::Open:
1626 case PrintPunctuation::Comma:
1629 case PrintPunctuation::NewLine:
1633 llvm_unreachable(
"unexpected punctuation");
1638 emitCall(rewriter,
printOp->getLoc(), op.value());
1646 enum class PrintConversion {
1655 LogicalResult emitScalarPrint(ConversionPatternRewriter &rewriter,
1656 ModuleOp parent, Location loc, Type printType,
1657 Value value)
const {
1658 if (typeConverter->convertType(printType) ==
nullptr)
1662 PrintConversion conversion = PrintConversion::None;
1663 FailureOr<Operation *> printer;
1669 conversion = PrintConversion::Bitcast16;
1672 conversion = PrintConversion::Bitcast16;
1676 }
else if (
auto intTy = dyn_cast<IntegerType>(printType)) {
1680 unsigned width = intTy.getWidth();
1681 if (intTy.isUnsigned()) {
1684 conversion = PrintConversion::ZeroExt64;
1691 assert(intTy.isSignless() || intTy.isSigned());
1696 conversion = PrintConversion::ZeroExt64;
1697 else if (width < 64)
1698 conversion = PrintConversion::SignExt64;
1705 }
else if (
auto floatTy = dyn_cast<FloatType>(printType)) {
1708 llvm::APFloatBase::SemanticsToEnum(floatTy.getFloatSemantics());
1709 Value semValue = LLVM::ConstantOp::create(
1710 rewriter, loc, rewriter.getI32Type(),
1711 rewriter.getIntegerAttr(rewriter.getI32Type(), sem));
1713 LLVM::ZExtOp::create(rewriter, loc, rewriter.getI64Type(), value);
1716 emitCall(rewriter, loc, printer.value(),
1725 switch (conversion) {
1726 case PrintConversion::ZeroExt64:
1727 value = arith::ExtUIOp::create(
1728 rewriter, loc, IntegerType::get(rewriter.getContext(), 64), value);
1730 case PrintConversion::SignExt64:
1731 value = arith::ExtSIOp::create(
1732 rewriter, loc, IntegerType::get(rewriter.getContext(), 64), value);
1734 case PrintConversion::Bitcast16:
1735 value = LLVM::BitcastOp::create(
1736 rewriter, loc, IntegerType::get(rewriter.getContext(), 16), value);
1738 case PrintConversion::None:
1741 emitCall(rewriter, loc, printer.value(), value);
1746 static void emitCall(ConversionPatternRewriter &rewriter, Location loc,
1748 LLVM::CallOp::create(rewriter, loc,
TypeRange(), SymbolRefAttr::get(ref),
1756struct VectorBroadcastScalarToLowRankLowering
1758 using ConvertOpToLLVMPattern<vector::BroadcastOp>::ConvertOpToLLVMPattern;
1761 matchAndRewrite(vector::BroadcastOp
broadcast, OpAdaptor adaptor,
1762 ConversionPatternRewriter &rewriter)
const override {
1763 if (isa<VectorType>(
broadcast.getSourceType()))
1764 return rewriter.notifyMatchFailure(
1765 broadcast,
"broadcast from vector type not handled");
1768 if (resultType.getRank() > 1)
1769 return rewriter.notifyMatchFailure(
broadcast,
1770 "broadcast to 2+-d handled elsewhere");
1776 auto zero = LLVM::ConstantOp::create(
1778 typeConverter->convertType(rewriter.getIntegerType(32)),
1779 rewriter.getZeroAttr(rewriter.getIntegerType(32)));
1782 if (resultType.getRank() == 0) {
1783 rewriter.replaceOpWithNewOp<LLVM::InsertElementOp>(
1784 broadcast, vectorType, poison, adaptor.getSource(), zero);
1789 LLVM::InsertElementOp::create(rewriter,
broadcast.
getLoc(), vectorType,
1790 poison, adaptor.getSource(), zero);
1794 SmallVector<int32_t> zeroValues(width, 0);
1797 auto shuffle = rewriter.createOrFold<LLVM::ShuffleVectorOp>(
1808struct VectorBroadcastScalarToNdLowering
1810 using ConvertOpToLLVMPattern<BroadcastOp>::ConvertOpToLLVMPattern;
1813 matchAndRewrite(BroadcastOp
broadcast, OpAdaptor adaptor,
1814 ConversionPatternRewriter &rewriter)
const override {
1815 if (isa<VectorType>(
broadcast.getSourceType()))
1816 return rewriter.notifyMatchFailure(
1817 broadcast,
"broadcast from vector type not handled");
1820 if (resultType.getRank() <= 1)
1821 return rewriter.notifyMatchFailure(
1822 broadcast,
"broadcast to 1-d or 0-d handled elsewhere");
1826 auto vectorTypeInfo =
1828 auto llvmNDVectorTy = vectorTypeInfo.llvmNDVectorTy;
1829 auto llvm1DVectorTy = vectorTypeInfo.llvm1DVectorTy;
1830 if (!llvmNDVectorTy || !llvm1DVectorTy)
1834 Value desc = LLVM::PoisonOp::create(rewriter, loc, llvmNDVectorTy);
1838 Value vdesc = LLVM::PoisonOp::create(rewriter, loc, llvm1DVectorTy);
1839 auto zero = LLVM::ConstantOp::create(
1840 rewriter, loc, typeConverter->convertType(rewriter.getIntegerType(32)),
1841 rewriter.getZeroAttr(rewriter.getIntegerType(32)));
1842 Value v = LLVM::InsertElementOp::create(rewriter, loc, llvm1DVectorTy,
1843 vdesc, adaptor.getSource(), zero);
1846 int64_t width = resultType.getDimSize(resultType.getRank() - 1);
1847 SmallVector<int32_t> zeroValues(width, 0);
1848 v = LLVM::ShuffleVectorOp::create(rewriter, loc, v, v, zeroValues);
1852 nDVectorIterate(vectorTypeInfo, rewriter, [&](ArrayRef<int64_t> position) {
1853 desc = LLVM::InsertValueOp::create(rewriter, loc, desc, v, position);
1862struct VectorInterleaveOpLowering
1867 matchAndRewrite(vector::InterleaveOp interleaveOp, OpAdaptor adaptor,
1868 ConversionPatternRewriter &rewriter)
const override {
1869 VectorType resultType = interleaveOp.getResultVectorType();
1871 if (resultType.getRank() != 1)
1872 return rewriter.notifyMatchFailure(interleaveOp,
1873 "InterleaveOp not rank 1");
1875 if (resultType.isScalable()) {
1876 rewriter.replaceOpWithNewOp<LLVM::vector_interleave2>(
1877 interleaveOp, typeConverter->convertType(resultType),
1878 adaptor.getLhs(), adaptor.getRhs());
1885 int64_t resultVectorSize = resultType.getNumElements();
1886 SmallVector<int32_t> interleaveShuffleMask;
1887 interleaveShuffleMask.reserve(resultVectorSize);
1888 for (
int i = 0, end = resultVectorSize / 2; i < end; ++i) {
1889 interleaveShuffleMask.push_back(i);
1890 interleaveShuffleMask.push_back((resultVectorSize / 2) + i);
1892 rewriter.replaceOpWithNewOp<LLVM::ShuffleVectorOp>(
1893 interleaveOp, adaptor.getLhs(), adaptor.getRhs(),
1894 interleaveShuffleMask);
1901struct VectorDeinterleaveOpLowering
1906 matchAndRewrite(vector::DeinterleaveOp deinterleaveOp, OpAdaptor adaptor,
1907 ConversionPatternRewriter &rewriter)
const override {
1908 VectorType resultType = deinterleaveOp.getResultVectorType();
1909 VectorType sourceType = deinterleaveOp.getSourceVectorType();
1910 auto loc = deinterleaveOp.getLoc();
1914 if (resultType.getRank() != 1)
1915 return rewriter.notifyMatchFailure(deinterleaveOp,
1916 "DeinterleaveOp not rank 1");
1918 if (resultType.isScalable()) {
1919 const auto *llvmTypeConverter = this->getTypeConverter();
1920 auto deinterleaveResults = deinterleaveOp.getResultTypes();
1921 auto packedOpResults =
1922 llvmTypeConverter->packOperationResults(deinterleaveResults);
1923 auto intrinsic = LLVM::vector_deinterleave2::create(
1924 rewriter, loc, packedOpResults, adaptor.getSource());
1926 auto evenResult = LLVM::ExtractValueOp::create(
1927 rewriter, loc, intrinsic->getResult(0), 0);
1928 auto oddResult = LLVM::ExtractValueOp::create(rewriter, loc,
1929 intrinsic->getResult(0), 1);
1931 rewriter.replaceOp(deinterleaveOp,
ValueRange{evenResult, oddResult});
1938 int64_t resultVectorSize = resultType.getNumElements();
1939 SmallVector<int32_t> evenShuffleMask;
1940 SmallVector<int32_t> oddShuffleMask;
1942 evenShuffleMask.reserve(resultVectorSize);
1943 oddShuffleMask.reserve(resultVectorSize);
1945 for (
int i = 0; i < sourceType.getNumElements(); ++i) {
1947 evenShuffleMask.push_back(i);
1949 oddShuffleMask.push_back(i);
1952 auto poison = LLVM::PoisonOp::create(rewriter, loc, sourceType);
1953 auto evenShuffle = LLVM::ShuffleVectorOp::create(
1954 rewriter, loc, adaptor.getSource(), poison, evenShuffleMask);
1955 auto oddShuffle = LLVM::ShuffleVectorOp::create(
1956 rewriter, loc, adaptor.getSource(), poison, oddShuffleMask);
1958 rewriter.replaceOp(deinterleaveOp,
ValueRange{evenShuffle, oddShuffle});
1964struct VectorFromElementsLowering
1969 matchAndRewrite(vector::FromElementsOp fromElementsOp, OpAdaptor adaptor,
1970 ConversionPatternRewriter &rewriter)
const override {
1971 Location loc = fromElementsOp.getLoc();
1972 VectorType vectorType = fromElementsOp.getType();
1976 if (vectorType.getRank() > 1)
1977 return rewriter.notifyMatchFailure(fromElementsOp,
1978 "rank > 1 vectors are not supported");
1979 Type llvmType = typeConverter->convertType(vectorType);
1980 Type llvmIndexType = typeConverter->convertType(rewriter.getIndexType());
1981 Value
result = LLVM::PoisonOp::create(rewriter, loc, llvmType);
1982 for (
auto [idx, val] : llvm::enumerate(adaptor.getElements())) {
1984 LLVM::ConstantOp::create(rewriter, loc, llvmIndexType, idx);
1985 result = LLVM::InsertElementOp::create(rewriter, loc, llvmType,
result,
1988 rewriter.replaceOp(fromElementsOp,
result);
1994struct VectorToElementsLowering
1999 matchAndRewrite(vector::ToElementsOp toElementsOp, OpAdaptor adaptor,
2000 ConversionPatternRewriter &rewriter)
const override {
2001 Location loc = toElementsOp.getLoc();
2002 auto idxType = typeConverter->convertType(rewriter.getIndexType());
2003 Value source = adaptor.getSource();
2005 SmallVector<Value> results(toElementsOp->getNumResults());
2006 for (
auto [idx, element] : llvm::enumerate(toElementsOp.getElements())) {
2008 if (element.use_empty())
2011 auto constIdx = LLVM::ConstantOp::create(
2012 rewriter, loc, idxType, rewriter.getIntegerAttr(idxType, idx));
2013 auto llvmType = typeConverter->convertType(element.getType());
2015 Value
result = LLVM::ExtractElementOp::create(rewriter, loc, llvmType,
2020 rewriter.replaceOp(toElementsOp, results);
2030 matchAndRewrite(vector::StepOp stepOp, OpAdaptor adaptor,
2031 ConversionPatternRewriter &rewriter)
const override {
2032 Type llvmType = typeConverter->convertType(stepOp.getType());
2033 rewriter.replaceOpWithNewOp<LLVM::StepVectorOp>(stepOp, llvmType);
2048class ContractionOpToMatmulOpLowering
2051 using MaskableOpRewritePattern::MaskableOpRewritePattern;
2053 ContractionOpToMatmulOpLowering(MLIRContext *context,
2054 PatternBenefit benefit = 100)
2055 : MaskableOpRewritePattern<vector::ContractionOp>(context, benefit) {}
2058 matchAndRewriteMaskableOp(vector::ContractionOp op, MaskingOpInterface maskOp,
2059 PatternRewriter &rewriter)
const override;
2079FailureOr<Value> ContractionOpToMatmulOpLowering::matchAndRewriteMaskableOp(
2080 vector::ContractionOp op, MaskingOpInterface maskOp,
2086 auto iteratorTypes = op.getIteratorTypes().getValue();
2092 Type opResType = op.getType();
2093 VectorType vecType = dyn_cast<VectorType>(opResType);
2094 if (vecType && vecType.isScalable()) {
2099 Type elementType = op.getLhsType().getElementType();
2103 Type dstElementType = vecType ? vecType.getElementType() : opResType;
2104 if (elementType != dstElementType)
2109 MLIRContext *ctx = op.getContext();
2110 Location loc = op.getLoc();
2114 Value
lhs = op.getLhs();
2115 auto lhsMap = op.getIndexingMapsArray()[0];
2117 lhs = vector::TransposeOp::create(rew, loc,
lhs, ArrayRef<int64_t>{1, 0});
2122 Value
rhs = op.getRhs();
2123 auto rhsMap = op.getIndexingMapsArray()[1];
2125 rhs = vector::TransposeOp::create(rew, loc,
rhs, ArrayRef<int64_t>{1, 0});
2130 VectorType lhsType = cast<VectorType>(
lhs.getType());
2131 VectorType rhsType = cast<VectorType>(
rhs.getType());
2132 int64_t lhsRows = lhsType.getDimSize(0);
2133 int64_t lhsColumns = lhsType.getDimSize(1);
2134 int64_t rhsColumns = rhsType.getDimSize(1);
2136 Type flattenedLHSType =
2137 VectorType::get(lhsType.getNumElements(), lhsType.getElementType());
2138 lhs = vector::ShapeCastOp::create(rew, loc, flattenedLHSType,
lhs);
2140 Type flattenedRHSType =
2141 VectorType::get(rhsType.getNumElements(), rhsType.getElementType());
2142 rhs = vector::ShapeCastOp::create(rew, loc, flattenedRHSType,
rhs);
2144 Value
mul = LLVM::MatrixMultiplyOp::create(
2146 VectorType::get(lhsRows * rhsColumns,
2147 cast<VectorType>(
lhs.getType()).getElementType()),
2148 lhs,
rhs, lhsRows, lhsColumns, rhsColumns);
2150 mul = vector::ShapeCastOp::create(
2152 VectorType::get({lhsRows, rhsColumns},
2157 auto accMap = op.getIndexingMapsArray()[2];
2159 mul = vector::TransposeOp::create(rew, loc,
mul, ArrayRef<int64_t>{1, 0});
2161 llvm_unreachable(
"invalid contraction semantics");
2163 Value res = isa<IntegerType>(elementType)
2164 ?
static_cast<Value
>(
2165 arith::AddIOp::create(rew, loc, op.getAcc(),
mul))
2166 : static_cast<Value>(
2167 arith::AddFOp::create(rew, loc, op.getAcc(),
mul));
2185class TransposeOpToMatrixTransposeOpLowering
2186 :
public OpRewritePattern<vector::TransposeOp> {
2190 LogicalResult matchAndRewrite(vector::TransposeOp op,
2191 PatternRewriter &rewriter)
const override {
2192 auto loc = op.getLoc();
2194 Value input = op.getVector();
2195 VectorType inputType = op.getSourceVectorType();
2196 VectorType resType = op.getResultVectorType();
2198 if (inputType.isScalable())
2200 op,
"This lowering does not support scalable vectors");
2203 ArrayRef<int64_t> transp = op.getPermutation();
2205 if (resType.getRank() != 2 || transp[0] != 1 || transp[1] != 0) {
2209 Type flattenedType =
2210 VectorType::get(resType.getNumElements(), resType.getElementType());
2212 vector::ShapeCastOp::create(rewriter, loc, flattenedType, input);
2215 Value trans = LLVM::MatrixTransposeOp::create(rewriter, loc, flattenedType,
2216 matrix, rows, columns);
2226 patterns.
add<VectorFMAOpNDRewritePattern>(patterns.
getContext());
2231 patterns.
add<ContractionOpToMatmulOpLowering>(patterns.
getContext(), benefit);
2236 patterns.
add<TransposeOpToMatrixTransposeOpLowering>(patterns.
getContext(),
2243 bool reassociateFPReductions,
bool force32BitVectorIndices,
2244 bool useVectorAlignment,
bool enableGEPInboundsNuw) {
2247 patterns.
add<VectorReductionOpConversion>(converter, reassociateFPReductions);
2248 patterns.
add<VectorCreateMaskOpConversion>(ctx, force32BitVectorIndices);
2249 patterns.
add<VectorLoadStoreConversion<vector::LoadOp>,
2250 VectorLoadStoreConversion<vector::MaskedLoadOp>,
2251 VectorLoadStoreConversion<vector::StoreOp>,
2252 VectorLoadStoreConversion<vector::MaskedStoreOp>>(
2253 converter, useVectorAlignment, enableGEPInboundsNuw);
2254 patterns.
add<VectorGatherOpConversion, VectorScatterOpConversion>(
2255 converter, useVectorAlignment);
2256 patterns.
add<VectorBitCastOpConversion, VectorShuffleOpConversion,
2257 VectorExtractOpConversion, VectorFMAOp1DConversion,
2258 VectorInsertOpConversion, VectorPrintOpConversion,
2259 VectorTypeCastOpConversion, VectorScaleOpConversion,
2260 VectorExpandLoadOpConversion, VectorCompressStoreOpConversion,
2261 VectorBroadcastScalarToLowRankLowering,
2262 VectorBroadcastScalarToNdLowering,
2263 VectorScalableInsertOpLowering, VectorScalableExtractOpLowering,
2264 MaskedReductionOpConversion, VectorInterleaveOpLowering,
2265 VectorDeinterleaveOpLowering, VectorFromElementsLowering,
2266 VectorToElementsLowering, VectorStepOpLowering>(converter);
2270struct VectorToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
2271 VectorToLLVMDialectInterface(
Dialect *dialect)
2272 : ConvertToLLVMPatternInterface(dialect) {}
2274 using ConvertToLLVMPatternInterface::ConvertToLLVMPatternInterface;
2275 void loadDependentDialects(MLIRContext *context)
const final {
2276 context->loadDialect<LLVM::LLVMDialect>();
2281 void populateConvertToLLVMConversionPatterns(
2282 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
2283 RewritePatternSet &patterns)
const final {
2292 dialect->addInterfaces<VectorToLLVMDialectInterface>();
static Value getIndexedPtrs(ConversionPatternRewriter &rewriter, Location loc, const LLVMTypeConverter &typeConverter, MemRefType memRefType, Value llvmMemref, Value base, Value index, VectorType vectorType)
LogicalResult getVectorToLLVMAlignment(const LLVMTypeConverter &typeConverter, VectorType vectorType, MemRefType memrefType, unsigned &align, bool useVectorAlignment)
LogicalResult getVectorAlignment(const LLVMTypeConverter &typeConverter, VectorType vectorType, unsigned &align)
LogicalResult getMemRefAlignment(const LLVMTypeConverter &typeConverter, MemRefType memrefType, unsigned &align)
static Value extractOne(ConversionPatternRewriter &rewriter, const LLVMTypeConverter &typeConverter, Location loc, Value val, Type llvmType, int64_t rank, int64_t pos)
static Value insertOne(ConversionPatternRewriter &rewriter, const LLVMTypeConverter &typeConverter, Location loc, Value val1, Value val2, Type llvmType, int64_t rank, int64_t pos)
static Value getAsLLVMValue(OpBuilder &builder, Location loc, OpFoldResult foldResult)
Convert foldResult into a Value.
static LogicalResult isMemRefTypeSupported(MemRefType memRefType, const LLVMTypeConverter &converter)
LogicalResult initialize(unsigned origNumLoops, ArrayRef< ReassociationIndices > foldedIterationDims)
static Value broadcast(Location loc, Value toBroadcast, unsigned numElements, const TypeConverter &typeConverter, ConversionPatternRewriter &rewriter)
Broadcasts the value to vector with numElements number of elements.
static void printOp(llvm::raw_ostream &os, Operation *op, OpPrintingFlags &flags)
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
IntegerAttr getI32IntegerAttr(int32_t value)
TypedAttr getZeroAttr(Type type)
MLIRContext * getContext() const
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
ConvertOpToLLVMPattern(const LLVMTypeConverter &typeConverter, PatternBenefit benefit=1)
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Conversion from types to the LLVM IR dialect.
const llvm::DataLayout & getDataLayout() const
Returns the data layout to use during and after conversion.
FailureOr< unsigned > getMemRefAddressSpace(BaseMemRefType type) const
Return the LLVM address space corresponding to the memory space of the memref type type or failure if...
LLVM::LLVMDialect * getDialect() const
Returns the LLVM dialect.
Utility class to translate MLIR LLVM dialect types to LLVM IR.
unsigned getPreferredAlignment(Type type, const llvm::DataLayout &layout)
Returns the preferred alignment for the type given the data layout.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
Helper class to produce LLVM dialect operations extracting or inserting elements of a MemRef descript...
LLVM::LLVMPointerType getElementPtrType()
Returns the (LLVM) pointer type this descriptor contains.
Generic implementation of one-to-one conversion from "SourceOp" to "TargetOp" where the latter belong...
This class helps build Operations.
This class represents a single result from folding an operation.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
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.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isIntOrIndex() const
Return true if this is an integer (of any signedness) or an index type.
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
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.
Location getLoc() const
Return the location of this value.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
void printType(Type type, AsmPrinter &printer)
Prints an LLVM Dialect type.
void nDVectorIterate(const NDVectorTypeInfo &info, OpBuilder &builder, function_ref< void(ArrayRef< int64_t >)> fun)
NDVectorTypeInfo extractNDVectorTypeInfo(VectorType vectorType, const LLVMTypeConverter &converter)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintBF16Fn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintOpenFn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
Value getStridedElementPtr(OpBuilder &builder, Location loc, const LLVMTypeConverter &converter, MemRefType type, Value memRefDesc, ValueRange indices, LLVM::GEPNoWrapFlags noWrapFlags=LLVM::GEPNoWrapFlags::none)
Performs the index computation to get to the element at indices of the memory pointed to by memRefDes...
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintCommaFn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintI64Fn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
Helper functions to look up or create the declaration for commonly used external C function calls.
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintNewlineFn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintCloseFn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintU64Fn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintF32Fn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreateApFloatPrintFn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
LogicalResult createPrintStrCall(OpBuilder &builder, Location loc, ModuleOp moduleOp, StringRef symbolName, StringRef string, const LLVMTypeConverter &typeConverter, bool addNewline=true, std::optional< StringRef > runtimeFunctionName={}, SymbolTableCollection *symbolTables=nullptr)
Generate IR that prints the given string to stdout.
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintF16Fn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
FailureOr< LLVM::LLVMFuncOp > lookupOrCreatePrintF64Fn(OpBuilder &b, Operation *moduleOp, SymbolTableCollection *symbolTables=nullptr)
LLVM::FastmathFlags convertArithFastMathFlagsToLLVM(arith::FastMathFlags arithFMF)
Maps arithmetic fastmath enum values to LLVM enum values.
bool hasNegativeStaticStride(MemRefType memRefTy)
Returns true if any stride of memRefTy is statically known to be negative.
bool isReductionIterator(Attribute attr)
Returns true if attr has "reduction" iterator type semantics.
void populateVectorContractToMatrixMultiply(RewritePatternSet &patterns, PatternBenefit benefit=100)
Populate the pattern set with the following patterns:
void populateVectorRankReducingFMAPattern(RewritePatternSet &patterns)
Populates a pattern that rank-reduces n-D FMAs into (n-1)-D FMAs where n > 1.
bool isParallelIterator(Attribute attr)
Returns true if attr has "parallel" iterator type semantics.
void registerConvertVectorToLLVMInterface(DialectRegistry ®istry)
SmallVector< int64_t > getAsIntegers(ArrayRef< Value > values)
Returns the integer numbers in values.
void populateVectorTransposeToFlatTranspose(RewritePatternSet &patterns, PatternBenefit benefit=100)
Populate the pattern set with the following patterns:
Value createReductionNeutralValue(OpBuilder &builder, Location loc, Type type, vector::CombiningKind kind)
Creates a constant filled with the neutral (identity) value for the given reduction kind.
Include the generated interface declarations.
SmallVector< OpFoldResult > getMixedValues(ArrayRef< int64_t > staticValues, ValueRange dynamicValues, MLIRContext *context)
Return a vector of OpFoldResults with the same size a staticValues, but all elements for which Shaped...
void populateVectorToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, bool reassociateFPReductions=false, bool force32BitVectorIndices=false, bool useVectorAlignment=false, bool enableGEPInboundsNuw=false)
Collect a set of patterns to convert from the Vector dialect to LLVM.
void bindDims(MLIRContext *ctx, AffineExprTy &...exprs)
Bind a list of AffineExpr references to DimExpr at positions: [0 .
Value getValueOrCreateCastToIndexLike(OpBuilder &b, Location loc, Type targetType, Value value)
Create a cast from an index-like value (index or integer) to another index-like value.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
A pattern for ops that implement MaskableOpInterface and that might be masked (i.e.