32 #include <type_traits>
40 if (llvm::all_of(pad, [](int64_t p) {
return p == 0; }))
43 ShapedType inputTy = cast<ShapedType>(input.
getType());
44 Type inputETy = inputTy.getElementType();
45 auto inputShape = inputTy.getShape();
47 assert((inputShape.size() * 2) == pad.size());
52 for (
size_t i : llvm::seq(inputShape.size())) {
53 auto lowPad = pad[i * 2];
54 auto highPad = pad[i * 2 + 1];
55 if (ShapedType::isDynamic(inputShape[i]))
56 paddedShape.push_back(inputShape[i]);
58 paddedShape.push_back(inputShape[i] + highPad + lowPad);
63 Value padValue = rewriter.
create<arith::ConstantOp>(loc, padAttr);
65 return rewriter.
create<tensor::PadOp>(
67 highIndices, padValue);
74 ShapedType resultTy = cast<ShapedType>(conv.
getType());
76 .
create<linalg::GenericOp>(
77 loc, resultTy,
ValueRange({bias, conv}), result, indexingMaps,
80 Value biasVal = args[0];
81 Type resType = args[1].getType();
82 if (resType != biasVal.
getType()) {
83 biasVal = builder.create<arith::ExtSIOp>(loc, resType, biasVal);
85 Value added = builder.create<arith::AddIOp>(loc, biasVal, args[1]);
86 builder.create<linalg::YieldOp>(loc, added);
96 ShapedType resultTy = cast<ShapedType>(result.
getType());
97 ShapedType sourceTy = cast<ShapedType>(source.
getType());
98 int64_t resultRank = resultTy.getRank();
99 int64_t sourceRank = sourceTy.getRank();
107 assert(sourceTy.hasStaticShape() &&
108 "Dynamic broadcasting shapes not supported!");
109 if (sourceRank == 1 && sourceTy.getDimSize(0) == 1) {
112 for (
auto dim : llvm::seq<int64_t>(0, sourceRank)) {
114 sourceDims.push_back(expr);
129 .
create<linalg::GenericOp>(
130 loc, resultTy,
ValueRange({source}), result, indexingMaps,
133 Value biasVal = args[0];
134 Type resType = args[1].getType();
135 if (resType != biasVal.
getType()) {
136 biasVal = builder.create<arith::ExtSIOp>(loc, resType, biasVal);
138 builder.create<linalg::YieldOp>(loc, biasVal);
145 return builder.
create<arith::ConstantIndexOp>(attr);
153 int64_t padBeforeAttr,
154 int64_t padAfterAttr,
Value kernelDim,
156 int64_t dilationAttr,
159 auto one = rewriter.
create<arith::ConstantOp>(
162 Value paddedBefore = builder.
create<arith::AddIOp>(inputDim, padBefore);
164 Value paddedAfter = builder.
create<arith::AddIOp>(paddedBefore, padAfter);
166 Value subOne = builder.
create<arith::SubIOp>(kernelDim, one);
168 Value dilated = builder.
create<arith::MulIOp>(dilation, subOne);
169 Value addOne = builder.
create<arith::AddIOp>(dilated, one);
171 Value subtract = builder.
create<arith::SubIOp>(paddedAfter, addOne);
173 Value divide = builder.
create<arith::DivUIOp>(subtract, stride);
174 return builder.
create<arith::AddIOp>(divide, one);
183 ShapedType inputTy = cast<ShapedType>(input.
getType());
184 int64_t inputRank = inputTy.getRank();
187 dynDims.resize(resultTy.getRank());
189 for (uint32_t i = 0, s = inputSizeDims.size(); i < s; ++i) {
190 int64_t inputDim = inputSizeDims[i];
191 int64_t kernelDim = kernelSizeDims[i];
192 if (resultTy.isDynamicDim(inputDim)) {
193 auto padTop = padAttr[i * 2];
194 auto padBottom = padAttr[i * 2 + 1];
195 auto stride = strideAttr[i];
196 auto dilation = dilationAttr[i];
197 Value initDynDim = rewriter.
create<tensor::DimOp>(loc, input, inputDim);
199 rewriter.
create<tensor::DimOp>(loc, weight, kernelDim);
203 kernelDynDim, stride, dilation, rewriter);
208 for (
int i = 0; i < inputRank; i++) {
209 if (resultTy.isDynamicDim(i) && !dynDims[i])
210 dynDims[i] = rewriter.
create<tensor::DimOp>(loc, input, i);
222 reassociationMap.resize(outputRank);
223 for (
int i = 0; i < outputRank; i++) {
226 reassociationMap[outputRank - 1].push_back(
232 template <
typename TosaConvOp,
typename LinalgConvOp,
typename LinalgConvQOp>
237 matchAndRewrite(TosaConvOp op,
typename TosaConvOp::Adaptor adaptor,
244 ShapedType inputTy = cast<ShapedType>(input.
getType());
245 ShapedType weightTy = cast<ShapedType>(weight.
getType());
246 ShapedType biasTy = cast<ShapedType>(bias.
getType());
249 Type inputETy = inputTy.getElementType();
250 Type resultETy = resultTy.getElementType();
255 bool isQuantized = op.getQuantizationInfo().has_value();
257 if (!weightTy.hasStaticShape() || !biasTy.hasStaticShape())
258 return rewriter.notifyMatchFailure(
259 op,
"tosa.conv ops require static shapes for weight and bias");
262 return rewriter.notifyMatchFailure(
263 op,
"tosa.conv ops does not support unsigned integer input");
267 for (
int i = 1; i < resultTy.getRank() - 1; i++) {
268 inputSizeDims.push_back(i);
269 kernelSizeDims.push_back(i);
273 loc, input, weight, resultTy, padAttr.
asArrayRef(),
275 inputSizeDims, kernelSizeDims, rewriter);
277 auto weightShape = weightTy.getShape();
280 TypedAttr zeroAttr = rewriter.getZeroAttr(inputETy);
282 auto quantizationInfo = *op.getQuantizationInfo();
283 int64_t iZp = quantizationInfo.getInputZp();
292 if (iZp < intMin || iZp > intMax)
293 return rewriter.notifyMatchFailure(
294 op,
"tosa.conv op quantization has zp outside of input range");
296 zeroAttr = rewriter.getIntegerAttr(inputETy, iZp);
301 llvm::append_range(pad, padAttr.
asArrayRef());
302 pad.resize(pad.size() + 2, 0);
303 input =
applyPad(loc, input, pad, zeroAttr, rewriter);
305 if (4 == inputTy.getRank()) {
309 isQuantized ? std::is_same_v<LinalgConvQOp, linalg::Conv2DNhwcHwcfQOp>
310 : std::is_same_v<LinalgConvOp, linalg::Conv2DNhwcHwcfOp>;
317 for (
int i = 1; i < resultTy.getRank(); i++)
318 weightPerm.push_back(i);
319 weightPerm.push_back(0);
322 for (
auto dim : weightPerm)
323 newWeightShape.push_back(weightShape[dim]);
324 auto weightPermAttr = rewriter.getI64TensorAttr(weightPerm);
325 Value weightPermValue =
326 rewriter.create<arith::ConstantOp>(loc, weightPermAttr);
329 weight = rewriter.create<tosa::TransposeOp>(loc, newWeightTy, weight,
337 if (5 == inputTy.getRank()) {
341 for (
int i = 1; i < resultTy.getRank(); i++)
342 weightPerm.push_back(i);
343 weightPerm.push_back(0);
346 for (
auto dim : weightPerm)
347 newWeightShape.push_back(weightShape[dim]);
348 auto weightPermAttr = rewriter.getI64TensorAttr(weightPerm);
349 Value weightPermValue =
350 rewriter.create<arith::ConstantOp>(loc, weightPermAttr);
353 weight = rewriter.create<tosa::TransposeOp>(loc, newWeightTy, weight,
362 auto strideAttr = rewriter.getI64TensorAttr(stride);
363 auto dilationAttr = rewriter.getI64TensorAttr(dilation);
365 Value biasEmptyTensor = rewriter.create<tensor::EmptyOp>(
366 loc, resultTy.getShape(), resultETy, filteredDims);
368 Value broadcastBias =
372 auto quantizationInfo = *op.getQuantizationInfo();
373 auto iZp = rewriter.getI32IntegerAttr(quantizationInfo.getInputZp());
374 auto kZp = rewriter.getI32IntegerAttr(quantizationInfo.getWeightZp());
376 auto iZpVal = rewriter.
create<arith::ConstantOp>(loc, iZp);
377 auto kZpVal = rewriter.
create<arith::ConstantOp>(loc, kZp);
381 .create<LinalgConvQOp>(
382 loc, resultTy,
ValueRange{input, weight, iZpVal, kZpVal},
383 ValueRange{broadcastBias}, strideAttr, dilationAttr)
386 rewriter.replaceOp(op, conv);
390 Value conv = rewriter
391 .create<LinalgConvOp>(
393 ValueRange{broadcastBias}, strideAttr, dilationAttr)
396 rewriter.replaceOp(op, conv);
401 class DepthwiseConvConverter
406 matchAndRewrite(tosa::DepthwiseConv2DOp op, OpAdaptor adaptor,
413 ShapedType inputTy = cast<ShapedType>(input.
getType());
414 ShapedType weightTy = cast<ShapedType>(weight.
getType());
415 ShapedType biasTy = cast<ShapedType>(bias.
getType());
417 int64_t resultRank = resultTy.getRank();
419 Type inputETy = inputTy.getElementType();
420 Type resultETy = resultTy.getElementType();
422 auto padAttr = cast<DenseI64ArrayAttr>(op->
getAttr(
"pad"));
423 auto strideTosaAttr = cast<DenseI64ArrayAttr>(op->
getAttr(
"stride"));
424 auto dilationTosaAttr = cast<DenseI64ArrayAttr>(op->
getAttr(
"dilation"));
426 if (!weightTy.hasStaticShape() || !biasTy.hasStaticShape())
427 return rewriter.notifyMatchFailure(
428 op,
"tosa.depthwise_conv ops require static shapes");
432 loc, input, weight, resultTy, padAttr.
asArrayRef(),
437 bool isQuantized = op->
hasAttr(
"quantization_info");
441 auto quantizationInfo =
442 cast<tosa::ConvOpQuantizationAttr>(op->
getAttr(
"quantization_info"));
443 iZp = rewriter.getI32IntegerAttr(quantizationInfo.getInputZp());
444 kZp = rewriter.getI32IntegerAttr(quantizationInfo.getWeightZp());
447 auto weightShape = weightTy.getShape();
448 auto resultShape = resultTy.getShape();
451 TypedAttr zeroAttr = rewriter.getZeroAttr(inputETy);
453 auto quantizationInfo =
454 cast<tosa::ConvOpQuantizationAttr>(op->
getAttr(
"quantization_info"));
455 int64_t iZp = quantizationInfo.getInputZp();
464 if (iZp < intMin || iZp > intMax)
465 return rewriter.notifyMatchFailure(
466 op,
"tosa.depthwise_conv op quantization has zp outside of input "
469 zeroAttr = rewriter.getIntegerAttr(inputETy, iZp);
474 llvm::append_range(pad, padAttr.
asArrayRef());
475 pad.resize(pad.size() + 2, 0);
477 input =
applyPad(loc, input, pad, zeroAttr, rewriter);
484 auto strideAttr = rewriter.getI64TensorAttr(stride);
485 auto dilationAttr = rewriter.getI64TensorAttr(dilation);
486 ShapedType linalgConvTy =
488 weightShape[2], weightShape[3]},
495 {rewriter.getAffineDimExpr(3)}, rewriter.getContext()));
496 indexingMaps.push_back(rewriter.getMultiDimIdentityMap(resultRank));
497 indexingMaps.push_back(rewriter.getMultiDimIdentityMap(resultRank));
499 auto resultZeroAttr = rewriter.getZeroAttr(resultETy);
500 Value emptyTensor = rewriter.create<tensor::EmptyOp>(
501 loc, linalgConvTy.getShape(), resultETy, filteredDims);
502 Value zero = rewriter.create<arith::ConstantOp>(loc, resultZeroAttr);
503 Value zeroTensor = rewriter
504 .create<linalg::FillOp>(loc,
ValueRange{zero},
508 Value biasEmptyTensor = rewriter.create<tensor::EmptyOp>(
509 loc, resultTy.getShape(), resultETy, filteredDims);
511 Value conv = rewriter
512 .create<linalg::DepthwiseConv2DNhwcHwcmOp>(
514 ValueRange{zeroTensor}, strideAttr, dilationAttr)
519 Value convReshape = rewriter.create<tensor::CollapseShapeOp>(
520 loc, resultTy, conv, reassociationMap);
524 .create<linalg::GenericOp>(
525 loc, resultTy,
ValueRange({bias, convReshape}),
526 biasEmptyTensor, indexingMaps,
530 Value added = nestedBuilder.create<arith::AddFOp>(
531 loc, args[0], args[1]);
532 nestedBuilder.create<linalg::YieldOp>(nestedLoc, added);
535 rewriter.replaceOp(op, result);
537 auto iZpVal = rewriter.create<arith::ConstantOp>(loc, iZp);
538 auto kZpVal = rewriter.create<arith::ConstantOp>(loc, kZp);
541 .create<linalg::DepthwiseConv2DNhwcHwcmQOp>(
542 loc, linalgConvTy,
ValueRange{input, weight, iZpVal, kZpVal},
543 ValueRange{zeroTensor}, strideAttr, dilationAttr)
547 Value convReshape = rewriter.create<tensor::CollapseShapeOp>(
548 loc, resultTy, conv, reassociationMap);
550 rewriter, loc, bias, convReshape, biasEmptyTensor, indexingMaps);
551 rewriter.replaceOp(op, result);
561 matchAndRewrite(tosa::MatMulOp op, OpAdaptor adaptor,
565 auto outputTy = cast<ShapedType>(op.getType());
566 auto outputElementTy = outputTy.getElementType();
571 if (!outputTy.hasRank() || outputTy.isDynamicDim(0)) {
572 dynDims[0] = rewriter.create<tensor::DimOp>(loc, op->
getOperand(0), 0);
575 if (!outputTy.hasRank() || outputTy.isDynamicDim(1)) {
576 dynDims[1] = rewriter.create<tensor::DimOp>(loc, op->
getOperand(0), 1);
579 if (!outputTy.hasRank() || outputTy.isDynamicDim(2)) {
580 dynDims[2] = rewriter.create<tensor::DimOp>(loc, op->
getOperand(1), 2);
585 auto zeroAttr = rewriter.getZeroAttr(outputElementTy);
586 Value zero = rewriter.create<arith::ConstantOp>(loc, zeroAttr);
587 auto emptyTensor = rewriter.create<tensor::EmptyOp>(
588 loc, outputTy.getShape(), outputTy.getElementType(), filteredDims);
589 Value zeroTensor = rewriter
590 .create<linalg::FillOp>(loc,
ValueRange{zero},
593 if (!op.getQuantizationInfo()) {
594 rewriter.replaceOpWithNewOp<linalg::BatchMatmulOp>(
600 auto quantizationInfo = *op.getQuantizationInfo();
601 auto aZp = rewriter.
create<arith::ConstantOp>(
602 loc, rewriter.getI32IntegerAttr(quantizationInfo.getAZp()));
603 auto bZp = rewriter.
create<arith::ConstantOp>(
604 loc, rewriter.getI32IntegerAttr(quantizationInfo.getBZp()));
605 rewriter.replaceOpWithNewOp<linalg::QuantizedBatchMatmulOp>(
607 ValueRange{adaptor.getA(), adaptor.getB(), aZp, bZp}, zeroTensor);
613 class FullyConnectedConverter
618 matchAndRewrite(tosa::FullyConnectedOp op, OpAdaptor adaptor,
621 auto outputTy = cast<ShapedType>(op.getType());
622 auto input = op.getInput();
623 auto inputTy = cast<ShapedType>(input.
getType());
625 auto bias = op.getBias();
627 auto weight = op.getWeight();
628 auto weightTy = cast<ShapedType>(weight.
getType());
629 auto weightShape = weightTy.getShape();
631 auto outputETy = outputTy.getElementType();
636 if (!inputTy.hasRank() || inputTy.isDynamicDim(0)) {
637 dynDims[0] = rewriter.create<tensor::DimOp>(loc, input, 0);
640 if (!weightTy.hasRank() || weightTy.isDynamicDim(0)) {
641 dynDims[1] = rewriter.create<tensor::DimOp>(loc, weight, 0);
647 auto permutationAttr = rewriter.getI64TensorAttr(permutation);
648 Value permutationValue =
649 rewriter.create<arith::ConstantOp>(loc, permutationAttr);
655 Value transposedWeight = rewriter.create<tosa::TransposeOp>(
656 loc, newWeightTy, weight, permutationValue);
658 Value biasEmptyTensor = rewriter.create<tensor::EmptyOp>(
659 loc, outputTy.getShape(), outputETy, filteredDims);
661 Value broadcastBias =
664 if (!op.getQuantizationInfo()) {
665 Value matmul = rewriter
666 .create<linalg::MatmulOp>(
668 ValueRange{input, transposedWeight}, broadcastBias)
671 rewriter.replaceOp(op, matmul);
675 auto quantizationInfo = *op.getQuantizationInfo();
676 auto inputZp = rewriter.
create<arith::ConstantOp>(
677 loc, rewriter.getI32IntegerAttr(quantizationInfo.getInputZp()));
678 auto outputZp = rewriter.
create<arith::ConstantOp>(
679 loc, rewriter.getI32IntegerAttr(quantizationInfo.getWeightZp()));
682 .create<linalg::QuantizedMatmulOp>(
684 ValueRange{input, transposedWeight, inputZp, outputZp},
688 rewriter.replaceOp(op, matmul);
699 computeDynamicOutputSizes(tosa::MaxPool2dOp op,
PatternRewriter &rewriter) {
711 if (resultTy.isDynamicDim(0))
712 dynamicDims.push_back(rewriter.
create<tensor::DimOp>(loc, input, 0));
715 for (int64_t dim : {1, 2}) {
716 if (!resultTy.isDynamicDim(dim))
720 int64_t index = dim - 1;
723 Value ihw = rewriter.
create<tensor::DimOp>(loc, input, dim);
726 Value khw = rewriter.
create<arith::ConstantIndexOp>(loc, kernel[index]);
730 pad[index * 2 + 1], khw, stride[index],
732 dynamicDims.push_back(ohw);
736 if (resultTy.isDynamicDim(3))
737 dynamicDims.push_back(rewriter.
create<tensor::DimOp>(loc, input, 3));
742 LogicalResult matchAndRewrite(tosa::MaxPool2dOp op,
746 ShapedType inputTy = input.getType();
748 ShapedType resultTy = op.getType();
749 Type resultETy = inputTy.getElementType();
754 TypedAttr initialAttr;
757 resultETy, APFloat::getLargest(
758 cast<FloatType>(resultETy).getFloatSemantics(),
true));
760 if (isa<IntegerType>(resultETy))
767 op,
"Unsupported initial value for tosa.maxpool_2d op");
772 llvm::append_range(pad, op.getPad());
773 pad.resize(pad.size() + 2, 0);
775 Value paddedInput =
applyPad(loc, input, pad, initialAttr, rewriter);
777 Value initialValue = rewriter.
create<arith::ConstantOp>(loc, initialAttr);
786 Value emptyTensor = rewriter.
create<tensor::EmptyOp>(
787 loc, resultTy.getShape(), resultTy.getElementType(), dynamicDims);
789 Value filledEmptyTensor =
790 rewriter.
create<linalg::FillOp>(loc, initialValue, emptyTensor)
793 Value fakeWindowDims =
794 rewriter.
create<tensor::EmptyOp>(loc, kernel, resultETy);
798 filledEmptyTensor, strideAttr, dilationAttr);
807 LogicalResult matchAndRewrite(tosa::AvgPool2dOp op,
810 Value input = op.getInput();
811 ShapedType inputTy = cast<ShapedType>(input.
getType());
812 Type inElementTy = inputTy.getElementType();
814 ShapedType resultTy = cast<ShapedType>(op.getType());
815 Type resultETy = cast<ShapedType>(op.getType()).getElementType();
817 Type accETy = op.getAccType();
818 ShapedType accTy = resultTy.
clone(accETy);
822 if (!dynamicDimsOr.has_value())
829 llvm::append_range(pad, op.getPad());
830 pad.resize(pad.size() + 2, 0);
831 TypedAttr padAttr = rewriter.
getZeroAttr(inElementTy);
835 Value paddedInput =
applyPad(loc, input, pad, padAttr, rewriter);
838 Value initialValue = rewriter.
create<arith::ConstantOp>(loc, initialAttr);
847 Value poolEmptyTensor = rewriter.
create<tensor::EmptyOp>(
848 loc, accTy.getShape(), accETy, dynamicDims);
850 Value filledEmptyTensor =
856 Value fakeWindowDims =
857 rewriter.
create<tensor::EmptyOp>(loc, kernel, accETy);
860 Value poolingOp = rewriter
861 .
create<linalg::PoolingNhwcSumOp>(
864 filledEmptyTensor, strideAttr, dilationAttr)
869 Value iH = rewriter.
create<tensor::DimOp>(loc, poolingOp, 1);
870 Value iW = rewriter.
create<tensor::DimOp>(loc, poolingOp, 2);
872 auto one = rewriter.
create<arith::ConstantIndexOp>(loc, 1);
873 iH = rewriter.
create<arith::SubIOp>(loc, iH, one);
874 iW = rewriter.
create<arith::SubIOp>(loc, iW, one);
876 Value genericEmptyTensor = rewriter.
create<tensor::EmptyOp>(
877 loc, resultTy.getShape(), resultETy, dynamicDims);
880 auto genericOp = rewriter.
create<linalg::GenericOp>(
886 auto zero = rewriter.
create<arith::ConstantIndexOp>(loc, 0);
894 auto padVal = rewriter.
create<arith::ConstantIndexOp>(loc, pad);
895 Value dpos = rewriter.
create<arith::SubIOp>(loc, pos, padVal);
897 Value offset = rewriter.
create<arith::MinSIOp>(loc, dpos, zero);
898 return rewriter.
create<arith::AddIOp>(loc, valid, offset)
902 auto coverageFn = [&](int64_t i,
Value isize) ->
Value {
904 rewriter.
create<arith::ConstantIndexOp>(loc, stride[i - 1]);
906 rewriter.
create<arith::ConstantIndexOp>(loc, kernel[i - 1]);
909 Value left = rewriter.
create<linalg::IndexOp>(loc, i);
910 Value right = rewriter.
create<arith::SubIOp>(loc, isize, left);
911 left = rewriter.
create<arith::MulIOp>(loc, left, strideVal);
912 right = rewriter.
create<arith::MulIOp>(loc, right, strideVal);
915 val = padFn(val, left, pad[i * 2]);
916 val = padFn(val, right, pad[i * 2 + 1]);
917 return rewriter.
create<arith::MaxSIOp>(loc, one, val);
921 Value kH3 = coverageFn(1, iH);
922 Value kW3 = coverageFn(2, iW);
925 auto count = rewriter.
create<arith::IndexCastOp>(
927 rewriter.
create<arith::MulIOp>(loc, kH3, kW3));
932 Value poolVal = args[0];
933 if (isa<FloatType>(accETy)) {
934 auto countF = rewriter.
create<arith::SIToFPOp>(loc, accETy, count);
935 poolVal = rewriter.
create<arith::DivFOp>(loc, poolVal, countF)
937 if (accETy.getIntOrFloatBitWidth() >
940 rewriter.
create<arith::TruncFOp>(loc, resultETy, poolVal);
945 if (op.getQuantizationInfo()) {
946 auto quantizationInfo = *op.getQuantizationInfo();
947 auto inputZp = rewriter.
create<arith::ConstantOp>(
950 rewriter.
create<arith::MulIOp>(loc, accETy, count, inputZp);
952 rewriter.
create<arith::SubIOp>(loc, accETy, poolVal, offset);
958 Value thirtyTwo32 = rewriter.
create<arith::ConstantOp>(
962 rewriter.
create<arith::SubIOp>(loc, count, one32);
964 rewriter.
create<math::CountLeadingZerosOp>(loc, countSubOne);
966 rewriter.
create<arith::SubIOp>(loc, thirtyTwo32, leadingZeros);
971 Value thirtyShiftPlusOne = rewriter.
create<arith::ConstantOp>(
974 rewriter.
create<arith::ShLIOp>(loc, thirtyShiftPlusOne, k64);
980 rewriter.
create<arith::DivUIOp>(loc, numerator, count64);
981 multiplier = rewriter.
create<arith::TruncIOp>(
987 Value thirty8 = rewriter.
create<arith::ConstantOp>(
989 Value shift = rewriter.
create<arith::AddIOp>(loc, k8, thirty8);
994 poolVal, multiplier, shift,
1000 if (op.getQuantizationInfo()) {
1001 auto quantizationInfo = *op.getQuantizationInfo();
1002 auto outputZp = rewriter.
create<arith::ConstantOp>(
1004 quantizationInfo.getOutputZp()));
1005 scaled = rewriter.
create<arith::AddIOp>(loc, scaled, outputZp)
1012 auto min = rewriter.
create<arith::ConstantIntOp>(
1013 loc, APInt::getSignedMinValue(outBitwidth).getSExtValue(),
1015 auto max = rewriter.
create<arith::ConstantIntOp>(
1016 loc, APInt::getSignedMaxValue(outBitwidth).getSExtValue(),
1025 rewriter.
create<arith::TruncIOp>(loc, resultETy, poolVal);
1029 rewriter.
create<linalg::YieldOp>(loc, poolVal);
1032 rewriter.
replaceOp(op, genericOp.getResult(0));
1041 LogicalResult matchAndRewrite(tosa::TransposeOp op,
1044 if (failed(op.getConstantPerms(constantPerms)))
1052 auto permutedSizes =
1053 applyPermutation<OpFoldResult>(inputSizes, constantPerms);
1055 auto permutedInit = rewriter.
create<tensor::EmptyOp>(
1056 loc, permutedSizes, op.getInput1().getType().getElementType());
1058 op, op.getInput1(), permutedInit, constantPerms);
1066 if (
options.preferConv2DKernelLayoutHWCF) {
1067 patterns->
add<ConvConverter<tosa::Conv2DOp, linalg::Conv2DNhwcHwcfOp,
1068 linalg::Conv2DNhwcHwcfQOp>>(
1071 patterns->
add<ConvConverter<tosa::Conv2DOp, linalg::Conv2DNhwcFhwcOp,
1072 linalg::Conv2DNhwcFhwcQOp>>(
1077 ConvConverter<tosa::Conv3DOp, linalg::Conv3DNdhwcDhwcfOp, linalg::Conv3DNdhwcDhwcfQOp>,
1078 DepthwiseConvConverter,
1082 FullyConnectedConverter,
static llvm::ManagedStatic< PassManagerOptions > options
static Value clamp(ImplicitLocOpBuilder &builder, Value value, Value lowerBound, Value upperBound)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static mlir::Value applyPad(Location loc, Value input, ArrayRef< int64_t > pad, TypedAttr padAttr, OpBuilder &rewriter)
static mlir::Value linalgBroadcastAndMaybeExtSI(PatternRewriter &rewriter, Location loc, Value source, Value result)
static void createDepthwiseConvCollapseMap(int64_t outputRank, SmallVector< ReassociationExprs, 4 > &reassociationMap, OpBuilder &rewriter)
static mlir::Value linalgIntBroadcastExtSIAdd(PatternRewriter &rewriter, Location loc, Value bias, Value conv, Value result, ArrayRef< AffineMap > indexingMaps)
static mlir::Value getConvOrPoolOutputDim(Location loc, Value inputDim, int64_t padBeforeAttr, int64_t padAfterAttr, Value kernelDim, int64_t strideAttr, int64_t dilationAttr, OpBuilder &rewriter)
static mlir::Value reifyConstantDim(int64_t attr, ImplicitLocOpBuilder &builder)
static SmallVector< Value > inferDynamicDimsForConv(Location loc, Value input, Value weight, ShapedType resultTy, ArrayRef< int64_t > padAttr, ArrayRef< int64_t > strideAttr, ArrayRef< int64_t > dilationAttr, ArrayRef< int64_t > inputSizeDims, ArrayRef< int64_t > kernelSizeDims, OpBuilder &rewriter)
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
Attributes are known-constant values of operations.
IntegerAttr getIndexAttr(int64_t value)
IntegerAttr getI32IntegerAttr(int32_t value)
IntegerAttr getIntegerAttr(Type type, int64_t value)
AffineMap getMultiDimIdentityMap(unsigned rank)
FloatAttr getFloatAttr(Type type, double value)
AffineExpr getAffineConstantExpr(int64_t constant)
IntegerAttr getI64IntegerAttr(int64_t value)
BoolAttr getBoolAttr(bool value)
TypedAttr getZeroAttr(Type type)
AffineExpr getAffineDimExpr(unsigned position)
MLIRContext * getContext() const
DenseIntElementsAttr getI64VectorAttr(ArrayRef< int64_t > values)
IntegerAttr getI8IntegerAttr(int8_t value)
This class implements a pattern rewriter for use with ConversionPatterns.
ImplicitLocOpBuilder maintains a 'current location', allowing use of the create<> method without spec...
OpTy create(Args &&...args)
Create an operation of specific op type at the current insertion point and location.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
OpConversionPattern is a wrapper around ConversionPattern that allows for matching and rewriting agai...
Value getOperand(unsigned idx)
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
bool hasAttr(StringAttr name)
Return true if the operation has an attribute with the provided name, false otherwise.
Operation * clone(IRMapping &mapper, CloneOptions options=CloneOptions::all())
Create a deep copy of this operation, remapping any operands that use values outside of the operation...
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
static Operation * create(Location location, OperationName name, TypeRange resultTypes, ValueRange operands, NamedAttrList &&attributes, OpaqueProperties properties, BlockRange successors, unsigned numRegions)
Create a new Operation with the specific fields.
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.
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,...
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
Tensor types represent multi-dimensional arrays, and have two variants: RankedTensorType and Unranked...
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isUnsignedInteger() const
Return true if this is an unsigned integer type (with the specified width).
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class 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.
Base class for DenseArrayAttr that is instantiated and specialized for each supported element type be...
ArrayRef< T > asArrayRef() const
SmallVector< OpFoldResult > getMixedSizes(OpBuilder &builder, Location loc, Value value)
Return the dimensions of the given tensor value.
std::optional< SmallVector< Value > > checkHasDynamicBatchDims(PatternRewriter &rewriter, Op op, ArrayRef< Value > params)
SmallVector< utils::IteratorType > getNParallelLoopsAttrs(unsigned nParallelLoops)
SmallVector< Value > condenseValues(const SmallVector< Value > &values)
Value clampIntHelper(Location loc, Value arg, Value min, Value max, OpBuilder &rewriter, bool isUnsigned)
void populateTosaToLinalgNamedConversionPatterns(RewritePatternSet *patterns, const TosaToLinalgNamedOptions &options)
Populates conversion passes from TOSA dialect to Linalg named operations.
Include the generated interface declarations.
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool isPermutationVector(ArrayRef< int64_t > interchange)
Method to check if an interchange vector is a permutation.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...