22#include "llvm/ADT/ArrayRef.h"
29static FailureOr<Attribute>
33 if (
auto dstElementsAttr = dyn_cast<DenseElementsAttr>(value)) {
34 if (resType.isScalable() && !isa<SplatElementsAttr>(value))
35 return rewriter.notifyMatchFailure(
37 "Cannot linearize a constant scalable vector that's not a splat");
39 return dstElementsAttr.reshape(resType);
42 if (
auto poisonAttr = dyn_cast<ub::PoisonAttr>(value))
45 return rewriter.notifyMatchFailure(loc,
"unsupported attr type");
50struct LinearizeConstantLike final
51 : OpTraitConversionPattern<OpTrait::ConstantLike> {
52 using OpTraitConversionPattern::OpTraitConversionPattern;
54 LinearizeConstantLike(
const TypeConverter &typeConverter,
55 MLIRContext *context, PatternBenefit benefit = 1)
56 : OpTraitConversionPattern(typeConverter, context, benefit) {}
58 matchAndRewrite(Operation *op, ArrayRef<Value> operands,
59 ConversionPatternRewriter &rewriter)
const override {
60 Location loc = op->
getLoc();
62 return rewriter.notifyMatchFailure(loc,
"expected 1 result");
64 const TypeConverter &typeConverter = *getTypeConverter();
67 assert(resType &&
"expected 1-D vector type");
69 StringAttr attrName = rewriter.getStringAttr(
"value");
70 Attribute value = op->
getAttr(attrName);
72 return rewriter.notifyMatchFailure(loc,
"no 'value' attr");
74 FailureOr<Attribute> newValue =
79 FailureOr<Operation *> convertResult =
80 convertOpResultTypes(op, {}, typeConverter, rewriter);
84 Operation *newOp = *convertResult;
85 newOp->
setAttr(attrName, *newValue);
86 rewriter.replaceOp(op, newOp);
91struct LinearizeVectorizable final
92 : OpTraitConversionPattern<OpTrait::Vectorizable> {
93 using OpTraitConversionPattern::OpTraitConversionPattern;
96 LinearizeVectorizable(
const TypeConverter &typeConverter,
97 MLIRContext *context, PatternBenefit benefit = 1)
98 : OpTraitConversionPattern(typeConverter, context, benefit) {}
100 matchAndRewrite(Operation *op, ArrayRef<Value> operands,
101 ConversionPatternRewriter &rewriter)
const override {
102 FailureOr<Operation *> newOp =
103 convertOpResultTypes(op, operands, *getTypeConverter(), rewriter);
107 rewriter.replaceOp(op, (*newOp)->getResults());
112template <
typename TOp>
113static bool stridesAllOne(TOp op) {
115 std::is_same_v<TOp, vector::ExtractStridedSliceOp> ||
116 std::is_same_v<TOp, vector::InsertStridedSliceOp>,
117 "expected vector.extract_strided_slice or vector.insert_strided_slice");
123static FailureOr<SmallVector<int64_t>> intsFromArrayAttr(
ArrayAttr attrs) {
127 ints.reserve(attrs.size());
128 for (
auto attr : attrs) {
129 if (
auto intAttr = dyn_cast<IntegerAttr>(attr)) {
130 ints.push_back(intAttr.getInt());
158 assert((large.size() >= small.size()) &&
159 "rank of 'large' cannot be lower than rank of 'small'");
160 assert((large.size() >= offsets.size()) &&
161 "rank of 'large' cannot be lower than the number of offsets");
162 unsigned delta = large.size() - small.size();
163 unsigned nOffsets = offsets.size();
165 return i >= delta ? small[i - delta] : 1;
168 return i < nOffsets ? offsets[i] : 0;
176 for (
int i = large.size() - 1; i >= 0; --i) {
178 int64_t smallSize = getSmall(i);
179 int64_t nextSize = currentSize * smallSize;
181 int64_t *base = nextIndices.begin();
182 int64_t offset = getOffset(i) * stride;
183 for (
int j = 0;
j < smallSize; ++
j) {
184 for (
int k = 0; k < currentSize; ++k) {
191 indices = std::move(nextIndices);
215struct LinearizeVectorExtractStridedSlice final
216 :
public mlir::OpConversionPattern<mlir::vector::ExtractStridedSliceOp> {
218 LinearizeVectorExtractStridedSlice(
const TypeConverter &typeConverter,
219 MLIRContext *context,
220 PatternBenefit benefit = 1)
221 : OpConversionPattern(typeConverter, context, benefit) {}
224 matchAndRewrite(vector::ExtractStridedSliceOp extractStridedSliceOp,
226 ConversionPatternRewriter &rewriter)
const override {
228 VectorType flatOutputType = getTypeConverter()->convertType<VectorType>(
229 extractStridedSliceOp.getType());
230 assert(flatOutputType &&
"vector type expected");
234 if (!stridesAllOne(extractStridedSliceOp)) {
235 return rewriter.notifyMatchFailure(
236 extractStridedSliceOp,
237 "extract_strided_slice with strides != 1 not supported");
240 FailureOr<SmallVector<int64_t>> offsets =
241 intsFromArrayAttr(extractStridedSliceOp.getOffsets());
243 return rewriter.notifyMatchFailure(extractStridedSliceOp,
244 "failed to get integer offsets");
247 ArrayRef<int64_t> inputShape =
248 extractStridedSliceOp.getSourceVectorType().getShape();
250 ArrayRef<int64_t> outputShape = extractStridedSliceOp.getType().getShape();
252 SmallVector<int64_t>
indices = getStridedSliceInsertionIndices(
253 outputShape, inputShape, offsets.value());
255 Value srcVector = adaptor.getSource();
256 rewriter.replaceOpWithNewOp<vector::ShuffleOp>(
257 extractStridedSliceOp, flatOutputType, srcVector, srcVector,
indices);
286struct LinearizeVectorInsertStridedSlice final
287 :
public mlir::OpConversionPattern<mlir::vector::InsertStridedSliceOp> {
289 LinearizeVectorInsertStridedSlice(
const TypeConverter &typeConverter,
290 MLIRContext *context,
291 PatternBenefit benefit = 1)
292 : OpConversionPattern(typeConverter, context, benefit) {}
295 matchAndRewrite(vector::InsertStridedSliceOp insertStridedSliceOp,
297 ConversionPatternRewriter &rewriter)
const override {
301 if (!stridesAllOne(insertStridedSliceOp)) {
302 return rewriter.notifyMatchFailure(
303 insertStridedSliceOp,
304 "insert_strided_slice with strides != 1 not supported");
307 VectorType inputType = insertStridedSliceOp.getValueToStore().getType();
308 ArrayRef<int64_t> inputShape = inputType.getShape();
310 VectorType outputType = insertStridedSliceOp.getType();
311 ArrayRef<int64_t> outputShape = outputType.getShape();
312 int64_t nOutputElements = outputType.getNumElements();
314 FailureOr<SmallVector<int64_t>> offsets =
315 intsFromArrayAttr(insertStridedSliceOp.getOffsets());
317 return rewriter.notifyMatchFailure(insertStridedSliceOp,
318 "failed to get integer offsets");
320 SmallVector<int64_t> sliceIndices = getStridedSliceInsertionIndices(
321 inputShape, outputShape, offsets.value());
323 SmallVector<int64_t>
indices(nOutputElements);
325 for (
auto [index, sliceIndex] : llvm::enumerate(sliceIndices)) {
326 indices[sliceIndex] = index + nOutputElements;
329 Value flatToStore = adaptor.getValueToStore();
330 Value flatDest = adaptor.getDest();
331 rewriter.replaceOpWithNewOp<vector::ShuffleOp>(insertStridedSliceOp,
349struct LinearizeVectorShuffle final
350 :
public OpConversionPattern<vector::ShuffleOp> {
352 LinearizeVectorShuffle(
const TypeConverter &typeConverter,
353 MLIRContext *context, PatternBenefit benefit = 1)
354 : OpConversionPattern(typeConverter, context, benefit) {}
357 matchAndRewrite(vector::ShuffleOp shuffleOp, OpAdaptor adaptor,
358 ConversionPatternRewriter &rewriter)
const override {
360 getTypeConverter()->convertType<VectorType>(shuffleOp.getType());
361 assert(dstType &&
"vector type destination expected.");
363 Value vec1 = adaptor.getV1();
364 Value vec2 = adaptor.getV2();
365 int shuffleSliceLen = 1;
366 int rank = shuffleOp.getV1().getType().getRank();
373 llvm::ArrayRef<int64_t> shape = shuffleOp.getV1().getType().getShape();
374 for (
unsigned i = 1; i < shape.size(); ++i) {
375 shuffleSliceLen *= shape[i];
383 ArrayRef<int64_t> mask = shuffleOp.getMask();
384 int64_t totalSizeOfShuffledElmnts = mask.size() * shuffleSliceLen;
385 llvm::SmallVector<int64_t, 2>
indices(totalSizeOfShuffledElmnts);
386 for (
auto [i, value] : llvm::enumerate(mask)) {
387 std::iota(
indices.begin() + shuffleSliceLen * i,
388 indices.begin() + shuffleSliceLen * (i + 1),
389 shuffleSliceLen * value);
392 rewriter.replaceOpWithNewOp<vector::ShuffleOp>(shuffleOp, dstType, vec1,
424struct LinearizeVectorExtract final
425 :
public OpConversionPattern<vector::ExtractOp> {
427 LinearizeVectorExtract(
const TypeConverter &typeConverter,
428 MLIRContext *context, PatternBenefit benefit = 1)
429 : OpConversionPattern(typeConverter, context, benefit) {}
431 matchAndRewrite(vector::ExtractOp extractOp, OpAdaptor adaptor,
432 ConversionPatternRewriter &rewriter)
const override {
433 Type dstTy = getTypeConverter()->convertType(extractOp.getType());
434 assert(dstTy &&
"expected 1-D vector type");
437 if (extractOp.hasDynamicPosition())
438 return rewriter.notifyMatchFailure(extractOp,
439 "dynamic position is not supported.");
441 llvm::ArrayRef<int64_t> shape = extractOp.getSource().getType().getShape();
442 int64_t size = extractOp.getSource().getType().getNumElements();
445 int64_t linearizedOffset = 0;
446 llvm::ArrayRef<int64_t> offsets = extractOp.getStaticPosition();
447 for (
auto [i, off] : llvm::enumerate(offsets)) {
449 linearizedOffset += offsets[i] * size;
452 Value srcVector = adaptor.getSource();
453 if (!isa<VectorType>(extractOp.getType())) {
455 Value
result = rewriter.createOrFold<vector::ExtractOp>(
456 extractOp.getLoc(), srcVector, linearizedOffset);
457 rewriter.replaceOp(extractOp,
result);
463 llvm::SmallVector<int64_t, 2>
indices(size);
465 rewriter.replaceOpWithNewOp<vector::ShuffleOp>(extractOp, dstTy, srcVector,
502struct LinearizeVectorInsert final
503 :
public OpConversionPattern<vector::InsertOp> {
505 LinearizeVectorInsert(
const TypeConverter &typeConverter,
506 MLIRContext *context, PatternBenefit benefit = 1)
507 : OpConversionPattern(typeConverter, context, benefit) {}
509 matchAndRewrite(vector::InsertOp insertOp, OpAdaptor adaptor,
510 ConversionPatternRewriter &rewriter)
const override {
511 VectorType dstTy = getTypeConverter()->convertType<VectorType>(
512 insertOp.getDestVectorType());
513 assert(dstTy &&
"vector type destination expected.");
516 if (insertOp.hasDynamicPosition())
517 return rewriter.notifyMatchFailure(insertOp,
518 "dynamic position is not supported.");
519 auto srcTy = insertOp.getValueToStoreType();
520 auto srcAsVec = dyn_cast<VectorType>(srcTy);
521 uint64_t srcSize = srcAsVec ? srcAsVec.getNumElements() : 1;
523 auto dstShape = insertOp.getDestVectorType().getShape();
524 const auto dstSize = insertOp.getDestVectorType().getNumElements();
525 auto dstSizeForOffsets = dstSize;
528 int64_t linearizedOffset = 0;
529 auto offsetsNd = insertOp.getStaticPosition();
530 for (
auto [dim, offset] : llvm::enumerate(offsetsNd)) {
531 dstSizeForOffsets /= dstShape[dim];
532 linearizedOffset += offset * dstSizeForOffsets;
535 Location loc = insertOp.getLoc();
536 Value valueToStore = adaptor.getValueToStore();
538 if (!isa<VectorType>(valueToStore.
getType())) {
540 Value
result = rewriter.createOrFold<vector::InsertOp>(
541 loc, valueToStore, adaptor.getDest(), linearizedOffset);
542 rewriter.replaceOp(insertOp,
result);
547 llvm::SmallVector<int64_t, 2>
indices(dstSize);
548 auto *origValsUntil =
indices.begin();
549 std::advance(origValsUntil, linearizedOffset);
552 std::iota(
indices.begin(), origValsUntil, 0);
553 auto *newValsUntil = origValsUntil;
554 std::advance(newValsUntil, srcSize);
556 std::iota(origValsUntil, newValsUntil, dstSize);
558 std::iota(newValsUntil,
indices.end(), linearizedOffset + srcSize);
560 Value
result = rewriter.createOrFold<vector::ShuffleOp>(
561 loc, dstTy, adaptor.getDest(), valueToStore,
indices);
563 rewriter.replaceOp(insertOp,
result);
576struct LinearizeVectorBitCast final
577 :
public OpConversionPattern<vector::BitCastOp> {
579 LinearizeVectorBitCast(
const TypeConverter &typeConverter,
580 MLIRContext *context, PatternBenefit benefit = 1)
581 : OpConversionPattern(typeConverter, context, benefit) {}
583 matchAndRewrite(vector::BitCastOp castOp, OpAdaptor adaptor,
584 ConversionPatternRewriter &rewriter)
const override {
585 auto resType = getTypeConverter()->convertType(castOp.getType());
586 assert(resType &&
"expected 1-D vector type");
587 rewriter.replaceOpWithNewOp<vector::BitCastOp>(castOp, resType,
588 adaptor.getSource());
589 return mlir::success();
604struct LinearizeVectorCreateMask final
605 : OpConversionPattern<vector::CreateMaskOp> {
608 LinearizeVectorCreateMask(
const TypeConverter &typeConverter,
609 MLIRContext *context, PatternBenefit benefit = 1)
610 : OpConversionPattern(typeConverter, context, benefit) {}
613 matchAndRewrite(vector::CreateMaskOp createMaskOp, OpAdaptor adaptor,
614 ConversionPatternRewriter &rewriter)
const override {
615 Location loc = createMaskOp.getLoc();
616 VectorType srcTy = createMaskOp.getType();
617 auto srcShape = srcTy.getShape();
618 if (srcShape.size() != 2)
619 return rewriter.notifyMatchFailure(createMaskOp,
620 "only 2D mask is supported.");
622 if (srcShape[0] != 1)
623 return rewriter.notifyMatchFailure(
624 createMaskOp,
"only unit outer dimension is supported.");
626 auto dstTy = getTypeConverter()->convertType(srcTy);
628 return rewriter.notifyMatchFailure(createMaskOp,
"cannot convert type.");
634 auto firstOperand = adaptor.getOperands().front();
636 auto isNonZero = rewriter.createOrFold<mlir::arith::CmpIOp>(
637 loc, mlir::arith::CmpIPredicate::sgt, firstOperand, zero);
638 auto isNonZeroIndex = rewriter.createOrFold<mlir::arith::IndexCastOp>(
639 loc, rewriter.getIndexType(), isNonZero);
640 auto secondOperand = adaptor.getOperands().back();
641 auto maskSize = rewriter.createOrFold<mlir::arith::AndIOp>(
642 loc, rewriter.getIndexType(), isNonZeroIndex, secondOperand);
645 mlir::vector::CreateMaskOp::create(rewriter, loc, dstTy, maskSize);
646 rewriter.replaceOp(createMaskOp, newMask);
660struct LinearizeVectorLoad final :
public OpConversionPattern<vector::LoadOp> {
662 LinearizeVectorLoad(
const TypeConverter &typeConverter, MLIRContext *context,
663 PatternBenefit benefit = 1)
664 : OpConversionPattern(typeConverter, context, benefit) {}
667 matchAndRewrite(vector::LoadOp loadOp, OpAdaptor adaptor,
668 ConversionPatternRewriter &rewriter)
const override {
669 VectorType vecTy = loadOp.getType();
671 return rewriter.notifyMatchFailure(loadOp,
"expected vector type");
673 auto shape = vecTy.getShape();
674 auto scalableDims = vecTy.getScalableDims();
677 if (!llvm::all_of(shape.drop_back(1), [](
auto d) { return d == 1; }))
678 return rewriter.notifyMatchFailure(loadOp,
679 "only vector<1x1x...xN> supported");
681 if (llvm::any_of(scalableDims.drop_back(1), [](
bool s) { return s; }))
682 return rewriter.notifyMatchFailure(loadOp,
683 "only innermost dim may be scalable");
685 auto linearTy = typeConverter->convertType<VectorType>(vecTy);
688 vector::LoadOp::create(rewriter, loadOp.getLoc(), linearTy,
689 adaptor.getBase(), adaptor.getIndices());
690 rewriter.replaceOp(loadOp, newLoad.getResult());
706struct LinearizeVectorStore final
707 :
public OpConversionPattern<vector::StoreOp> {
709 LinearizeVectorStore(
const TypeConverter &typeConverter, MLIRContext *context,
710 PatternBenefit benefit = 1)
711 : OpConversionPattern(typeConverter, context, benefit) {}
714 matchAndRewrite(vector::StoreOp storeOp, OpAdaptor adaptor,
715 ConversionPatternRewriter &rewriter)
const override {
716 VectorType vecTy = storeOp.getValueToStore().getType();
718 return rewriter.notifyMatchFailure(storeOp,
"expected vector type");
720 auto shape = vecTy.getShape();
721 auto scalableDims = vecTy.getScalableDims();
724 if (!llvm::all_of(shape.drop_back(1), [](
auto d) { return d == 1; }))
725 return rewriter.notifyMatchFailure(storeOp,
726 "only vector<1x1x...xN> supported");
728 if (llvm::any_of(scalableDims.drop_back(1), [](
bool s) { return s; }))
729 return rewriter.notifyMatchFailure(storeOp,
730 "only innermost dim may be scalable");
732 rewriter.replaceOpWithNewOp<vector::StoreOp>(
733 storeOp, adaptor.getValueToStore(), adaptor.getBase(),
734 adaptor.getIndices());
753struct LinearizeVectorFromElements final
754 :
public OpConversionPattern<vector::FromElementsOp> {
756 LinearizeVectorFromElements(
const TypeConverter &typeConverter,
757 MLIRContext *context, PatternBenefit benefit = 1)
758 : OpConversionPattern(typeConverter, context, benefit) {}
760 matchAndRewrite(vector::FromElementsOp fromElementsOp, OpAdaptor adaptor,
761 ConversionPatternRewriter &rewriter)
const override {
763 getTypeConverter()->convertType<VectorType>(fromElementsOp.getType());
764 assert(dstTy &&
"vector type destination expected.");
766 OperandRange elements = fromElementsOp.getElements();
767 assert(elements.size() ==
static_cast<size_t>(dstTy.getNumElements()) &&
768 "expected same number of elements");
769 rewriter.replaceOpWithNewOp<vector::FromElementsOp>(fromElementsOp, dstTy,
789struct LinearizeVectorToElements final
790 :
public OpConversionPattern<vector::ToElementsOp> {
793 LinearizeVectorToElements(
const TypeConverter &typeConverter,
794 MLIRContext *context, PatternBenefit benefit = 1)
795 : OpConversionPattern(typeConverter, context, benefit) {}
798 matchAndRewrite(vector::ToElementsOp toElementsOp, OpAdaptor adaptor,
799 ConversionPatternRewriter &rewriter)
const override {
801 VectorType vecType = toElementsOp.getSource().getType();
802 if (vecType.getRank() <= 1)
803 return rewriter.notifyMatchFailure(
804 toElementsOp,
"the rank is already less than or equal to 1");
806 assert(vecType.getNumScalableDims() == 0 &&
807 "to_elements does not support scalable vectors");
809 VectorType::get({vecType.getNumElements()}, vecType.getElementType());
810 Value shapeCast = vector::ShapeCastOp::create(
811 rewriter, toElementsOp.getLoc(), vec1DType, toElementsOp.getSource());
812 auto newToElementsOp =
813 vector::ToElementsOp::create(rewriter, toElementsOp.getLoc(),
814 toElementsOp.getResultTypes(), shapeCast);
815 rewriter.replaceOp(toElementsOp, newToElementsOp);
833struct LinearizeVectorBroadcast final
834 :
public OpConversionPattern<vector::BroadcastOp> {
837 LinearizeVectorBroadcast(
const TypeConverter &typeConverter,
838 MLIRContext *context, PatternBenefit benefit = 1)
839 : OpConversionPattern(typeConverter, context, benefit) {}
842 matchAndRewrite(vector::BroadcastOp broadcastOp, OpAdaptor adaptor,
843 ConversionPatternRewriter &rewriter)
const override {
846 Type sourceType = broadcastOp.getSourceType();
847 if (
auto vecType = dyn_cast<VectorType>(sourceType)) {
848 numElements = vecType.getNumElements();
851 if (numElements != 1) {
852 return rewriter.notifyMatchFailure(
853 broadcastOp,
"only broadcasts of single elements can be linearized.");
856 auto dstTy = getTypeConverter()->convertType(broadcastOp.getType());
857 rewriter.replaceOpWithNewOp<vector::BroadcastOp>(broadcastOp, dstTy,
858 adaptor.getSource());
872 StringLiteral vectorDialect = vector::VectorDialect::getDialectNamespace();
874 bool supported = (opDialect == vectorDialect) ||
884 .Case<vector::ShapeCastOp>([&](
auto) {
return false; })
894 .Case<vector::ExtractStridedSliceOp>(
895 [&](vector::ExtractStridedSliceOp extractOp) {
896 return !extractOp.getType().isScalable();
898 .Case<vector::InsertStridedSliceOp>(
899 [&](vector::InsertStridedSliceOp insertOp) {
900 return !insertOp.getType().isScalable();
902 .Case<vector::InsertOp>([&](vector::InsertOp insertOp) {
903 return !insertOp.getType().isScalable();
905 .Case<vector::ExtractOp>([&](vector::ExtractOp extractOp) {
906 return !extractOp.getSourceVectorType().isScalable();
908 .Default([&](
auto) {
return true; });
911void mlir::vector::populateForVectorLinearize(
TypeConverter &typeConverter,
914 auto convertType = [](
Type type) -> std::optional<Type> {
915 VectorType vectorType = dyn_cast<VectorType>(type);
919 VectorType linearizedType =
920 VectorType::get(vectorType.getNumElements(),
921 vectorType.getElementType(), vectorType.isScalable());
922 return linearizedType;
924 typeConverter.addConversion(convertType);
928 if (inputs.size() != 1)
931 Value value = inputs.front();
932 if (!isa<VectorType>(type) || !isa<VectorType>(value.
getType()))
935 return vector::ShapeCastOp::create(builder, loc, type, value);
937 typeConverter.addSourceMaterialization(materializeCast);
938 typeConverter.addTargetMaterialization(materializeCast);
940 target.markUnknownOpDynamicallyLegal(
941 [=](
Operation *op) -> std::optional<bool> {
946 return typeConverter.isLegal(op);
950void mlir::vector::populateVectorLinearizeBasePatterns(
954 .add<LinearizeConstantLike, LinearizeVectorizable, LinearizeVectorBitCast,
955 LinearizeVectorCreateMask, LinearizeVectorLoad, LinearizeVectorStore,
956 LinearizeVectorBroadcast, LinearizeVectorFromElements,
957 LinearizeVectorToElements>(typeConverter,
patterns.getContext());
960void mlir::vector::populateVectorLinearizeShuffleLikeOpsPatterns(
963 patterns.add<LinearizeVectorShuffle, LinearizeVectorExtract,
964 LinearizeVectorInsert, LinearizeVectorExtractStridedSlice,
965 LinearizeVectorInsertStridedSlice>(typeConverter,
static FailureOr< Attribute > linearizeConstAttr(Location loc, ConversionPatternRewriter &rewriter, VectorType resType, Attribute value)
static bool isLinearizable(Operation *op)
This method defines the set of operations that are linearizable, and hence that are considered illega...
Attributes are known-constant values of operations.
StringRef getNamespace() const
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
This class provides the API for a sub-set of ops that are known to be constant-like.
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
unsigned getNumResults()
Return the number of results held by this operation.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
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.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
bool isLinearizableVector(VectorType type)
Returns true if the input Vector type can be linearized.
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
const FrozenRewritePatternSet & patterns
llvm::TypeSwitch< T, ResultT > TypeSwitch
bool isOneInteger(OpFoldResult v)
Return true if v is an IntegerAttr with value 1.
This trait tags Elementwise operatons that can be systematically vectorized.
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.