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 Type idxType = typeConverter.convertType(rewriter.getIndexType());
49 auto constant = LLVM::ConstantOp::create(
50 rewriter, loc, idxType, rewriter.getIntegerAttr(idxType, pos));
51 return LLVM::InsertElementOp::create(rewriter, loc, llvmType, val1, val2,
54 return LLVM::InsertValueOp::create(rewriter, loc, val1, val2, pos);
62 Type idxType = typeConverter.convertType(rewriter.getIndexType());
63 auto constant = LLVM::ConstantOp::create(
64 rewriter, loc, idxType, rewriter.getIntegerAttr(idxType, pos));
65 return LLVM::ExtractElementOp::create(rewriter, loc, llvmType, val,
68 return LLVM::ExtractValueOp::create(rewriter, loc, val, pos);
73 VectorType vectorType,
unsigned &align) {
74 Type convertedVectorTy = typeConverter.convertType(vectorType);
75 if (!convertedVectorTy)
78 llvm::LLVMContext llvmContext;
88 MemRefType memrefType,
unsigned &align) {
89 Type elementTy = typeConverter.convertType(memrefType.getElementType());
95 llvm::LLVMContext llvmContext;
108 VectorType vectorType,
109 MemRefType memrefType,
unsigned &align,
110 bool useVectorAlignment) {
111 if (useVectorAlignment) {
126 if (!memRefType.isLastDimUnitStride())
136 MemRefType memRefType,
Value llvmMemref,
Value base,
139 "unsupported memref type");
140 assert(vectorType.getRank() == 1 &&
"expected a 1-d vector type");
144 vectorType.getScalableDims()[0]);
145 return LLVM::GEPOp::create(
146 rewriter, loc, ptrsType,
147 typeConverter.convertType(memRefType.getElementType()), base,
index);
154 if (
auto attr = dyn_cast<Attribute>(foldResult)) {
155 auto intAttr = cast<IntegerAttr>(attr);
156 return LLVM::ConstantOp::create(builder, loc, intAttr).getResult();
159 return cast<Value>(foldResult);
165using VectorScaleOpConversion =
169class VectorBitCastOpConversion
172 using ConvertOpToLLVMPattern<vector::BitCastOp>::ConvertOpToLLVMPattern;
175 matchAndRewrite(vector::BitCastOp bitCastOp, OpAdaptor adaptor,
176 ConversionPatternRewriter &rewriter)
const override {
178 VectorType resultTy = bitCastOp.getResultVectorType();
179 if (resultTy.getRank() > 1)
181 Type newResultTy = typeConverter->convertType(resultTy);
182 rewriter.replaceOpWithNewOp<LLVM::BitcastOp>(bitCastOp, newResultTy,
183 adaptor.getOperands()[0]);
191static void replaceLoadOrStoreOp(vector::LoadOp loadOp,
192 vector::LoadOpAdaptor adaptor,
193 VectorType vectorTy,
Value ptr,
unsigned align,
194 ConversionPatternRewriter &rewriter) {
195 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(loadOp, vectorTy,
ptr, align,
197 loadOp.getNontemporal());
200static void replaceLoadOrStoreOp(vector::MaskedLoadOp loadOp,
201 vector::MaskedLoadOpAdaptor adaptor,
202 VectorType vectorTy,
Value ptr,
unsigned align,
203 ConversionPatternRewriter &rewriter) {
204 rewriter.replaceOpWithNewOp<LLVM::MaskedLoadOp>(
205 loadOp, vectorTy,
ptr, adaptor.getMask(), adaptor.getPassThru(), align);
208static void replaceLoadOrStoreOp(vector::StoreOp storeOp,
209 vector::StoreOpAdaptor adaptor,
210 VectorType vectorTy,
Value ptr,
unsigned align,
211 ConversionPatternRewriter &rewriter) {
212 rewriter.replaceOpWithNewOp<LLVM::StoreOp>(storeOp, adaptor.getValueToStore(),
214 storeOp.getNontemporal());
217static void replaceLoadOrStoreOp(vector::MaskedStoreOp storeOp,
218 vector::MaskedStoreOpAdaptor adaptor,
219 VectorType vectorTy,
Value ptr,
unsigned align,
220 ConversionPatternRewriter &rewriter) {
221 rewriter.replaceOpWithNewOp<LLVM::MaskedStoreOp>(
222 storeOp, adaptor.getValueToStore(),
ptr, adaptor.getMask(), align);
227template <
class LoadOrStoreOp>
230 explicit VectorLoadStoreConversion(
const LLVMTypeConverter &typeConv,
232 bool enableGEPInboundsNuw)
233 : ConvertOpToLLVMPattern<LoadOrStoreOp>(typeConv),
234 useVectorAlignment(useVectorAlign),
235 enableGEPInboundsNuw(enableGEPInboundsNuw) {}
238 matchAndRewrite(LoadOrStoreOp loadOrStoreOp,
239 typename LoadOrStoreOp::Adaptor adaptor,
240 ConversionPatternRewriter &rewriter)
const override {
242 VectorType vectorTy = loadOrStoreOp.getVectorType();
243 if (vectorTy.getRank() > 1)
246 auto loc = loadOrStoreOp->getLoc();
247 MemRefType memRefTy = loadOrStoreOp.getMemRefType();
251 unsigned align = loadOrStoreOp.getAlignment().value_or(0);
254 memRefTy, align, useVectorAlignment)))
255 return rewriter.notifyMatchFailure(loadOrStoreOp,
256 "could not resolve alignment");
264 LLVM::GEPNoWrapFlags noWrapFlags = LLVM::GEPNoWrapFlags::none;
265 if constexpr (std::is_same_v<LoadOrStoreOp, vector::LoadOp> ||
266 std::is_same_v<LoadOrStoreOp, vector::StoreOp>) {
270 auto [strides, offset] = memRefTy.getStridesAndOffset();
271 assert((strides.empty() || strides.back() == 1) &&
272 "vector.load/store requires unit trailing memref stride");
273 if (enableGEPInboundsNuw) {
274 noWrapFlags = noWrapFlags | LLVM::GEPNoWrapFlags::inbounds;
279 "Invalid MemRef type - should have been rejected by Op verifier.");
280 noWrapFlags = noWrapFlags | LLVM::GEPNoWrapFlags::nuw;
283 auto vtype = cast<VectorType>(
284 this->typeConverter->convertType(loadOrStoreOp.getVectorType()));
287 adaptor.getIndices(), noWrapFlags);
288 replaceLoadOrStoreOp(loadOrStoreOp, adaptor, vtype, dataPtr, align,
298 const bool useVectorAlignment;
299 const bool enableGEPInboundsNuw;
303class VectorGatherOpConversion
306 explicit VectorGatherOpConversion(
const LLVMTypeConverter &typeConv,
308 : ConvertOpToLLVMPattern<vector::GatherOp>(typeConv),
309 useVectorAlignment(useVectorAlign) {}
310 using ConvertOpToLLVMPattern<vector::GatherOp>::ConvertOpToLLVMPattern;
313 matchAndRewrite(vector::GatherOp gather, OpAdaptor adaptor,
314 ConversionPatternRewriter &rewriter)
const override {
315 Location loc = gather->getLoc();
316 MemRefType memRefType = dyn_cast<MemRefType>(gather.getBaseType());
317 assert(memRefType &&
"The base should be bufferized");
321 return rewriter.notifyMatchFailure(gather,
"memref type not supported");
323 VectorType vType = gather.getVectorType();
324 if (vType.getRank() > 1) {
325 return rewriter.notifyMatchFailure(
326 gather,
"only 1-D vectors can be lowered to LLVM");
331 unsigned align = gather.getAlignment().value_or(0);
334 memRefType, align, useVectorAlignment)))
335 return rewriter.notifyMatchFailure(gather,
"could not resolve alignment");
339 adaptor.getBase(), adaptor.getOffsets());
340 Value base = adaptor.getBase();
342 getIndexedPtrs(rewriter, loc, *this->getTypeConverter(), memRefType,
343 base, ptr, adaptor.getIndices(), vType);
346 rewriter.replaceOpWithNewOp<LLVM::masked_gather>(
347 gather, typeConverter->convertType(vType), ptrs, adaptor.getMask(),
348 adaptor.getPassThru(), align);
357 const bool useVectorAlignment;
361class VectorScatterOpConversion
364 explicit VectorScatterOpConversion(
const LLVMTypeConverter &typeConv,
366 : ConvertOpToLLVMPattern<vector::ScatterOp>(typeConv),
367 useVectorAlignment(useVectorAlign) {}
369 using ConvertOpToLLVMPattern<vector::ScatterOp>::ConvertOpToLLVMPattern;
372 matchAndRewrite(vector::ScatterOp scatter, OpAdaptor adaptor,
373 ConversionPatternRewriter &rewriter)
const override {
374 auto loc = scatter->getLoc();
375 auto memRefType = dyn_cast<MemRefType>(scatter.getBaseType());
376 assert(memRefType &&
"The base should be bufferized");
380 return rewriter.notifyMatchFailure(scatter,
"memref type not supported");
382 VectorType vType = scatter.getVectorType();
383 if (vType.getRank() > 1) {
384 return rewriter.notifyMatchFailure(
385 scatter,
"only 1-D vectors can be lowered to LLVM");
390 unsigned align = scatter.getAlignment().value_or(0);
393 memRefType, align, useVectorAlignment)))
394 return rewriter.notifyMatchFailure(scatter,
395 "could not resolve alignment");
399 adaptor.getBase(), adaptor.getOffsets());
401 getIndexedPtrs(rewriter, loc, *this->getTypeConverter(), memRefType,
402 adaptor.getBase(), ptr, adaptor.getIndices(), vType);
405 rewriter.replaceOpWithNewOp<LLVM::masked_scatter>(
406 scatter, adaptor.getValueToStore(), ptrs, adaptor.getMask(), align);
415 const bool useVectorAlignment;
419class VectorExpandLoadOpConversion
422 using ConvertOpToLLVMPattern<vector::ExpandLoadOp>::ConvertOpToLLVMPattern;
425 matchAndRewrite(vector::ExpandLoadOp expand, OpAdaptor adaptor,
426 ConversionPatternRewriter &rewriter)
const override {
427 auto loc = expand->getLoc();
428 MemRefType memRefType = expand.getMemRefType();
431 auto vtype = typeConverter->convertType(expand.getVectorType());
433 adaptor.getBase(), adaptor.getIndices());
438 uint64_t alignment = expand.getAlignment().value_or(1);
440 rewriter.replaceOpWithNewOp<LLVM::masked_expandload>(
441 expand, vtype, ptr, adaptor.getMask(), adaptor.getPassThru(),
448class VectorCompressStoreOpConversion
451 using ConvertOpToLLVMPattern<vector::CompressStoreOp>::ConvertOpToLLVMPattern;
454 matchAndRewrite(vector::CompressStoreOp compress, OpAdaptor adaptor,
455 ConversionPatternRewriter &rewriter)
const override {
456 auto loc = compress->getLoc();
457 MemRefType memRefType = compress.getMemRefType();
461 adaptor.getBase(), adaptor.getIndices());
466 uint64_t alignment = compress.getAlignment().value_or(1);
468 rewriter.replaceOpWithNewOp<LLVM::masked_compressstore>(
469 compress, adaptor.getValueToStore(), ptr, adaptor.getMask(), alignment);
475class ReductionNeutralZero {};
476class ReductionNeutralIntOne {};
477class ReductionNeutralFPOne {};
478class ReductionNeutralAllOnes {};
479class ReductionNeutralSIntMin {};
480class ReductionNeutralUIntMin {};
481class ReductionNeutralSIntMax {};
482class ReductionNeutralUIntMax {};
483class ReductionNeutralFPQNaN {};
484class ReductionNeutralFPNegQNaN {};
485class ReductionNeutralFPNegInf {};
486class ReductionNeutralFPPosInf {};
487class ReductionNeutralFPLowestFinite {};
488class ReductionNeutralFPLargestFinite {};
492 ConversionPatternRewriter &rewriter,
494 return LLVM::ConstantOp::create(rewriter, loc, llvmType,
495 rewriter.getZeroAttr(llvmType));
500 ConversionPatternRewriter &rewriter,
502 return LLVM::ConstantOp::create(rewriter, loc, llvmType,
503 rewriter.getIntegerAttr(llvmType, 1));
508 ConversionPatternRewriter &rewriter,
510 return LLVM::ConstantOp::create(rewriter, loc, llvmType,
511 rewriter.getFloatAttr(llvmType, 1.0));
516 ConversionPatternRewriter &rewriter,
518 return LLVM::ConstantOp::create(
519 rewriter, loc, llvmType,
520 rewriter.getIntegerAttr(
526 ConversionPatternRewriter &rewriter,
528 return LLVM::ConstantOp::create(
529 rewriter, loc, llvmType,
530 rewriter.getIntegerAttr(llvmType, llvm::APInt::getSignedMinValue(
536 ConversionPatternRewriter &rewriter,
538 return LLVM::ConstantOp::create(
539 rewriter, loc, llvmType,
540 rewriter.getIntegerAttr(llvmType, llvm::APInt::getMinValue(
546 ConversionPatternRewriter &rewriter,
548 return LLVM::ConstantOp::create(
549 rewriter, loc, llvmType,
550 rewriter.getIntegerAttr(llvmType, llvm::APInt::getSignedMaxValue(
556 ConversionPatternRewriter &rewriter,
558 return LLVM::ConstantOp::create(
559 rewriter, loc, llvmType,
560 rewriter.getIntegerAttr(llvmType, llvm::APInt::getMaxValue(
566 ConversionPatternRewriter &rewriter,
568 auto floatType = cast<FloatType>(llvmType);
569 return LLVM::ConstantOp::create(
570 rewriter, loc, llvmType,
571 rewriter.getFloatAttr(
572 llvmType, llvm::APFloat::getQNaN(floatType.getFloatSemantics(),
578 ConversionPatternRewriter &rewriter,
580 auto floatType = cast<FloatType>(llvmType);
581 return LLVM::ConstantOp::create(
582 rewriter, loc, llvmType,
583 rewriter.getFloatAttr(
584 llvmType, llvm::APFloat::getQNaN(floatType.getFloatSemantics(),
590 ConversionPatternRewriter &rewriter,
592 auto floatType = cast<FloatType>(llvmType);
593 return LLVM::ConstantOp::create(
594 rewriter, loc, llvmType,
595 rewriter.getFloatAttr(llvmType,
596 llvm::APFloat::getInf(floatType.getFloatSemantics(),
602 ConversionPatternRewriter &rewriter,
604 auto floatType = cast<FloatType>(llvmType);
605 return LLVM::ConstantOp::create(
606 rewriter, loc, llvmType,
607 rewriter.getFloatAttr(llvmType,
608 llvm::APFloat::getInf(floatType.getFloatSemantics(),
614 ConversionPatternRewriter &rewriter,
616 auto floatType = cast<FloatType>(llvmType);
617 return LLVM::ConstantOp::create(
618 rewriter, loc, llvmType,
619 rewriter.getFloatAttr(
620 llvmType, llvm::APFloat::getLargest(floatType.getFloatSemantics(),
627 ConversionPatternRewriter &rewriter,
Location loc,
629 auto floatType = cast<FloatType>(llvmType);
630 return LLVM::ConstantOp::create(
631 rewriter, loc, llvmType,
632 rewriter.getFloatAttr(
633 llvmType, llvm::APFloat::getLargest(floatType.getFloatSemantics(),
639template <
class ReductionNeutral>
640static Value getOrCreateAccumulator(ConversionPatternRewriter &rewriter,
653static Value createVectorLengthValue(ConversionPatternRewriter &rewriter,
655 VectorType vType = cast<VectorType>(llvmType);
656 auto vShape = vType.getShape();
657 assert(vShape.size() == 1 &&
"Unexpected multi-dim vector type");
659 Value baseVecLength = LLVM::ConstantOp::create(
660 rewriter, loc, rewriter.getI32Type(),
661 rewriter.getIntegerAttr(rewriter.getI32Type(), vShape[0]));
663 if (!vType.getScalableDims()[0])
664 return baseVecLength;
667 Value vScale = vector::VectorScaleOp::create(rewriter, loc);
669 arith::IndexCastOp::create(rewriter, loc, rewriter.getI32Type(), vScale);
670 Value scalableVecLength =
671 arith::MulIOp::create(rewriter, loc, baseVecLength, vScale);
672 return scalableVecLength;
679template <
class LLVMRedIntrinOp,
class ScalarOp>
680static Value createIntegerReductionArithmeticOpLowering(
681 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
685 LLVMRedIntrinOp::create(rewriter, loc, llvmType, vectorOperand);
688 result = ScalarOp::create(rewriter, loc, accumulator,
result);
696template <
class LLVMRedIntrinOp>
697static Value createIntegerReductionComparisonOpLowering(
698 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
699 Value vectorOperand,
Value accumulator, LLVM::ICmpPredicate predicate) {
701 LLVMRedIntrinOp::create(rewriter, loc, llvmType, vectorOperand);
704 LLVM::ICmpOp::create(rewriter, loc, predicate, accumulator,
result);
705 result = LLVM::SelectOp::create(rewriter, loc, cmp, accumulator,
result);
711template <
typename Source>
712struct VectorToScalarMapper;
714struct VectorToScalarMapper<
LLVM::vector_reduce_fmaximum> {
715 using Type = LLVM::MaximumOp;
718struct VectorToScalarMapper<
LLVM::vector_reduce_fminimum> {
719 using Type = LLVM::MinimumOp;
722struct VectorToScalarMapper<
LLVM::vector_reduce_fmax> {
723 using Type = LLVM::MaxNumOp;
726struct VectorToScalarMapper<
LLVM::vector_reduce_fmin> {
727 using Type = LLVM::MinNumOp;
730struct VectorToScalarMapper<
LLVM::vector_reduce_fmaximumnum> {
731 using Type = LLVM::MaximumNumOp;
734struct VectorToScalarMapper<
LLVM::vector_reduce_fminimumnum> {
735 using Type = LLVM::MinimumNumOp;
739template <
class LLVMRedIntrinOp>
740static Value createFPReductionComparisonOpLowering(
741 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
742 Value vectorOperand,
Value accumulator, LLVM::FastmathFlagsAttr fmf) {
744 LLVMRedIntrinOp::create(rewriter, loc, llvmType, vectorOperand, fmf);
747 result = VectorToScalarMapper<LLVMRedIntrinOp>::Type::create(
748 rewriter, loc,
result, accumulator);
755class MaskNeutralFMaximumNum {};
756class MaskNeutralFMinimumNum {};
762static llvm::APFloat getMaskNeutralValue(MaskNeutralFMaximumNum,
763 const llvm::fltSemantics &semantics,
764 bool noNaNs,
bool noInfs) {
766 return llvm::APFloat::getQNaN(semantics);
768 return llvm::APFloat::getLargest(semantics,
true);
769 return llvm::APFloat::getInf(semantics,
true);
774static llvm::APFloat getMaskNeutralValue(MaskNeutralFMinimumNum,
775 const llvm::fltSemantics &semantics,
776 bool noNaNs,
bool noInfs) {
778 return llvm::APFloat::getQNaN(semantics);
780 return llvm::APFloat::getLargest(semantics);
781 return llvm::APFloat::getInf(semantics);
789template <
class LLVMRedIntrinOp,
class MaskNeutral>
791lowerMaskedReductionWithRegular(ConversionPatternRewriter &rewriter,
794 Value mask, LLVM::FastmathFlagsAttr fmf) {
795 const auto &floatSemantics = cast<FloatType>(llvmType).getFloatSemantics();
796 auto value = getMaskNeutralValue(
797 MaskNeutral{}, floatSemantics,
798 LLVM::bitEnumContainsAny(fmf.getValue(), LLVM::FastmathFlags::nnan),
799 LLVM::bitEnumContainsAny(fmf.getValue(), LLVM::FastmathFlags::ninf));
802 const Value vectorMaskNeutral =
803 LLVM::ConstantOp::create(rewriter, loc, vectorType, denseValue);
804 const Value selectedVectorByMask = LLVM::SelectOp::create(
805 rewriter, loc, mask, vectorOperand, vectorMaskNeutral);
806 return createFPReductionComparisonOpLowering<LLVMRedIntrinOp>(
807 rewriter, loc, llvmType, selectedVectorByMask, accumulator, fmf);
810template <
class LLVMRedIntrinOp,
class ReductionNeutral>
812lowerReductionWithStartValue(ConversionPatternRewriter &rewriter,
Location loc,
814 Value accumulator, LLVM::FastmathFlagsAttr fmf) {
815 accumulator = getOrCreateAccumulator<ReductionNeutral>(rewriter, loc,
816 llvmType, accumulator);
817 return LLVMRedIntrinOp::create(rewriter, loc, llvmType,
818 accumulator, vectorOperand,
822template <
class LLVMVPRedIntrinOp,
class ReductionNeutral>
823static Value lowerPredicatedReductionWithStartValue(
824 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
826 accumulator = getOrCreateAccumulator<ReductionNeutral>(rewriter, loc,
827 llvmType, accumulator);
829 createVectorLengthValue(rewriter, loc, vectorOperand.
getType());
830 return LLVMVPRedIntrinOp::create(rewriter, loc, llvmType,
831 accumulator, vectorOperand,
835template <
class LLVMIntVPRedIntrinOp,
class IntReductionNeutral,
836 class LLVMFPVPRedIntrinOp,
class FPReductionNeutral>
837static Value lowerPredicatedReductionWithStartValue(
838 ConversionPatternRewriter &rewriter,
Location loc,
Type llvmType,
841 return lowerPredicatedReductionWithStartValue<LLVMIntVPRedIntrinOp,
842 IntReductionNeutral>(
843 rewriter, loc, llvmType, vectorOperand, accumulator, mask);
846 return lowerPredicatedReductionWithStartValue<LLVMFPVPRedIntrinOp,
848 rewriter, loc, llvmType, vectorOperand, accumulator, mask);
852class VectorReductionOpConversion
855 explicit VectorReductionOpConversion(
const LLVMTypeConverter &typeConv,
856 bool reassociateFPRed)
857 : ConvertOpToLLVMPattern<vector::ReductionOp>(typeConv),
858 reassociateFPReductions(reassociateFPRed) {}
861 matchAndRewrite(vector::ReductionOp reductionOp, OpAdaptor adaptor,
862 ConversionPatternRewriter &rewriter)
const override {
863 auto kind = reductionOp.getKind();
864 Type eltType = reductionOp.getResult().getType();
865 Type llvmType = typeConverter->convertType(eltType);
866 Value operand = adaptor.getVector();
867 Value acc = adaptor.getAcc();
868 Location loc = reductionOp.getLoc();
874 case vector::CombiningKind::ADD:
876 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_add,
878 rewriter, loc, llvmType, operand, acc);
880 case vector::CombiningKind::MUL:
882 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_mul,
884 rewriter, loc, llvmType, operand, acc);
886 case vector::CombiningKind::MINUI:
887 result = createIntegerReductionComparisonOpLowering<
888 LLVM::vector_reduce_umin>(rewriter, loc, llvmType, operand, acc,
889 LLVM::ICmpPredicate::ule);
891 case vector::CombiningKind::MINSI:
892 result = createIntegerReductionComparisonOpLowering<
893 LLVM::vector_reduce_smin>(rewriter, loc, llvmType, operand, acc,
894 LLVM::ICmpPredicate::sle);
896 case vector::CombiningKind::MAXUI:
897 result = createIntegerReductionComparisonOpLowering<
898 LLVM::vector_reduce_umax>(rewriter, loc, llvmType, operand, acc,
899 LLVM::ICmpPredicate::uge);
901 case vector::CombiningKind::MAXSI:
902 result = createIntegerReductionComparisonOpLowering<
903 LLVM::vector_reduce_smax>(rewriter, loc, llvmType, operand, acc,
904 LLVM::ICmpPredicate::sge);
906 case vector::CombiningKind::AND:
908 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_and,
910 rewriter, loc, llvmType, operand, acc);
912 case vector::CombiningKind::OR:
914 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_or,
916 rewriter, loc, llvmType, operand, acc);
918 case vector::CombiningKind::XOR:
920 createIntegerReductionArithmeticOpLowering<LLVM::vector_reduce_xor,
922 rewriter, loc, llvmType, operand, acc);
927 rewriter.replaceOp(reductionOp,
result);
932 if (!isa<FloatType>(eltType))
935 arith::FastMathFlagsAttr fMFAttr = reductionOp.getFastMathFlagsAttr();
936 LLVM::FastmathFlagsAttr fmf = LLVM::FastmathFlagsAttr::get(
937 reductionOp.getContext(),
939 fmf = LLVM::FastmathFlagsAttr::get(
940 reductionOp.getContext(),
941 fmf.getValue() | (reassociateFPReductions ? LLVM::FastmathFlags::reassoc
942 : LLVM::FastmathFlags::none));
947 case vector::CombiningKind::ADD:
948 result = lowerReductionWithStartValue<LLVM::vector_reduce_fadd,
949 ReductionNeutralZero>(
950 rewriter, loc, llvmType, operand, acc, fmf);
952 case vector::CombiningKind::MUL:
953 result = lowerReductionWithStartValue<LLVM::vector_reduce_fmul,
954 ReductionNeutralFPOne>(
955 rewriter, loc, llvmType, operand, acc, fmf);
957 case vector::CombiningKind::MINIMUMF:
959 createFPReductionComparisonOpLowering<LLVM::vector_reduce_fminimum>(
960 rewriter, loc, llvmType, operand, acc, fmf);
962 case vector::CombiningKind::MAXIMUMF:
964 createFPReductionComparisonOpLowering<LLVM::vector_reduce_fmaximum>(
965 rewriter, loc, llvmType, operand, acc, fmf);
967 case vector::CombiningKind::MINNUMF:
968 result = createFPReductionComparisonOpLowering<LLVM::vector_reduce_fmin>(
969 rewriter, loc, llvmType, operand, acc, fmf);
971 case vector::CombiningKind::MAXNUMF:
972 result = createFPReductionComparisonOpLowering<LLVM::vector_reduce_fmax>(
973 rewriter, loc, llvmType, operand, acc, fmf);
975 case vector::CombiningKind::MAXIMUMNUMF:
976 result = createFPReductionComparisonOpLowering<
977 LLVM::vector_reduce_fmaximumnum>(rewriter, loc, llvmType, operand,
980 case vector::CombiningKind::MINIMUMNUMF:
981 result = createFPReductionComparisonOpLowering<
982 LLVM::vector_reduce_fminimumnum>(rewriter, loc, llvmType, operand,
989 rewriter.replaceOp(reductionOp,
result);
994 const bool reassociateFPReductions;
1005template <
class MaskedOp>
1006class VectorMaskOpConversionBase
1009 using ConvertOpToLLVMPattern<vector::MaskOp>::ConvertOpToLLVMPattern;
1012 matchAndRewrite(vector::MaskOp maskOp, OpAdaptor adaptor,
1013 ConversionPatternRewriter &rewriter)
const final {
1015 auto maskedOp = llvm::dyn_cast_or_null<MaskedOp>(maskOp.getMaskableOp());
1018 return matchAndRewriteMaskableOp(maskOp, maskedOp, rewriter);
1022 virtual LogicalResult
1023 matchAndRewriteMaskableOp(vector::MaskOp maskOp,
1024 vector::MaskableOpInterface maskableOp,
1025 ConversionPatternRewriter &rewriter)
const = 0;
1028class MaskedReductionOpConversion
1029 :
public VectorMaskOpConversionBase<vector::ReductionOp> {
1032 using VectorMaskOpConversionBase<
1033 vector::ReductionOp>::VectorMaskOpConversionBase;
1035 LogicalResult matchAndRewriteMaskableOp(
1036 vector::MaskOp maskOp, MaskableOpInterface maskableOp,
1037 ConversionPatternRewriter &rewriter)
const override {
1038 auto reductionOp = cast<ReductionOp>(maskableOp.getOperation());
1039 auto kind = reductionOp.getKind();
1040 Type eltType = reductionOp.getResult().getType();
1041 Type llvmType = typeConverter->convertType(eltType);
1042 Value operand = reductionOp.getVector();
1043 Value acc = reductionOp.getAcc();
1044 Location loc = reductionOp.getLoc();
1046 arith::FastMathFlagsAttr fMFAttr = reductionOp.getFastMathFlagsAttr();
1047 LLVM::FastmathFlagsAttr fmf = LLVM::FastmathFlagsAttr::get(
1048 reductionOp.getContext(),
1051 LLVM::bitEnumContainsAny(fmf.getValue(), LLVM::FastmathFlags::ninf);
1055 case vector::CombiningKind::ADD:
1056 result = lowerPredicatedReductionWithStartValue<
1057 LLVM::VPReduceAddOp, ReductionNeutralZero, LLVM::VPReduceFAddOp,
1058 ReductionNeutralZero>(rewriter, loc, llvmType, operand, acc,
1061 case vector::CombiningKind::MUL:
1062 result = lowerPredicatedReductionWithStartValue<
1063 LLVM::VPReduceMulOp, ReductionNeutralIntOne, LLVM::VPReduceFMulOp,
1064 ReductionNeutralFPOne>(rewriter, loc, llvmType, operand, acc,
1067 case vector::CombiningKind::MINUI:
1068 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceUMinOp,
1069 ReductionNeutralUIntMax>(
1070 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1072 case vector::CombiningKind::MINSI:
1073 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceSMinOp,
1074 ReductionNeutralSIntMax>(
1075 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1077 case vector::CombiningKind::MAXUI:
1078 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceUMaxOp,
1079 ReductionNeutralUIntMin>(
1080 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1082 case vector::CombiningKind::MAXSI:
1083 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceSMaxOp,
1084 ReductionNeutralSIntMin>(
1085 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1087 case vector::CombiningKind::AND:
1088 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceAndOp,
1089 ReductionNeutralAllOnes>(
1090 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1092 case vector::CombiningKind::OR:
1093 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceOrOp,
1094 ReductionNeutralZero>(
1095 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1097 case vector::CombiningKind::XOR:
1098 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceXorOp,
1099 ReductionNeutralZero>(
1100 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1102 case vector::CombiningKind::MINNUMF:
1104 lowerPredicatedReductionWithStartValue<LLVM::VPReduceFMinOp,
1105 ReductionNeutralFPNegQNaN>(
1106 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1108 case vector::CombiningKind::MAXNUMF:
1109 result = lowerPredicatedReductionWithStartValue<LLVM::VPReduceFMaxOp,
1110 ReductionNeutralFPQNaN>(
1111 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1113 case CombiningKind::MAXIMUMF:
1118 ? lowerPredicatedReductionWithStartValue<
1119 LLVM::VPReduceFMaximumOp, ReductionNeutralFPLowestFinite>(
1120 rewriter, loc, llvmType, operand, acc, maskOp.getMask())
1121 : lowerPredicatedReductionWithStartValue<
1122 LLVM::VPReduceFMaximumOp, ReductionNeutralFPNegInf>(
1123 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1125 case CombiningKind::MINIMUMF:
1128 ? lowerPredicatedReductionWithStartValue<
1129 LLVM::VPReduceFMinimumOp, ReductionNeutralFPLargestFinite>(
1130 rewriter, loc, llvmType, operand, acc, maskOp.getMask())
1131 : lowerPredicatedReductionWithStartValue<
1132 LLVM::VPReduceFMinimumOp, ReductionNeutralFPPosInf>(
1133 rewriter, loc, llvmType, operand, acc, maskOp.getMask());
1135 case CombiningKind::MAXIMUMNUMF:
1136 result = lowerMaskedReductionWithRegular<LLVM::vector_reduce_fmaximumnum,
1137 MaskNeutralFMaximumNum>(
1138 rewriter, loc, llvmType, operand, acc, maskOp.getMask(), fmf);
1140 case CombiningKind::MINIMUMNUMF:
1141 result = lowerMaskedReductionWithRegular<LLVM::vector_reduce_fminimumnum,
1142 MaskNeutralFMinimumNum>(
1143 rewriter, loc, llvmType, operand, acc, maskOp.getMask(), fmf);
1148 rewriter.replaceOp(maskOp,
result);
1153class VectorShuffleOpConversion
1156 using ConvertOpToLLVMPattern<vector::ShuffleOp>::ConvertOpToLLVMPattern;
1159 matchAndRewrite(vector::ShuffleOp shuffleOp, OpAdaptor adaptor,
1160 ConversionPatternRewriter &rewriter)
const override {
1161 auto loc = shuffleOp->getLoc();
1162 auto v1Type = shuffleOp.getV1VectorType();
1163 auto v2Type = shuffleOp.getV2VectorType();
1164 auto vectorType = shuffleOp.getResultVectorType();
1165 Type llvmType = typeConverter->convertType(vectorType);
1166 ArrayRef<int64_t> mask = shuffleOp.getMask();
1173 int64_t rank = vectorType.getRank();
1175 bool wellFormed0DCase =
1176 v1Type.getRank() == 0 && v2Type.getRank() == 0 && rank == 1;
1177 bool wellFormedNDCase =
1178 v1Type.getRank() == rank && v2Type.getRank() == rank;
1179 assert((wellFormed0DCase || wellFormedNDCase) &&
"op is not well-formed");
1184 if (rank <= 1 && v1Type == v2Type) {
1185 Value llvmShuffleOp = LLVM::ShuffleVectorOp::create(
1186 rewriter, loc, adaptor.getV1(), adaptor.getV2(),
1187 llvm::to_vector_of<int32_t>(mask));
1188 rewriter.replaceOp(shuffleOp, llvmShuffleOp);
1193 int64_t v1Dim = v1Type.getDimSize(0);
1195 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(llvmType))
1196 eltType = arrayType.getElementType();
1198 eltType = cast<VectorType>(llvmType).getElementType();
1199 Value insert = LLVM::PoisonOp::create(rewriter, loc, llvmType);
1201 for (int64_t extPos : mask) {
1203 if (extPos == vector::ShuffleOp::kPoisonIndex) {
1207 Value value = adaptor.getV1();
1208 if (extPos >= v1Dim) {
1210 value = adaptor.getV2();
1212 Value extract =
extractOne(rewriter, *getTypeConverter(), loc, value,
1213 eltType, rank, extPos);
1214 insert =
insertOne(rewriter, *getTypeConverter(), loc, insert, extract,
1215 llvmType, rank, insPos++);
1217 rewriter.replaceOp(shuffleOp, insert);
1222class VectorExtractOpConversion
1225 using ConvertOpToLLVMPattern<vector::ExtractOp>::ConvertOpToLLVMPattern;
1228 matchAndRewrite(vector::ExtractOp extractOp, OpAdaptor adaptor,
1229 ConversionPatternRewriter &rewriter)
const override {
1230 auto loc = extractOp->getLoc();
1231 auto resultType = extractOp.getResult().getType();
1232 auto llvmResultType = typeConverter->convertType(resultType);
1234 if (!llvmResultType)
1238 adaptor.getStaticPosition(), adaptor.getDynamicPosition(), rewriter);
1252 bool extractsAggregate = extractOp.getSourceVectorType().getRank() >= 2;
1256 bool extractsScalar =
static_cast<int64_t
>(positionVec.size()) ==
1257 extractOp.getSourceVectorType().getRank();
1261 if (extractOp.getSourceVectorType().getRank() == 0) {
1262 Type idxType = typeConverter->convertType(rewriter.getIndexType());
1263 positionVec.push_back(rewriter.getZeroAttr(idxType));
1266 Value extracted = adaptor.getSource();
1267 if (extractsAggregate) {
1268 ArrayRef<OpFoldResult> position(positionVec);
1269 if (extractsScalar) {
1273 position = position.drop_back();
1276 if (!llvm::all_of(position, llvm::IsaPred<Attribute>)) {
1279 extracted = LLVM::ExtractValueOp::create(rewriter, loc, extracted,
1283 if (extractsScalar) {
1284 extracted = LLVM::ExtractElementOp::create(
1285 rewriter, loc, extracted,
1289 rewriter.replaceOp(extractOp, extracted);
1310 using ConvertOpToLLVMPattern<vector::FMAOp>::ConvertOpToLLVMPattern;
1313 matchAndRewrite(vector::FMAOp fmaOp, OpAdaptor adaptor,
1314 ConversionPatternRewriter &rewriter)
const override {
1315 VectorType vType = fmaOp.getVectorType();
1316 if (vType.getRank() > 1)
1319 rewriter.replaceOpWithNewOp<LLVM::FMulAddOp>(
1320 fmaOp, adaptor.getLhs(), adaptor.getRhs(), adaptor.getAcc());
1325class VectorInsertOpConversion
1328 using ConvertOpToLLVMPattern<vector::InsertOp>::ConvertOpToLLVMPattern;
1331 matchAndRewrite(vector::InsertOp insertOp, OpAdaptor adaptor,
1332 ConversionPatternRewriter &rewriter)
const override {
1333 auto loc = insertOp->getLoc();
1334 auto destVectorType = insertOp.getDestVectorType();
1335 auto llvmResultType = typeConverter->convertType(destVectorType);
1337 if (!llvmResultType)
1341 adaptor.getStaticPosition(), adaptor.getDynamicPosition(), rewriter);
1363 bool isNestedAggregate = isa<LLVM::LLVMArrayType>(llvmResultType);
1365 bool insertIntoInnermostDim =
1366 static_cast<int64_t
>(positionVec.size()) == destVectorType.getRank();
1368 ArrayRef<OpFoldResult> positionOf1DVectorWithinAggregate(
1369 positionVec.begin(),
1370 insertIntoInnermostDim ? positionVec.size() - 1 : positionVec.size());
1371 OpFoldResult positionOfScalarWithin1DVector;
1372 if (destVectorType.getRank() == 0) {
1375 Type idxType = typeConverter->convertType(rewriter.getIndexType());
1376 positionOfScalarWithin1DVector = rewriter.getZeroAttr(idxType);
1377 }
else if (insertIntoInnermostDim) {
1378 positionOfScalarWithin1DVector = positionVec.back();
1384 Value sourceAggregate = adaptor.getValueToStore();
1385 if (insertIntoInnermostDim) {
1388 if (isNestedAggregate) {
1391 if (!llvm::all_of(positionOf1DVectorWithinAggregate,
1392 llvm::IsaPred<Attribute>)) {
1396 sourceAggregate = LLVM::ExtractValueOp::create(
1397 rewriter, loc, adaptor.getDest(),
1402 sourceAggregate = adaptor.getDest();
1405 sourceAggregate = LLVM::InsertElementOp::create(
1406 rewriter, loc, sourceAggregate.
getType(), sourceAggregate,
1407 adaptor.getValueToStore(),
1411 Value
result = sourceAggregate;
1412 if (isNestedAggregate) {
1413 if (!llvm::all_of(positionOf1DVectorWithinAggregate,
1414 llvm::IsaPred<Attribute>)) {
1418 result = LLVM::InsertValueOp::create(
1419 rewriter, loc, adaptor.getDest(), sourceAggregate,
1423 rewriter.replaceOp(insertOp,
result);
1429struct VectorScalableInsertOpLowering
1431 using ConvertOpToLLVMPattern<
1432 vector::ScalableInsertOp>::ConvertOpToLLVMPattern;
1435 matchAndRewrite(vector::ScalableInsertOp insOp, OpAdaptor adaptor,
1436 ConversionPatternRewriter &rewriter)
const override {
1437 rewriter.replaceOpWithNewOp<LLVM::vector_insert>(
1438 insOp, adaptor.getDest(), adaptor.getValueToStore(), adaptor.getPos());
1444struct VectorScalableExtractOpLowering
1446 using ConvertOpToLLVMPattern<
1447 vector::ScalableExtractOp>::ConvertOpToLLVMPattern;
1450 matchAndRewrite(vector::ScalableExtractOp extOp, OpAdaptor adaptor,
1451 ConversionPatternRewriter &rewriter)
const override {
1452 rewriter.replaceOpWithNewOp<LLVM::vector_extract>(
1453 extOp, typeConverter->convertType(extOp.getResultVectorType()),
1454 adaptor.getSource(), adaptor.getPos());
1487 setHasBoundedRewriteRecursion();
1490 LogicalResult matchAndRewrite(FMAOp op,
1491 PatternRewriter &rewriter)
const override {
1492 auto vType = op.getVectorType();
1493 if (vType.getRank() < 2)
1496 auto loc = op.getLoc();
1497 auto elemType = vType.getElementType();
1498 Value zero = arith::ConstantOp::create(rewriter, loc, elemType,
1500 Value desc = vector::BroadcastOp::create(rewriter, loc, vType, zero);
1501 for (int64_t i = 0, e = vType.getShape().front(); i != e; ++i) {
1502 Value extrLHS = ExtractOp::create(rewriter, loc, op.getLhs(), i);
1503 Value extrRHS = ExtractOp::create(rewriter, loc, op.getRhs(), i);
1504 Value extrACC = ExtractOp::create(rewriter, loc, op.getAcc(), i);
1505 Value fma = FMAOp::create(rewriter, loc, extrLHS, extrRHS, extrACC);
1506 desc = InsertOp::create(rewriter, loc, fma, desc, i);
1515static std::optional<SmallVector<int64_t, 4>>
1516computeContiguousStrides(MemRefType memRefType) {
1519 if (
failed(memRefType.getStridesAndOffset(strides, offset)))
1520 return std::nullopt;
1521 if (!strides.empty() && strides.back() != 1)
1522 return std::nullopt;
1524 if (memRefType.getLayout().isIdentity())
1531 auto sizes = memRefType.getShape();
1533 if (ShapedType::isDynamic(sizes[
index + 1]) ||
1534 ShapedType::isDynamic(strides[
index]) ||
1535 ShapedType::isDynamic(strides[
index + 1]))
1536 return std::nullopt;
1538 return std::nullopt;
1543class VectorTypeCastOpConversion
1546 using ConvertOpToLLVMPattern<vector::TypeCastOp>::ConvertOpToLLVMPattern;
1549 matchAndRewrite(vector::TypeCastOp castOp, OpAdaptor adaptor,
1550 ConversionPatternRewriter &rewriter)
const override {
1551 auto loc = castOp->getLoc();
1552 MemRefType sourceMemRefType =
1553 cast<MemRefType>(castOp.getOperand().getType());
1554 MemRefType targetMemRefType = castOp.getType();
1557 if (!sourceMemRefType.hasStaticShape() ||
1558 !targetMemRefType.hasStaticShape())
1561 auto llvmSourceDescriptorTy =
1562 dyn_cast<LLVM::LLVMStructType>(adaptor.getOperands()[0].getType());
1563 if (!llvmSourceDescriptorTy)
1565 MemRefDescriptor sourceMemRef(adaptor.getOperands()[0]);
1567 auto llvmTargetDescriptorTy = dyn_cast_or_null<LLVM::LLVMStructType>(
1568 typeConverter->convertType(targetMemRefType));
1569 if (!llvmTargetDescriptorTy)
1573 auto sourceStrides = computeContiguousStrides(sourceMemRefType);
1576 auto targetStrides = computeContiguousStrides(targetMemRefType);
1580 if (llvm::any_of(*targetStrides, ShapedType::isDynamic))
1585 Type indexTy = getTypeConverter()->getIndexType();
1588 auto desc = MemRefDescriptor::poison(rewriter, loc, llvmTargetDescriptorTy);
1590 Value allocated = sourceMemRef.allocatedPtr(rewriter, loc);
1591 desc.setAllocatedPtr(rewriter, loc, allocated);
1594 Value ptr = sourceMemRef.alignedPtr(rewriter, loc);
1595 desc.setAlignedPtr(rewriter, loc, ptr);
1597 desc.setOffset(rewriter, loc,
1601 for (
const auto &indexedSize :
1602 llvm::enumerate(targetMemRefType.getShape())) {
1603 int64_t index = indexedSize.index();
1604 desc.setSize(rewriter, loc, index,
1606 indexedSize.value()));
1607 desc.setStride(rewriter, loc, index,
1609 (*targetStrides)[index]));
1612 rewriter.replaceOp(castOp, {desc});
1619class VectorCreateMaskOpConversion
1620 :
public OpConversionPattern<vector::CreateMaskOp> {
1622 explicit VectorCreateMaskOpConversion(MLIRContext *context,
1623 bool enableIndexOpt)
1624 : OpConversionPattern<vector::CreateMaskOp>(context),
1625 force32BitVectorIndices(enableIndexOpt) {}
1628 matchAndRewrite(vector::CreateMaskOp op, OpAdaptor adaptor,
1629 ConversionPatternRewriter &rewriter)
const override {
1630 auto dstType = op.getType();
1631 if (dstType.getRank() != 1 || !cast<VectorType>(dstType).isScalable())
1633 IntegerType idxType =
1634 force32BitVectorIndices ? rewriter.getI32Type() : rewriter.getI64Type();
1635 auto loc = op->getLoc();
1636 Value
indices = LLVM::StepVectorOp::create(
1640 Value maskBound = adaptor.getOperands()[0];
1647 if (force32BitVectorIndices) {
1650 maskBound = arith::MinSIOp::create(rewriter, loc, maskBound, maxBound);
1654 Value bounds = BroadcastOp::create(rewriter, loc,
indices.getType(), bound);
1655 Value comp = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::slt,
1657 rewriter.replaceOp(op, comp);
1662 const bool force32BitVectorIndices;
1666 SymbolTableCollection *symbolTables =
nullptr;
1669 explicit VectorPrintOpConversion(
1670 const LLVMTypeConverter &typeConverter,
1671 SymbolTableCollection *symbolTables =
nullptr)
1672 : ConvertOpToLLVMPattern<vector::PrintOp>(typeConverter),
1673 symbolTables(symbolTables) {}
1689 matchAndRewrite(vector::PrintOp
printOp, OpAdaptor adaptor,
1690 ConversionPatternRewriter &rewriter)
const override {
1691 auto parent =
printOp->getParentOfType<ModuleOp>();
1697 if (
auto value = adaptor.getSource()) {
1699 if (isa<VectorType>(printType)) {
1703 if (
failed(emitScalarPrint(rewriter, parent, loc, printType, value)))
1707 auto punct =
printOp.getPunctuation();
1708 if (
auto stringLiteral =
printOp.getStringLiteral()) {
1711 *stringLiteral, *getTypeConverter(),
1713 if (createResult.failed())
1716 }
else if (punct != PrintPunctuation::NoPunctuation) {
1717 FailureOr<LLVM::LLVMFuncOp> op = [&]() {
1719 case PrintPunctuation::Close:
1722 case PrintPunctuation::Open:
1725 case PrintPunctuation::Comma:
1728 case PrintPunctuation::NewLine:
1732 llvm_unreachable(
"unexpected punctuation");
1737 emitCall(rewriter,
printOp->getLoc(), op.value());
1745 enum class PrintConversion {
1754 LogicalResult emitScalarPrint(ConversionPatternRewriter &rewriter,
1755 ModuleOp parent, Location loc, Type printType,
1756 Value value)
const {
1757 if (typeConverter->convertType(printType) ==
nullptr)
1761 PrintConversion conversion = PrintConversion::None;
1762 FailureOr<Operation *> printer;
1768 conversion = PrintConversion::Bitcast16;
1771 conversion = PrintConversion::Bitcast16;
1775 }
else if (
auto intTy = dyn_cast<IntegerType>(printType)) {
1779 unsigned width = intTy.getWidth();
1780 if (intTy.isUnsigned()) {
1783 conversion = PrintConversion::ZeroExt64;
1790 assert(intTy.isSignless() || intTy.isSigned());
1795 conversion = PrintConversion::ZeroExt64;
1796 else if (width < 64)
1797 conversion = PrintConversion::SignExt64;
1804 }
else if (
auto floatTy = dyn_cast<FloatType>(printType)) {
1807 llvm::APFloatBase::SemanticsToEnum(floatTy.getFloatSemantics());
1808 Value semValue = LLVM::ConstantOp::create(
1809 rewriter, loc, rewriter.getI32Type(),
1810 rewriter.getIntegerAttr(rewriter.getI32Type(), sem));
1812 LLVM::ZExtOp::create(rewriter, loc, rewriter.getI64Type(), value);
1815 emitCall(rewriter, loc, printer.value(),
1824 switch (conversion) {
1825 case PrintConversion::ZeroExt64:
1826 value = arith::ExtUIOp::create(
1827 rewriter, loc, IntegerType::get(rewriter.getContext(), 64), value);
1829 case PrintConversion::SignExt64:
1830 value = arith::ExtSIOp::create(
1831 rewriter, loc, IntegerType::get(rewriter.getContext(), 64), value);
1833 case PrintConversion::Bitcast16:
1834 value = LLVM::BitcastOp::create(
1835 rewriter, loc, IntegerType::get(rewriter.getContext(), 16), value);
1837 case PrintConversion::None:
1840 emitCall(rewriter, loc, printer.value(), value);
1845 static void emitCall(ConversionPatternRewriter &rewriter, Location loc,
1847 LLVM::CallOp::create(rewriter, loc,
TypeRange(), SymbolRefAttr::get(ref),
1855struct VectorBroadcastScalarToLowRankLowering
1857 using ConvertOpToLLVMPattern<vector::BroadcastOp>::ConvertOpToLLVMPattern;
1860 matchAndRewrite(vector::BroadcastOp
broadcast, OpAdaptor adaptor,
1861 ConversionPatternRewriter &rewriter)
const override {
1862 if (isa<VectorType>(
broadcast.getSourceType()))
1863 return rewriter.notifyMatchFailure(
1864 broadcast,
"broadcast from vector type not handled");
1867 if (resultType.getRank() > 1)
1868 return rewriter.notifyMatchFailure(
broadcast,
1869 "broadcast to 2+-d handled elsewhere");
1875 auto zero = LLVM::ConstantOp::create(
1877 typeConverter->convertType(rewriter.getIntegerType(32)),
1878 rewriter.getZeroAttr(rewriter.getIntegerType(32)));
1881 if (resultType.getRank() == 0) {
1882 rewriter.replaceOpWithNewOp<LLVM::InsertElementOp>(
1883 broadcast, vectorType, poison, adaptor.getSource(), zero);
1888 LLVM::InsertElementOp::create(rewriter,
broadcast.
getLoc(), vectorType,
1889 poison, adaptor.getSource(), zero);
1893 SmallVector<int32_t> zeroValues(width, 0);
1896 auto shuffle = rewriter.createOrFold<LLVM::ShuffleVectorOp>(
1907struct VectorBroadcastScalarToNdLowering
1909 using ConvertOpToLLVMPattern<BroadcastOp>::ConvertOpToLLVMPattern;
1912 matchAndRewrite(BroadcastOp
broadcast, OpAdaptor adaptor,
1913 ConversionPatternRewriter &rewriter)
const override {
1914 if (isa<VectorType>(
broadcast.getSourceType()))
1915 return rewriter.notifyMatchFailure(
1916 broadcast,
"broadcast from vector type not handled");
1919 if (resultType.getRank() <= 1)
1920 return rewriter.notifyMatchFailure(
1921 broadcast,
"broadcast to 1-d or 0-d handled elsewhere");
1925 auto vectorTypeInfo =
1927 auto llvmNDVectorTy = vectorTypeInfo.llvmNDVectorTy;
1928 auto llvm1DVectorTy = vectorTypeInfo.llvm1DVectorTy;
1929 if (!llvmNDVectorTy || !llvm1DVectorTy)
1933 Value desc = LLVM::PoisonOp::create(rewriter, loc, llvmNDVectorTy);
1937 Value vdesc = LLVM::PoisonOp::create(rewriter, loc, llvm1DVectorTy);
1938 auto zero = LLVM::ConstantOp::create(
1939 rewriter, loc, typeConverter->convertType(rewriter.getIntegerType(32)),
1940 rewriter.getZeroAttr(rewriter.getIntegerType(32)));
1941 Value v = LLVM::InsertElementOp::create(rewriter, loc, llvm1DVectorTy,
1942 vdesc, adaptor.getSource(), zero);
1945 int64_t width = resultType.getDimSize(resultType.getRank() - 1);
1946 SmallVector<int32_t> zeroValues(width, 0);
1947 v = LLVM::ShuffleVectorOp::create(rewriter, loc, v, v, zeroValues);
1951 nDVectorIterate(vectorTypeInfo, rewriter, [&](ArrayRef<int64_t> position) {
1952 desc = LLVM::InsertValueOp::create(rewriter, loc, desc, v, position);
1961struct VectorInterleaveOpLowering
1966 matchAndRewrite(vector::InterleaveOp interleaveOp, OpAdaptor adaptor,
1967 ConversionPatternRewriter &rewriter)
const override {
1968 VectorType resultType = interleaveOp.getResultVectorType();
1970 if (resultType.getRank() != 1)
1971 return rewriter.notifyMatchFailure(interleaveOp,
1972 "InterleaveOp not rank 1");
1974 if (resultType.isScalable()) {
1975 rewriter.replaceOpWithNewOp<LLVM::vector_interleave2>(
1976 interleaveOp, typeConverter->convertType(resultType),
1977 adaptor.getLhs(), adaptor.getRhs());
1984 int64_t resultVectorSize = resultType.getNumElements();
1985 SmallVector<int32_t> interleaveShuffleMask;
1986 interleaveShuffleMask.reserve(resultVectorSize);
1987 for (
int i = 0, end = resultVectorSize / 2; i < end; ++i) {
1988 interleaveShuffleMask.push_back(i);
1989 interleaveShuffleMask.push_back((resultVectorSize / 2) + i);
1991 rewriter.replaceOpWithNewOp<LLVM::ShuffleVectorOp>(
1992 interleaveOp, adaptor.getLhs(), adaptor.getRhs(),
1993 interleaveShuffleMask);
2000struct VectorDeinterleaveOpLowering
2005 matchAndRewrite(vector::DeinterleaveOp deinterleaveOp, OpAdaptor adaptor,
2006 ConversionPatternRewriter &rewriter)
const override {
2007 VectorType resultType = deinterleaveOp.getResultVectorType();
2008 VectorType sourceType = deinterleaveOp.getSourceVectorType();
2009 auto loc = deinterleaveOp.getLoc();
2013 if (resultType.getRank() != 1)
2014 return rewriter.notifyMatchFailure(deinterleaveOp,
2015 "DeinterleaveOp not rank 1");
2017 if (resultType.isScalable()) {
2018 const auto *llvmTypeConverter = this->getTypeConverter();
2019 auto deinterleaveResults = deinterleaveOp.getResultTypes();
2020 auto packedOpResults =
2021 llvmTypeConverter->packOperationResults(deinterleaveResults);
2022 auto intrinsic = LLVM::vector_deinterleave2::create(
2023 rewriter, loc, packedOpResults, adaptor.getSource());
2025 auto evenResult = LLVM::ExtractValueOp::create(
2026 rewriter, loc, intrinsic->getResult(0), 0);
2027 auto oddResult = LLVM::ExtractValueOp::create(rewriter, loc,
2028 intrinsic->getResult(0), 1);
2030 rewriter.replaceOp(deinterleaveOp,
ValueRange{evenResult, oddResult});
2037 int64_t resultVectorSize = resultType.getNumElements();
2038 SmallVector<int32_t> evenShuffleMask;
2039 SmallVector<int32_t> oddShuffleMask;
2041 evenShuffleMask.reserve(resultVectorSize);
2042 oddShuffleMask.reserve(resultVectorSize);
2044 for (
int i = 0; i < sourceType.getNumElements(); ++i) {
2046 evenShuffleMask.push_back(i);
2048 oddShuffleMask.push_back(i);
2051 auto poison = LLVM::PoisonOp::create(rewriter, loc, sourceType);
2052 auto evenShuffle = LLVM::ShuffleVectorOp::create(
2053 rewriter, loc, adaptor.getSource(), poison, evenShuffleMask);
2054 auto oddShuffle = LLVM::ShuffleVectorOp::create(
2055 rewriter, loc, adaptor.getSource(), poison, oddShuffleMask);
2057 rewriter.replaceOp(deinterleaveOp,
ValueRange{evenShuffle, oddShuffle});
2063struct VectorFromElementsLowering
2068 matchAndRewrite(vector::FromElementsOp fromElementsOp, OpAdaptor adaptor,
2069 ConversionPatternRewriter &rewriter)
const override {
2070 Location loc = fromElementsOp.getLoc();
2071 VectorType vectorType = fromElementsOp.getType();
2075 if (vectorType.getRank() > 1)
2076 return rewriter.notifyMatchFailure(fromElementsOp,
2077 "rank > 1 vectors are not supported");
2078 Type llvmType = typeConverter->convertType(vectorType);
2079 Type llvmIndexType = typeConverter->convertType(rewriter.getIndexType());
2080 Value
result = LLVM::PoisonOp::create(rewriter, loc, llvmType);
2081 for (
auto [idx, val] : llvm::enumerate(adaptor.getElements())) {
2083 LLVM::ConstantOp::create(rewriter, loc, llvmIndexType, idx);
2084 result = LLVM::InsertElementOp::create(rewriter, loc, llvmType,
result,
2087 rewriter.replaceOp(fromElementsOp,
result);
2093struct VectorToElementsLowering
2098 matchAndRewrite(vector::ToElementsOp toElementsOp, OpAdaptor adaptor,
2099 ConversionPatternRewriter &rewriter)
const override {
2100 Location loc = toElementsOp.getLoc();
2101 auto idxType = typeConverter->convertType(rewriter.getIndexType());
2102 Value source = adaptor.getSource();
2104 SmallVector<Value> results(toElementsOp->getNumResults());
2105 for (
auto [idx, element] : llvm::enumerate(toElementsOp.getElements())) {
2107 if (element.use_empty())
2110 auto constIdx = LLVM::ConstantOp::create(
2111 rewriter, loc, idxType, rewriter.getIntegerAttr(idxType, idx));
2112 auto llvmType = typeConverter->convertType(element.getType());
2114 Value
result = LLVM::ExtractElementOp::create(rewriter, loc, llvmType,
2119 rewriter.replaceOp(toElementsOp, results);
2129 matchAndRewrite(vector::StepOp stepOp, OpAdaptor adaptor,
2130 ConversionPatternRewriter &rewriter)
const override {
2131 Type llvmType = typeConverter->convertType(stepOp.getType());
2132 rewriter.replaceOpWithNewOp<LLVM::StepVectorOp>(stepOp, llvmType);
2147class ContractionOpToMatmulOpLowering
2150 using MaskableOpRewritePattern::MaskableOpRewritePattern;
2152 ContractionOpToMatmulOpLowering(MLIRContext *context,
2153 PatternBenefit benefit = 100)
2154 : MaskableOpRewritePattern<vector::ContractionOp>(context, benefit) {}
2157 matchAndRewriteMaskableOp(vector::ContractionOp op, MaskingOpInterface maskOp,
2158 PatternRewriter &rewriter)
const override;
2178FailureOr<Value> ContractionOpToMatmulOpLowering::matchAndRewriteMaskableOp(
2179 vector::ContractionOp op, MaskingOpInterface maskOp,
2185 auto iteratorTypes = op.getIteratorTypes().getValue();
2191 Type opResType = op.getType();
2192 VectorType vecType = dyn_cast<VectorType>(opResType);
2193 if (vecType && vecType.isScalable())
2197 if (op.getLhsType().isScalable() || op.getRhsType().isScalable())
2200 Type elementType = op.getLhsType().getElementType();
2204 Type dstElementType = vecType ? vecType.getElementType() : opResType;
2205 if (elementType != dstElementType)
2210 MLIRContext *ctx = op.getContext();
2211 Location loc = op.getLoc();
2215 Value
lhs = op.getLhs();
2216 auto lhsMap = op.getIndexingMapsArray()[0];
2218 lhs = vector::TransposeOp::create(rew, loc,
lhs, ArrayRef<int64_t>{1, 0});
2223 Value
rhs = op.getRhs();
2224 auto rhsMap = op.getIndexingMapsArray()[1];
2226 rhs = vector::TransposeOp::create(rew, loc,
rhs, ArrayRef<int64_t>{1, 0});
2231 VectorType lhsType = cast<VectorType>(
lhs.getType());
2232 VectorType rhsType = cast<VectorType>(
rhs.getType());
2233 int64_t lhsRows = lhsType.getDimSize(0);
2234 int64_t lhsColumns = lhsType.getDimSize(1);
2235 int64_t rhsColumns = rhsType.getDimSize(1);
2237 Type flattenedLHSType =
2238 VectorType::get(lhsType.getNumElements(), lhsType.getElementType());
2239 lhs = vector::ShapeCastOp::create(rew, loc, flattenedLHSType,
lhs);
2241 Type flattenedRHSType =
2242 VectorType::get(rhsType.getNumElements(), rhsType.getElementType());
2243 rhs = vector::ShapeCastOp::create(rew, loc, flattenedRHSType,
rhs);
2245 Value
mul = LLVM::MatrixMultiplyOp::create(
2247 VectorType::get(lhsRows * rhsColumns,
2248 cast<VectorType>(
lhs.getType()).getElementType()),
2249 lhs,
rhs, lhsRows, lhsColumns, rhsColumns);
2251 mul = vector::ShapeCastOp::create(
2253 VectorType::get({lhsRows, rhsColumns},
2258 auto accMap = op.getIndexingMapsArray()[2];
2260 mul = vector::TransposeOp::create(rew, loc,
mul, ArrayRef<int64_t>{1, 0});
2262 llvm_unreachable(
"invalid contraction semantics");
2264 Value res = isa<IntegerType>(elementType)
2265 ?
static_cast<Value
>(
2266 arith::AddIOp::create(rew, loc, op.getAcc(),
mul))
2267 : static_cast<Value>(
2268 arith::AddFOp::create(rew, loc, op.getAcc(),
mul));
2286class TransposeOpToMatrixTransposeOpLowering
2287 :
public OpRewritePattern<vector::TransposeOp> {
2291 LogicalResult matchAndRewrite(vector::TransposeOp op,
2292 PatternRewriter &rewriter)
const override {
2293 auto loc = op.getLoc();
2295 Value input = op.getVector();
2296 VectorType inputType = op.getSourceVectorType();
2297 VectorType resType = op.getResultVectorType();
2299 if (inputType.isScalable())
2301 op,
"This lowering does not support scalable vectors");
2304 ArrayRef<int64_t> transp = op.getPermutation();
2306 if (resType.getRank() != 2 || transp[0] != 1 || transp[1] != 0) {
2310 Type flattenedType =
2311 VectorType::get(resType.getNumElements(), resType.getElementType());
2313 vector::ShapeCastOp::create(rewriter, loc, flattenedType, input);
2316 Value trans = LLVM::MatrixTransposeOp::create(rewriter, loc, flattenedType,
2317 matrix, rows, columns);
2327 patterns.
add<VectorFMAOpNDRewritePattern>(patterns.
getContext());
2332 patterns.
add<ContractionOpToMatmulOpLowering>(patterns.
getContext(), benefit);
2337 patterns.
add<TransposeOpToMatrixTransposeOpLowering>(patterns.
getContext(),
2344 bool reassociateFPReductions,
bool force32BitVectorIndices,
2345 bool useVectorAlignment,
bool enableGEPInboundsNuw) {
2348 patterns.
add<VectorReductionOpConversion>(converter, reassociateFPReductions);
2349 patterns.
add<VectorCreateMaskOpConversion>(ctx, force32BitVectorIndices);
2350 patterns.
add<VectorLoadStoreConversion<vector::LoadOp>,
2351 VectorLoadStoreConversion<vector::MaskedLoadOp>,
2352 VectorLoadStoreConversion<vector::StoreOp>,
2353 VectorLoadStoreConversion<vector::MaskedStoreOp>>(
2354 converter, useVectorAlignment, enableGEPInboundsNuw);
2355 patterns.
add<VectorGatherOpConversion, VectorScatterOpConversion>(
2356 converter, useVectorAlignment);
2357 patterns.
add<VectorBitCastOpConversion, VectorShuffleOpConversion,
2358 VectorExtractOpConversion, VectorFMAOp1DConversion,
2359 VectorInsertOpConversion, VectorPrintOpConversion,
2360 VectorTypeCastOpConversion, VectorScaleOpConversion,
2361 VectorExpandLoadOpConversion, VectorCompressStoreOpConversion,
2362 VectorBroadcastScalarToLowRankLowering,
2363 VectorBroadcastScalarToNdLowering,
2364 VectorScalableInsertOpLowering, VectorScalableExtractOpLowering,
2365 MaskedReductionOpConversion, VectorInterleaveOpLowering,
2366 VectorDeinterleaveOpLowering, VectorFromElementsLowering,
2367 VectorToElementsLowering, VectorStepOpLowering>(converter);
2371struct VectorToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
2372 VectorToLLVMDialectInterface(
Dialect *dialect)
2373 : ConvertToLLVMPatternInterface(dialect) {}
2375 using ConvertToLLVMPatternInterface::ConvertToLLVMPatternInterface;
2376 void loadDependentDialects(MLIRContext *context)
const final {
2377 context->loadDialect<LLVM::LLVMDialect>();
2382 void populateConvertToLLVMConversionPatterns(
2383 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
2384 RewritePatternSet &patterns)
const final {
2393 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.
Value createIndexAttrConstant(OpBuilder &builder, Location loc, Type resultType, int64_t value)
Creates an llvm.mlir.constant producing value as resultType, which is expected to be the converted in...
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, arith::FastMathFlagsAttr fastmath=nullptr)
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.
@ None
An explicit data construct.
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.