16#include "llvm/ADT/APFloat.h"
33#define GEN_PASS_DEF_TOSANARROWI64TOI32PASS
34#define GEN_PASS_DEF_TOSANARROWF64TOF32PASS
35#include "mlir/Dialect/Tosa/Transforms/Passes.h.inc"
45enum class TosaNarrowKind { Int64ToInt32, Float64ToFloat32 };
51template <TosaNarrowKind Kind>
52bool isSourceInteger(IntegerType type) {
53 if constexpr (Kind == TosaNarrowKind::Int64ToInt32)
54 return type.isInteger(64);
58template <TosaNarrowKind Kind>
59bool isSourceFloat(FloatType type) {
60 if constexpr (Kind == TosaNarrowKind::Float64ToFloat32)
65template <TosaNarrowKind Kind>
66Type convertInteger(IntegerType type) {
67 if (!isSourceInteger<Kind>(type))
69 if constexpr (Kind == TosaNarrowKind::Int64ToInt32)
70 return IntegerType::get(type.getContext(), 32);
74template <TosaNarrowKind Kind>
75Type convertFloat(FloatType type) {
76 if (!isSourceFloat<Kind>(type))
78 if constexpr (Kind == TosaNarrowKind::Float64ToFloat32)
79 return Float32Type::get(type.getContext());
83template <TosaNarrowKind Kind>
84bool isSourceElement(
Type type) {
85 if (
auto intTy = dyn_cast<IntegerType>(type))
86 return isSourceInteger<Kind>(intTy);
87 if (
auto floatTy = dyn_cast<FloatType>(type))
88 return isSourceFloat<Kind>(floatTy);
92template <TosaNarrowKind Kind>
94 if (
auto intTy = dyn_cast<IntegerType>(type))
95 return convertInteger<Kind>(intTy);
96 if (
auto floatTy = dyn_cast<FloatType>(type))
97 return convertFloat<Kind>(floatTy);
101template <TosaNarrowKind Kind>
102bool typeNeedsConversion(
Type type) {
103 if (
auto shaped = dyn_cast<ShapedType>(type))
104 return isSourceElement<Kind>(shaped.getElementType());
105 return isSourceElement<Kind>(type);
108FailureOr<APInt> convertIntegerConstant(IntegerType targetType,
110 bool allowLossyConversion) {
111 const unsigned targetWidth = targetType.getWidth();
112 if (!allowLossyConversion && !value.isSignedIntN(targetWidth))
115 if (allowLossyConversion)
116 return value.truncSSat(targetWidth);
117 return value.sextOrTrunc(targetWidth);
120FailureOr<APFloat> convertFloatConstant(FloatType targetType,
121 const APFloat &value,
122 bool allowLossyConversion) {
123 APFloat converted(value);
124 bool losesInfo =
false;
125 converted.convert(targetType.getFloatSemantics(),
126 APFloat::rmNearestTiesToEven, &losesInfo);
127 if (!allowLossyConversion && losesInfo)
134template <TosaNarrowKind Kind>
135FailureOr<Attribute> tryConvertScalarAttribute(
Attribute attribute,
136 bool allowLossyConversion) {
137 if constexpr (Kind == TosaNarrowKind::Int64ToInt32) {
138 if (
const auto intAttr = dyn_cast<IntegerAttr>(attribute)) {
139 if (
const auto intType = dyn_cast<IntegerType>(intAttr.getType());
140 intType && isSourceInteger<Kind>(intType)) {
141 const auto convertedType =
142 cast<IntegerType>(convertInteger<Kind>(intType));
143 FailureOr<APInt> convertedValue = convertIntegerConstant(
144 convertedType, intAttr.getValue(), allowLossyConversion);
145 if (
failed(convertedValue))
147 return IntegerAttr::get(convertedType, convertedValue.value());
150 }
else if constexpr (Kind == TosaNarrowKind::Float64ToFloat32) {
151 if (
const auto floatAttr = dyn_cast<FloatAttr>(attribute)) {
152 if (
const auto floatType = dyn_cast<FloatType>(floatAttr.getType());
153 floatType && isSourceFloat<Kind>(floatType)) {
154 const auto convertedType =
155 cast<FloatType>(convertFloat<Kind>(floatType));
156 FailureOr<APFloat> convertedValue = convertFloatConstant(
157 convertedType, floatAttr.getValue(), allowLossyConversion);
158 if (
failed(convertedValue))
160 return FloatAttr::get(convertedType, convertedValue.value());
168template <TosaNarrowKind Kind>
172 bool allowLossyConversion) {
173 if constexpr (Kind != TosaNarrowKind::Int64ToInt32)
176 const auto oldElementType = dyn_cast<IntegerType>(type.getElementType());
177 if (!oldElementType || !isSourceInteger<Kind>(oldElementType))
181 dyn_cast_or_null<ShapedType>(typeConverter.convertType(type));
185 const auto newElementType = dyn_cast<IntegerType>(newType.getElementType());
189 if (!allowLossyConversion) {
190 for (APInt value : attr.getValues<APInt>())
191 if (
failed(convertIntegerConstant(newElementType, value,
197 attr.
mapValues(newElementType, [&](
const APInt &value) -> APInt {
198 return convertIntegerConstant(newElementType, value,
202 return convertedAttr;
205template <TosaNarrowKind Kind>
209 bool allowLossyConversion) {
210 if constexpr (Kind != TosaNarrowKind::Float64ToFloat32)
213 const auto oldElementType = dyn_cast<FloatType>(type.getElementType());
214 if (!oldElementType || !isSourceFloat<Kind>(oldElementType))
218 dyn_cast_or_null<ShapedType>(typeConverter.convertType(type));
222 const auto newElementType = dyn_cast<FloatType>(newType.getElementType());
226 if (!allowLossyConversion) {
227 for (APFloat value : attr.getValues<APFloat>())
228 if (
failed(convertFloatConstant(newElementType, value,
234 attr.
mapValues(newElementType, [&](
const APFloat &value) -> APInt {
235 APFloat converted = convertFloatConstant(newElementType, value,
240 return converted.bitcastToAPInt();
242 return convertedAttr;
245template <TosaNarrowKind Kind>
247 ShapedType type, DenseResourceElementsAttr attr,
248 const TypeConverter &typeConverter,
bool allowLossyConversion) {
249 static_assert(Kind == TosaNarrowKind::Int64ToInt32 ||
250 Kind == TosaNarrowKind::Float64ToFloat32);
252 std::conditional_t<Kind == TosaNarrowKind::Int64ToInt32, int64_t, double>;
254 std::conditional_t<Kind == TosaNarrowKind::Int64ToInt32, int32_t, float>;
256 if (Kind == TosaNarrowKind::Int64ToInt32 &&
257 !isa<DenseI64ResourceElementsAttr>(attr)) {
261 if (Kind == TosaNarrowKind::Float64ToFloat32 &&
262 !isa<DenseF64ResourceElementsAttr>(attr)) {
266 auto narrow = [](From value) {
267 if constexpr (Kind == TosaNarrowKind::Int64ToInt32) {
268 value = std::clamp<From>(value, std::numeric_limits<To>::min(),
269 std::numeric_limits<To>::max());
272 return static_cast<To
>(value);
276 dyn_cast_or_null<ShapedType>(typeConverter.convertType(type));
281 const std::optional<ArrayRef<From>> values =
288 newValues.reserve(values->size());
289 for (From value : *values) {
290 const To convertedValue = narrow(value);
291 if (!allowLossyConversion && convertedValue != value) {
295 newValues.push_back(convertedValue);
301 auto resourceManager =
303 resourceManager.getBlobManager().update(attr.getRawHandle().getKey(),
306 return DenseResourceElementsAttr::get(newType, attr.getRawHandle());
309template <TosaNarrowKind Kind,
typename AttrT>
311convertAttributeWithTypeConverter(AttrT attr,
Type type,
313 if (!typeNeedsConversion<Kind>(type))
316 const std::optional<Attribute> convertedAttribute =
317 typeConverter->convertTypeAttribute(type, attr);
318 if (!convertedAttribute)
321 return convertedAttribute.value();
326template <TosaNarrowKind Kind>
328verifyCastDoesNotLosePrecision(
Operation *op, ShapedType inputType,
329 ShapedType resultType,
330 ConversionPatternRewriter &rewriter) {
331 if constexpr (Kind == TosaNarrowKind::Int64ToInt32) {
332 const auto elementInputIntType =
333 dyn_cast<IntegerType>(inputType.getElementType());
334 const auto elementResultIntType =
335 dyn_cast<IntegerType>(resultType.getElementType());
336 if (elementInputIntType && elementResultIntType &&
337 elementInputIntType.getWidth() > elementResultIntType.getWidth())
338 return rewriter.notifyMatchFailure(
339 op,
"Narrowing cast may lead to data loss.");
340 }
else if constexpr (Kind == TosaNarrowKind::Float64ToFloat32) {
341 const auto elementInputFloatType =
342 dyn_cast<FloatType>(inputType.getElementType());
343 const auto elementResultFloatType =
344 dyn_cast<FloatType>(resultType.getElementType());
345 if (elementInputFloatType && elementResultFloatType &&
346 elementInputFloatType.getIntOrFloatBitWidth() >
347 elementResultFloatType.getIntOrFloatBitWidth())
348 return rewriter.notifyMatchFailure(
349 op,
"Narrowing cast may lead to data loss.");
361template <TosaNarrowKind Kind>
363 ConversionPatternRewriter &rewriter,
365 bool allowLossyConversion) {
375 const Attribute attribute = namedAttribute.getValue();
377 if (isa<IntegerAttr>(attribute) || isa<FloatAttr>(attribute)) {
378 FailureOr<Attribute> convertedAttr =
379 tryConvertScalarAttribute<Kind>(attribute, allowLossyConversion);
380 if (
failed(convertedAttr))
381 return rewriter.notifyMatchFailure(
382 op,
"Scalar attribute narrowing would lose precision; enable "
383 "aggressive rewrite to override.");
384 state.addAttribute(namedAttribute.getName(), convertedAttr.value());
388 if (
const auto typeAttr = dyn_cast<TypeAttr>(attribute)) {
389 FailureOr<Attribute> convertedAttr =
390 convertAttributeWithTypeConverter<Kind>(typeAttr, typeAttr.getValue(),
392 if (
failed(convertedAttr))
393 return rewriter.notifyMatchFailure(op,
394 "Failed to convert type attribute.");
395 state.addAttribute(namedAttribute.getName(), convertedAttr.value());
399 if (
const auto denseElementsAttr = dyn_cast<DenseElementsAttr>(attribute)) {
400 FailureOr<Attribute> convertedAttr =
401 convertAttributeWithTypeConverter<Kind>(
402 denseElementsAttr, denseElementsAttr.getType(), typeConverter);
403 if (
failed(convertedAttr))
404 return rewriter.notifyMatchFailure(
405 op,
"Failed to convert dense elements attribute without precision "
406 "loss; enable aggressive rewrite to override.");
407 state.addAttribute(namedAttribute.getName(), convertedAttr.value());
411 if (
const auto denseResourceElementsAttr =
412 dyn_cast<DenseResourceElementsAttr>(attribute)) {
413 FailureOr<Attribute> convertedAttr =
414 convertAttributeWithTypeConverter<Kind>(
415 denseResourceElementsAttr, denseResourceElementsAttr.getType(),
417 if (
failed(convertedAttr))
418 return rewriter.notifyMatchFailure(
419 op,
"Failed to convert dense resource elements attribute without "
420 "precision loss; enable aggressive rewrite to override.");
421 state.addAttribute(namedAttribute.getName(), convertedAttr.value());
425 state.addAttribute(namedAttribute.getName(), attribute);
429 if (
failed(rewriter.convertRegionTypes(®ion, *typeConverter)))
431 Region *newRegion = state.addRegion();
432 rewriter.inlineRegionBefore(region, *newRegion, newRegion->
begin());
435 Operation *newOp = rewriter.create(state);
440template <TosaNarrowKind Kind>
443 ConvertGenericOp(TypeConverter &typeConverter, MLIRContext *context,
444 bool allowLossyConversion)
445 : ConversionPattern(typeConverter, MatchAnyOpTypeTag{}, 0, context),
446 allowLossyConversion(allowLossyConversion) {}
449 matchAndRewrite(Operation *op, ArrayRef<Value> operands,
450 ConversionPatternRewriter &rewriter)
const final {
451 if (!isa<tosa::TosaOp>(op))
452 return rewriter.notifyMatchFailure(
454 "Support for operations other than TOSA has not been implemented.");
456 return convertGenericOp<Kind>(op, operands, rewriter, typeConverter,
457 allowLossyConversion);
461 const bool allowLossyConversion;
464template <
typename OpTy, TosaNarrowKind Kind>
465class ConvertTypedOp :
public OpConversionPattern<OpTy> {
467 ConvertTypedOp(TypeConverter &typeConverter, MLIRContext *context)
468 : OpConversionPattern<OpTy>(typeConverter, context) {}
471 matchAndRewrite(OpTy op,
typename OpTy::Adaptor adaptor,
472 ConversionPatternRewriter &rewriter)
const final {
473 return convertGenericOp<Kind>(op, adaptor.getOperands(), rewriter,
474 this->getTypeConverter(),
484template <TosaNarrowKind Kind>
485class ConvertCastOpWithBoundsChecking
486 :
public OpConversionPattern<tosa::CastOp> {
487 using OpConversionPattern<tosa::CastOp>::OpConversionPattern;
490 matchAndRewrite(tosa::CastOp op,
typename tosa::CastOp::Adaptor adaptor,
491 ConversionPatternRewriter &rewriter)
const final {
492 const auto inputType = dyn_cast<ShapedType>(adaptor.getInput().getType());
494 if (!inputType || !resultType)
497 const TypeConverter *typeConverter = this->getTypeConverter();
498 if (
failed(verifyCastDoesNotLosePrecision<Kind>(op, inputType, resultType,
502 rewriter.replaceOpWithNewOp<tosa::CastOp>(
503 op, typeConverter->convertType(resultType), adaptor.getInput(),
510class ConvertArgMaxOpWithBoundsChecking
511 :
public OpConversionPattern<tosa::ArgMaxOp> {
512 using OpConversionPattern::OpConversionPattern;
515 matchAndRewrite(tosa::ArgMaxOp op,
typename tosa::ArgMaxOp::Adaptor adaptor,
516 ConversionPatternRewriter &rewriter)
const final {
517 const int32_t axis = op.getAxis();
518 const auto inputType = dyn_cast<ShapedType>(adaptor.getInput().getType());
519 if (!inputType || !inputType.isStaticDim(axis))
520 return rewriter.notifyMatchFailure(
521 op,
"Requires a static axis dimension for bounds checking.");
522 const int64_t axisDim = inputType.getDimSize(axis);
523 if (axisDim >= std::numeric_limits<int32_t>::max())
524 return rewriter.notifyMatchFailure(
525 op,
"Axis dimension is too large to narrow safely.");
527 const Type resultType = op.getOutput().getType();
528 const Type newResultType =
529 this->getTypeConverter()->convertType(resultType);
530 rewriter.replaceOpWithNewOp<tosa::ArgMaxOp>(op, newResultType,
531 adaptor.getInput(), axis);
536template <TosaNarrowKind Kind>
537class ConvertClampOpWithBoundsChecking
538 :
public OpConversionPattern<tosa::ClampOp> {
539 static_assert(
Kind == TosaNarrowKind::Int64ToInt32,
540 "Clamp bounds checking only supported for integer narrowing");
541 using OpConversionPattern<tosa::ClampOp>::OpConversionPattern;
544 matchAndRewrite(tosa::ClampOp op,
typename tosa::ClampOp::Adaptor adaptor,
545 ConversionPatternRewriter &rewriter)
const final {
546 auto minAttr = dyn_cast<IntegerAttr>(op.getMinValAttr());
547 auto maxAttr = dyn_cast<IntegerAttr>(op.getMaxValAttr());
548 if (!minAttr || !maxAttr)
549 return rewriter.notifyMatchFailure(
550 op,
"Clamp attributes must be integer constants.");
552 const int64_t
min = minAttr.getInt();
553 const int64_t
max = maxAttr.getInt();
554 if (
min < std::numeric_limits<int32_t>::min() ||
555 max > std::numeric_limits<int32_t>::max())
556 return rewriter.notifyMatchFailure(
557 op,
"Clamp bounds exceed int32 range. Narrowing may lose data.");
559 const Type resultType = op.getOutput().getType();
560 const Type newResultType =
561 this->getTypeConverter()->convertType(resultType);
562 const auto newResultShaped = dyn_cast<ShapedType>(newResultType);
563 if (!newResultShaped)
565 const auto newElementType =
566 dyn_cast<IntegerType>(newResultShaped.getElementType());
570 const IntegerAttr newMinAttr = IntegerAttr::get(newElementType,
min);
571 const IntegerAttr newMaxAttr = IntegerAttr::get(newElementType,
max);
573 rewriter.replaceOpWithNewOp<tosa::ClampOp>(op, newResultType,
574 adaptor.getInput(), newMinAttr,
575 newMaxAttr, op.getNanModeAttr());
582template <TosaNarrowKind Kind>
583LogicalResult runTosaNarrowing(
Operation *op,
bool aggressiveRewrite,
584 bool convertFunctionBoundaries) {
586 const bool allowLossyConversion = aggressiveRewrite;
589 typeConverter.addConversion([](
Type type) ->
Type {
return type; });
591 typeConverter.addConversion(
592 [](IntegerType type) ->
Type {
return convertInteger<Kind>(type); });
593 typeConverter.addConversion(
594 [](FloatType type) ->
Type {
return convertFloat<Kind>(type); });
595 typeConverter.addConversion([&typeConverter](RankedTensorType type) ->
Type {
596 Type elementType = type.getElementType();
597 if (!isSourceElement<Kind>(elementType))
599 Type converted = typeConverter.convertType(elementType);
600 if (!converted || converted == elementType)
602 return RankedTensorType::get(type.getShape(), converted,
605 typeConverter.addConversion(
606 [&typeConverter](UnrankedTensorType type) ->
Type {
607 Type elementType = type.getElementType();
608 if (!isSourceElement<Kind>(elementType))
610 Type converted = typeConverter.convertType(elementType);
611 if (!converted || converted == elementType)
613 return UnrankedTensorType::get(converted);
616 const auto materializeCast = [](
OpBuilder &builder,
Type resultType,
618 if (inputs.size() != 1)
620 return tosa::CastOp::create(
621 builder, loc, resultType, inputs.front(),
623 .isUnsignedInteger());
625 typeConverter.addSourceMaterialization(materializeCast);
626 typeConverter.addTargetMaterialization(materializeCast);
628 typeConverter.addTypeAttributeConversion(
629 [&typeConverter, allowLossyConversion](ShapedType type,
630 DenseResourceElementsAttr attr)
631 -> TypeConverter::AttributeConversionResult {
633 type, attr, typeConverter, allowLossyConversion);
635 return TypeConverter::AttributeConversionResult::abort();
636 return TypeConverter::AttributeConversionResult::result(
640 if constexpr (Kind == TosaNarrowKind::Int64ToInt32) {
641 typeConverter.addTypeAttributeConversion(
642 [allowLossyConversion](IntegerType , IntegerAttr attribute)
643 -> TypeConverter::AttributeConversionResult {
644 FailureOr<Attribute> converted =
645 tryConvertScalarAttribute<Kind>(attribute, allowLossyConversion);
647 return TypeConverter::AttributeConversionResult::abort();
648 return TypeConverter::AttributeConversionResult::result(
651 typeConverter.addTypeAttributeConversion(
652 [&typeConverter, allowLossyConversion](ShapedType type,
654 -> TypeConverter::AttributeConversionResult {
655 FailureOr<Attribute> converted = convertDenseIntElementsAttr<Kind>(
656 type, attr, typeConverter, allowLossyConversion);
658 return TypeConverter::AttributeConversionResult::abort();
659 return TypeConverter::AttributeConversionResult::result(
662 }
else if constexpr (Kind == TosaNarrowKind::Float64ToFloat32) {
663 typeConverter.addTypeAttributeConversion(
664 [allowLossyConversion](FloatType , FloatAttr attribute)
665 -> TypeConverter::AttributeConversionResult {
666 FailureOr<Attribute> converted =
667 tryConvertScalarAttribute<Kind>(attribute, allowLossyConversion);
669 return TypeConverter::AttributeConversionResult::abort();
670 return TypeConverter::AttributeConversionResult::result(
673 typeConverter.addTypeAttributeConversion(
674 [&typeConverter, allowLossyConversion](ShapedType type,
676 -> TypeConverter::AttributeConversionResult {
677 FailureOr<Attribute> converted = convertDenseFPElementsAttr<Kind>(
678 type, attr, typeConverter, allowLossyConversion);
680 return TypeConverter::AttributeConversionResult::abort();
681 return TypeConverter::AttributeConversionResult::result(
687 target.addDynamicallyLegalDialect<tosa::TosaDialect>(
692 if (convertFunctionBoundaries) {
693 target.addDynamicallyLegalOp<func::FuncOp>(
694 [&typeConverter](func::FuncOp op) {
695 return typeConverter.isSignatureLegal(op.getFunctionType()) &&
696 typeConverter.isLegal(&op.getBody());
698 target.addDynamicallyLegalOp<func::ReturnOp>([](func::ReturnOp op) {
699 const FunctionType funcType =
704 target.addDynamicallyLegalOp<func::FuncOp>(
705 [](func::FuncOp) {
return true; });
706 target.addDynamicallyLegalOp<func::ReturnOp>(
707 [](func::ReturnOp) {
return true; });
711 if (convertFunctionBoundaries) {
712 populateFunctionOpInterfaceTypeConversionPattern<func::FuncOp>(
713 patterns, typeConverter);
716 if (aggressiveRewrite) {
717 patterns.add<ConvertGenericOp<Kind>>(typeConverter, context,
718 allowLossyConversion);
720 if constexpr (Kind == TosaNarrowKind::Int64ToInt32) {
721 patterns.add<ConvertArgMaxOpWithBoundsChecking>(typeConverter, context);
722 patterns.add<ConvertClampOpWithBoundsChecking<Kind>>(typeConverter,
725 patterns.add<ConvertTypedOp<tosa::ConstOp, Kind>>(typeConverter, context);
726 patterns.add<ConvertTypedOp<tosa::ConcatOp, Kind>>(typeConverter, context);
727 patterns.add<ConvertTypedOp<tosa::PadOp, Kind>>(typeConverter, context);
728 patterns.add<ConvertTypedOp<tosa::ReshapeOp, Kind>>(typeConverter, context);
729 patterns.add<ConvertTypedOp<tosa::ReverseOp, Kind>>(typeConverter, context);
730 patterns.add<ConvertTypedOp<tosa::SliceOp, Kind>>(typeConverter, context);
731 patterns.add<ConvertTypedOp<tosa::TileOp, Kind>>(typeConverter, context);
732 patterns.add<ConvertTypedOp<tosa::TransposeOp, Kind>>(typeConverter,
734 patterns.add<ConvertTypedOp<tosa::IdentityOp, Kind>>(typeConverter,
736 patterns.add<ConvertCastOpWithBoundsChecking<Kind>>(typeConverter, context);
737 patterns.add<ConvertTypedOp<tosa::IfOp, Kind>>(typeConverter, context);
738 patterns.add<ConvertTypedOp<tosa::WhileOp, Kind>>(typeConverter, context);
739 patterns.add<ConvertTypedOp<tosa::YieldOp, Kind>>(typeConverter, context);
742 if (failed(applyFullConversion(op,
target, std::move(patterns))))
751struct TosaNarrowI64ToI32
755 TosaNarrowI64ToI32() =
default;
758 this->aggressiveRewrite =
options.aggressiveRewrite;
759 this->convertFunctionBoundaries =
options.convertFunctionBoundaries;
762 void runOnOperation()
override {
763 if (failed(runTosaNarrowing<TosaNarrowKind::Int64ToInt32>(
764 getOperation(), this->aggressiveRewrite,
765 this->convertFunctionBoundaries)))
770struct TosaNarrowF64ToF32
774 TosaNarrowF64ToF32() =
default;
777 this->aggressiveRewrite =
options.aggressiveRewrite;
778 this->convertFunctionBoundaries =
options.convertFunctionBoundaries;
781 void runOnOperation()
override {
782 if (failed(runTosaNarrowing<TosaNarrowKind::Float64ToFloat32>(
784 this->convertFunctionBoundaries)))
static llvm::Constant * convertDenseResourceElementsAttr(Location loc, DenseResourceElementsAttr denseResourceAttr, llvm::Type *llvmType, const ModuleTranslation &moduleTranslation)
Convert a dense resource elements attribute to an LLVM IR constant using its raw data storage if poss...
static llvm::ManagedStatic< PassManagerOptions > options
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
This class represents a processed binary blob of data.
Attributes are known-constant values of operations.
An attribute that represents a reference to a dense float vector or tensor object.
DenseElementsAttr mapValues(Type newElementType, function_ref< APInt(const APFloat &)> mapping) const
Generates a new DenseElementsAttr by mapping each value attribute, and constructing the DenseElements...
An attribute that represents a reference to a dense integer vector or tensor object.
DenseElementsAttr mapValues(Type newElementType, function_ref< APInt(const APInt &)> mapping) const
Generates a new DenseElementsAttr by mapping each value attribute, and constructing the DenseElements...
static AsmResourceBlob allocateAndCopyInferAlign(ArrayRef< T > data, bool dataIsMutable=true)
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.
NamedAttribute represents a combination of a name and an Attribute value.
This class helps build Operations.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
func::FuncOp getOperation()
Operation is the basic unit of execution within MLIR.
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this 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.
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
OperationName getName()
The name of an operation is the key identifier for it.
operand_type_range getOperandTypes()
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
result_type_range getResultTypes()
SuccessorRange getSuccessors()
result_range getResults()
MLIRContext * getContext()
Return the context this operation is associated with.
void signalPassFailure()
Signal that some invariant was broken when running.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
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.
TosaNarrowF64ToF32PassBase Base
Kind
An enumeration of the kinds of predicates.
Type getStorageElementTypeOrSelf(Type type)
std::optional< ArrayRef< T > > tryGetDenseResourceValues(ElementsAttr attr)
Include the generated interface declarations.
void populateReturnOpTypeConversionPattern(RewritePatternSet &patterns, const TypeConverter &converter, PatternBenefit benefit=1)
Add a pattern to the given pattern list to rewrite return ops to use operands that have been legalize...
static ManagerInterface & getManagerInterface(MLIRContext *ctx)
This represents an operation in an abstracted form, suitable for use with the builder APIs.