20 #include "llvm/ADT/APInt.h"
21 #include "llvm/Support/FormatVariadic.h"
22 #include "llvm/Support/MathExtras.h"
26 #define GEN_PASS_DEF_ARITHEMULATEWIDEINT
27 #include "mlir/Dialect/Arith/Transforms/Passes.h.inc"
40 static std::pair<APInt, APInt>
getHalves(
const APInt &value,
41 unsigned newBitWidth) {
42 APInt low = value.extractBits(newBitWidth, 0);
43 APInt high = value.extractBits(newBitWidth, newBitWidth);
44 return {std::move(low), std::move(high)};
53 if (type.getShape().size() == 1)
54 return type.getElementType();
56 auto newShape = to_vector(type.getShape());
66 if (dyn_cast<IntegerType>(type)) {
69 auto vecTy = cast<VectorType>(type);
73 return rewriter.
create<arith::ConstantOp>(loc, attr);
80 unsigned elementBitWidth = 0;
81 if (
auto intTy = dyn_cast<IntegerType>(type))
82 elementBitWidth = intTy.getWidth();
84 elementBitWidth = cast<VectorType>(type).getElementTypeBitWidth();
87 APInt(elementBitWidth, value));
99 assert(lastOffset < shape.back() &&
"Offset out of bounds");
102 if (shape.size() == 1)
103 return rewriter.
create<vector::ExtractOp>(loc, input, lastOffset);
106 offsets.back() = lastOffset;
107 auto sizes = llvm::to_vector(shape);
111 return rewriter.
create<vector::ExtractStridedSliceOp>(loc, input, offsets,
117 static std::pair<Value, Value>
128 auto vecTy = dyn_cast<VectorType>(input.
getType());
134 assert(shape.size() >= 2 &&
"Expected vector with at list two dims");
135 assert(shape.back() == 1 &&
"Expected the last vector dim to be x1");
137 auto newVecTy =
VectorType::get(shape.drop_back(), vecTy.getElementType());
138 return rewriter.
create<vector::ShapeCastOp>(loc, newVecTy, input);
145 auto vecTy = dyn_cast<VectorType>(input.
getType());
150 auto newShape = llvm::to_vector(vecTy.getShape());
151 newShape.push_back(1);
153 return rewriter.
create<vector::ShapeCastOp>(loc, newTy, input);
161 int64_t lastOffset) {
163 assert(lastOffset < shape.back() &&
"Offset out of bounds");
166 if (isa<IntegerType>(source.
getType()))
167 return rewriter.
create<vector::InsertOp>(loc, source, dest, lastOffset);
170 offsets.back() = lastOffset;
172 return rewriter.
create<vector::InsertStridedSliceOp>(loc, source, dest,
183 Location loc, VectorType resultType,
187 assert(!resultShape.empty() &&
"Result expected to have dimensions");
188 assert(resultShape.back() ==
static_cast<int64_t
>(resultComponents.size()) &&
189 "Wrong number of result components");
207 matchAndRewrite(arith::ConstantOp op, OpAdaptor,
209 Type oldType = op.getType();
210 auto newType = getTypeConverter()->convertType<VectorType>(oldType);
213 op, llvm::formatv(
"unsupported type: {0}", op.getType()));
215 unsigned newBitWidth = newType.getElementTypeBitWidth();
218 if (
auto intAttr = dyn_cast<IntegerAttr>(oldValue)) {
219 auto [low, high] =
getHalves(intAttr.getValue(), newBitWidth);
225 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(oldValue)) {
227 getHalves(splatAttr.getSplatValue<APInt>(), newBitWidth);
228 int64_t numSplatElems = splatAttr.getNumElements();
230 values.reserve(numSplatElems * 2);
231 for (int64_t i = 0; i < numSplatElems; ++i) {
232 values.push_back(low);
233 values.push_back(high);
241 if (
auto elemsAttr = dyn_cast<DenseElementsAttr>(oldValue)) {
242 int64_t numElems = elemsAttr.getNumElements();
244 values.reserve(numElems * 2);
245 for (
const APInt &origVal : elemsAttr.getValues<APInt>()) {
246 auto [low, high] =
getHalves(origVal, newBitWidth);
247 values.push_back(std::move(low));
248 values.push_back(std::move(high));
257 "unhandled constant attribute");
269 matchAndRewrite(arith::AddIOp op, OpAdaptor adaptor,
272 auto newTy = getTypeConverter()->convertType<VectorType>(op.getType());
275 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
279 auto [lhsElem0, lhsElem1] =
281 auto [rhsElem0, rhsElem1] =
285 rewriter.
create<arith::AddUIExtendedOp>(loc, lhsElem0, rhsElem0);
287 rewriter.
create<arith::ExtUIOp>(loc, newElemTy, lowSum.getOverflow());
289 Value high0 = rewriter.
create<arith::AddIOp>(loc, overflowVal, lhsElem1);
290 Value high = rewriter.
create<arith::AddIOp>(loc, high0, rhsElem1);
304 template <
typename BinaryOp>
310 matchAndRewrite(BinaryOp op, OpAdaptor adaptor,
313 auto newTy = this->getTypeConverter()->template convertType<VectorType>(
317 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
319 auto [lhsElem0, lhsElem1] =
321 auto [rhsElem0, rhsElem1] =
324 Value resElem0 = rewriter.
create<BinaryOp>(loc, lhsElem0, rhsElem0);
325 Value resElem1 = rewriter.
create<BinaryOp>(loc, lhsElem1, rhsElem1);
339 static arith::CmpIPredicate toUnsignedPredicate(arith::CmpIPredicate pred) {
340 using P = arith::CmpIPredicate;
359 matchAndRewrite(arith::CmpIOp op, OpAdaptor adaptor,
363 getTypeConverter()->convertType<VectorType>(op.getLhs().getType());
366 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
368 arith::CmpIPredicate highPred = adaptor.getPredicate();
369 arith::CmpIPredicate lowPred = toUnsignedPredicate(highPred);
371 auto [lhsElem0, lhsElem1] =
373 auto [rhsElem0, rhsElem1] =
377 rewriter.
create<arith::CmpIOp>(loc, lowPred, lhsElem0, rhsElem0);
379 rewriter.
create<arith::CmpIOp>(loc, highPred, lhsElem1, rhsElem1);
383 case arith::CmpIPredicate::eq: {
384 cmpResult = rewriter.
create<arith::AndIOp>(loc, lowCmp, highCmp);
387 case arith::CmpIPredicate::ne: {
388 cmpResult = rewriter.
create<arith::OrIOp>(loc, lowCmp, highCmp);
394 loc, arith::CmpIPredicate::eq, lhsElem1, rhsElem1);
396 rewriter.
create<arith::SelectOp>(loc, highEq, lowCmp, highCmp);
401 assert(cmpResult &&
"Unhandled case");
415 matchAndRewrite(arith::MulIOp op, OpAdaptor adaptor,
418 auto newTy = getTypeConverter()->convertType<VectorType>(op.getType());
421 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
423 auto [lhsElem0, lhsElem1] =
425 auto [rhsElem0, rhsElem1] =
432 rewriter.
create<arith::MulUIExtendedOp>(loc, lhsElem0, rhsElem0);
433 Value mulLowHi = rewriter.
create<arith::MulIOp>(loc, lhsElem0, rhsElem1);
434 Value mulHiLow = rewriter.
create<arith::MulIOp>(loc, lhsElem1, rhsElem0);
436 Value resLow = mulLowLow.getLow();
438 rewriter.
create<arith::AddIOp>(loc, mulLowLow.getHigh(), mulLowHi);
439 resHi = rewriter.
create<arith::AddIOp>(loc, resHi, mulHiLow);
456 matchAndRewrite(arith::ExtSIOp op, OpAdaptor adaptor,
459 auto newTy = getTypeConverter()->convertType<VectorType>(op.getType());
462 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
471 loc, newResultComponentTy, newOperand);
472 Value operandZeroCst =
475 loc, arith::CmpIPredicate::slt, extended, operandZeroCst);
477 rewriter.
create<arith::ExtSIOp>(loc, newResultComponentTy, signBit);
494 matchAndRewrite(arith::ExtUIOp op, OpAdaptor adaptor,
497 auto newTy = getTypeConverter()->convertType<VectorType>(op.getType());
500 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
508 loc, newResultComponentTy, newOperand);
520 template <
typename SourceOp, arith::CmpIPredicate CmpPred>
525 matchAndRewrite(SourceOp op,
typename SourceOp::Adaptor adaptor,
529 Type oldTy = op.getType();
530 auto newTy = dyn_cast_or_null<VectorType>(
531 this->getTypeConverter()->convertType(oldTy));
534 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
539 rewriter.
create<arith::CmpIOp>(loc, CmpPred, op.getLhs(), op.getRhs());
550 static bool isIndexOrIndexVector(
Type type) {
551 if (isa<IndexType>(type))
554 if (
auto vectorTy = dyn_cast<VectorType>(type))
555 if (isa<IndexType>(vectorTy.getElementType()))
561 template <
typename CastOp>
566 matchAndRewrite(CastOp op,
typename CastOp::Adaptor adaptor,
568 Type resultType = op.getType();
569 if (!isIndexOrIndexVector(resultType))
573 Type inType = op.getIn().getType();
575 this->getTypeConverter()->template convertType<VectorType>(inType);
578 loc, llvm::formatv(
"unsupported type: {0}", inType));
588 template <
typename CastOp,
typename ExtensionOp>
593 matchAndRewrite(CastOp op,
typename CastOp::Adaptor adaptor,
595 Type inType = op.getIn().getType();
596 if (!isIndexOrIndexVector(inType))
600 auto *typeConverter =
601 this->
template getTypeConverter<arith::WideIntEmulationConverter>();
603 Type resultType = op.getType();
604 auto newTy = typeConverter->template convertType<VectorType>(resultType);
607 loc, llvm::formatv(
"unsupported type: {0}", resultType));
611 rewriter.
getIntegerType(typeConverter->getMaxTargetIntBitWidth());
612 if (
auto vecTy = dyn_cast<VectorType>(resultType))
617 Value underlyingVal =
618 rewriter.
create<CastOp>(loc, narrowTy, adaptor.getIn());
632 matchAndRewrite(arith::SelectOp op, OpAdaptor adaptor,
635 auto newTy = getTypeConverter()->convertType<VectorType>(op.getType());
638 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
640 auto [trueElem0, trueElem1] =
642 auto [falseElem0, falseElem1] =
647 rewriter.
create<arith::SelectOp>(loc, cond, trueElem0, falseElem0);
649 rewriter.
create<arith::SelectOp>(loc, cond, trueElem1, falseElem1);
665 matchAndRewrite(arith::ShLIOp op, OpAdaptor adaptor,
669 Type oldTy = op.getType();
670 auto newTy = getTypeConverter()->convertType<VectorType>(oldTy);
673 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
677 unsigned newBitWidth = newTy.getElementTypeBitWidth();
679 auto [lhsElem0, lhsElem1] =
711 Value illegalElemShift = rewriter.
create<arith::CmpIOp>(
712 loc, arith::CmpIPredicate::uge, rhsElem0, elemBitWidth);
715 rewriter.
create<arith::ShLIOp>(loc, lhsElem0, rhsElem0);
716 Value resElem0 = rewriter.
create<arith::SelectOp>(loc, illegalElemShift,
717 zeroCst, shiftedElem0);
719 Value cappedShiftAmount = rewriter.
create<arith::SelectOp>(
720 loc, illegalElemShift, elemBitWidth, rhsElem0);
721 Value rightShiftAmount =
722 rewriter.
create<arith::SubIOp>(loc, elemBitWidth, cappedShiftAmount);
724 rewriter.
create<arith::ShRUIOp>(loc, lhsElem0, rightShiftAmount);
725 Value overshotShiftAmount =
726 rewriter.
create<arith::SubIOp>(loc, rhsElem0, elemBitWidth);
728 rewriter.
create<arith::ShLIOp>(loc, lhsElem0, overshotShiftAmount);
731 rewriter.
create<arith::ShLIOp>(loc, lhsElem1, rhsElem0);
732 Value resElem1High = rewriter.
create<arith::SelectOp>(
733 loc, illegalElemShift, zeroCst, shiftedElem1);
734 Value resElem1Low = rewriter.
create<arith::SelectOp>(
735 loc, illegalElemShift, shiftedLeft, shiftedRight);
737 rewriter.
create<arith::OrIOp>(loc, resElem1Low, resElem1High);
754 matchAndRewrite(arith::ShRUIOp op, OpAdaptor adaptor,
758 Type oldTy = op.getType();
759 auto newTy = getTypeConverter()->convertType<VectorType>(oldTy);
762 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
766 unsigned newBitWidth = newTy.getElementTypeBitWidth();
768 auto [lhsElem0, lhsElem1] =
800 Value illegalElemShift = rewriter.
create<arith::CmpIOp>(
801 loc, arith::CmpIPredicate::uge, rhsElem0, elemBitWidth);
804 rewriter.
create<arith::ShRUIOp>(loc, lhsElem0, rhsElem0);
805 Value resElem0Low = rewriter.
create<arith::SelectOp>(loc, illegalElemShift,
806 zeroCst, shiftedElem0);
808 rewriter.
create<arith::ShRUIOp>(loc, lhsElem1, rhsElem0);
809 Value resElem1 = rewriter.
create<arith::SelectOp>(loc, illegalElemShift,
810 zeroCst, shiftedElem1);
812 Value cappedShiftAmount = rewriter.
create<arith::SelectOp>(
813 loc, illegalElemShift, elemBitWidth, rhsElem0);
814 Value leftShiftAmount =
815 rewriter.
create<arith::SubIOp>(loc, elemBitWidth, cappedShiftAmount);
817 rewriter.
create<arith::ShLIOp>(loc, lhsElem1, leftShiftAmount);
818 Value overshotShiftAmount =
819 rewriter.
create<arith::SubIOp>(loc, rhsElem0, elemBitWidth);
821 rewriter.
create<arith::ShRUIOp>(loc, lhsElem1, overshotShiftAmount);
823 Value resElem0High = rewriter.
create<arith::SelectOp>(
824 loc, illegalElemShift, shiftedRight, shiftedLeft);
826 rewriter.
create<arith::OrIOp>(loc, resElem0Low, resElem0High);
843 matchAndRewrite(arith::ShRSIOp op, OpAdaptor adaptor,
847 Type oldTy = op.getType();
848 auto newTy = getTypeConverter()->convertType<VectorType>(oldTy);
851 loc, llvm::formatv(
"unsupported type: {0}", op.getType()));
857 int64_t origBitwidth = newTy.getElementTypeBitWidth() * 2;
864 loc, arith::CmpIPredicate::slt, lhsElem1, elemZero);
870 Value allSign = rewriter.
create<arith::ExtSIOp>(loc, oldTy, signBit);
873 Value numNonSignExtBits =
874 rewriter.
create<arith::SubIOp>(loc, maxShift, rhsElem0);
877 rewriter.
create<arith::ExtUIOp>(loc, oldTy, numNonSignExtBits);
879 rewriter.
create<arith::ShLIOp>(loc, allSign, numNonSignExtBits);
883 rewriter.
create<arith::ShRUIOp>(loc, op.getLhs(), op.getRhs());
884 Value shrsi = rewriter.
create<arith::OrIOp>(loc, shrui, signBits);
888 Value isNoop = rewriter.
create<arith::CmpIOp>(loc, arith::CmpIPredicate::eq,
906 matchAndRewrite(arith::SIToFPOp op, OpAdaptor adaptor,
910 Value in = op.getIn();
912 auto newTy = getTypeConverter()->convertType<VectorType>(oldTy);
915 loc, llvm::formatv(
"unsupported type: {0}", oldTy));
921 rewriter, loc, oldTy, APInt::getAllOnes(oldBitWidth));
929 Value isNeg = rewriter.
create<arith::CmpIOp>(loc, arith::CmpIPredicate::slt,
931 Value bitwiseNeg = rewriter.
create<arith::XOrIOp>(loc, in, allOnesCst);
932 Value neg = rewriter.
create<arith::AddIOp>(loc, bitwiseNeg, oneCst);
933 Value abs = rewriter.
create<arith::SelectOp>(loc, isNeg, neg, in);
935 Value absResult = rewriter.
create<arith::UIToFPOp>(loc, op.getType(),
abs);
936 Value negResult = rewriter.
create<arith::NegFOp>(loc, absResult);
951 matchAndRewrite(arith::UIToFPOp op, OpAdaptor adaptor,
955 Type oldTy = op.getIn().getType();
956 auto newTy = getTypeConverter()->convertType<VectorType>(oldTy);
959 loc, llvm::formatv(
"unsupported type: {0}", oldTy));
960 unsigned newBitWidth = newTy.getElementTypeBitWidth();
983 loc, arith::CmpIPredicate::eq, hiInt, zeroCst);
985 Type resultTy = op.getType();
987 Value lowFp = rewriter.
create<arith::UIToFPOp>(loc, resultTy, lowInt);
988 Value hiFp = rewriter.
create<arith::UIToFPOp>(loc, resultTy, hiInt);
990 int64_t pow2Int = int64_t(1) << newBitWidth;
992 rewriter.
getFloatAttr(resultElemTy,
static_cast<double>(pow2Int));
993 if (
auto vecTy = dyn_cast<VectorType>(resultTy))
996 Value pow2Val = rewriter.
create<arith::ConstantOp>(loc, resultTy, pow2Attr);
998 Value hiVal = rewriter.
create<arith::MulFOp>(loc, hiFp, pow2Val);
999 Value result = rewriter.
create<arith::AddFOp>(loc, lowFp, hiVal);
1014 matchAndRewrite(arith::TruncIOp op, OpAdaptor adaptor,
1019 if (!getTypeConverter()->isLegal(op.getType()))
1021 loc, llvm::formatv(
"unsupported truncation result type: {0}",
1029 rewriter.
createOrFold<arith::TruncIOp>(loc, op.getType(), extracted);
1043 matchAndRewrite(vector::PrintOp op, OpAdaptor adaptor,
1054 struct EmulateWideIntPass final
1055 : arith::impl::ArithEmulateWideIntBase<EmulateWideIntPass> {
1056 using ArithEmulateWideIntBase::ArithEmulateWideIntBase;
1058 void runOnOperation()
override {
1059 if (!llvm::isPowerOf2_32(widestIntSupported) || widestIntSupported < 2) {
1060 signalPassFailure();
1067 arith::WideIntEmulationConverter typeConverter(widestIntSupported);
1069 target.addDynamicallyLegalOp<func::FuncOp>([&typeConverter](
Operation *op) {
1070 return typeConverter.isLegal(cast<func::FuncOp>(op).getFunctionType());
1072 auto opLegalCallback = [&typeConverter](
Operation *op) {
1073 return typeConverter.isLegal(op);
1075 target.addDynamicallyLegalOp<func::CallOp, func::ReturnOp>(opLegalCallback);
1077 .addDynamicallyLegalDialect<arith::ArithDialect, vector::VectorDialect>(
1084 signalPassFailure();
1094 unsigned widestIntSupportedByTarget)
1095 : maxIntWidth(widestIntSupportedByTarget) {
1096 assert(llvm::isPowerOf2_32(widestIntSupportedByTarget) &&
1097 "Only power-of-two integers with are supported");
1098 assert(widestIntSupportedByTarget >= 2 &&
"Integer type too narrow");
1104 addConversion([
this](IntegerType ty) -> std::optional<Type> {
1105 unsigned width = ty.getWidth();
1106 if (width <= maxIntWidth)
1110 if (width == 2 * maxIntWidth)
1113 return std::nullopt;
1117 addConversion([
this](VectorType ty) -> std::optional<Type> {
1118 auto intTy = dyn_cast<IntegerType>(ty.getElementType());
1122 unsigned width = intTy.getWidth();
1123 if (width <= maxIntWidth)
1127 if (width == 2 * maxIntWidth) {
1128 auto newShape = to_vector(ty.getShape());
1129 newShape.push_back(2);
1134 return std::nullopt;
1138 addConversion([
this](FunctionType ty) -> std::optional<Type> {
1143 return std::nullopt;
1147 return std::nullopt;
1156 populateFunctionOpInterfaceTypeConversionPattern<func::FuncOp>(patterns,
1164 ConvertConstant, ConvertCmpI, ConvertSelect, ConvertVectorPrint,
1166 ConvertAddI, ConvertMulI, ConvertShLI, ConvertShRSI, ConvertShRUI,
1167 ConvertMaxMin<arith::MaxUIOp, arith::CmpIPredicate::ugt>,
1168 ConvertMaxMin<arith::MaxSIOp, arith::CmpIPredicate::sgt>,
1169 ConvertMaxMin<arith::MinUIOp, arith::CmpIPredicate::ult>,
1170 ConvertMaxMin<arith::MinSIOp, arith::CmpIPredicate::slt>,
1172 ConvertBitwiseBinary<arith::AndIOp>, ConvertBitwiseBinary<arith::OrIOp>,
1173 ConvertBitwiseBinary<arith::XOrIOp>,
1175 ConvertExtSI, ConvertExtUI, ConvertTruncI,
1177 ConvertIndexCastIntToIndex<arith::IndexCastOp>,
1178 ConvertIndexCastIntToIndex<arith::IndexCastUIOp>,
1179 ConvertIndexCastIndexToInt<arith::IndexCastOp, arith::ExtSIOp>,
1180 ConvertIndexCastIndexToInt<arith::IndexCastUIOp, arith::ExtUIOp>,
1181 ConvertSIToFP, ConvertUIToFP>(typeConverter, patterns.
getContext());
Attributes are known-constant values of operations.
IntegerAttr getIntegerAttr(Type type, int64_t value)
FloatAttr getFloatAttr(Type type, double value)
IntegerType getIntegerType(unsigned width)
This class implements a pattern rewriter for use with ConversionPatterns.
void replaceOp(Operation *op, ValueRange newValues) override
PatternRewriter hook for replacing an operation.
LogicalResult notifyMatchFailure(Location loc, function_ref< void(Diagnostic &)> reasonCallback) override
PatternRewriter hook for notifying match failure reasons.
This class describes a specific conversion target.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
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.
void createOrFold(SmallVectorImpl< Value > &results, Location location, Args &&...args)
Create an operation of specific op type at the current insertion point, and immediately try to fold i...
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...
typename SourceOp::Adaptor OpAdaptor
OpConversionPattern(MLIRContext *context, PatternBenefit benefit=1)
Operation is the basic unit of execution within MLIR.
MLIRContext * getContext()
Return the context this operation is associated with.
Location getLoc()
The source location the operation was defined or derived from.
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.
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replaces the result op with a new op that is created without verification.
void addConversion(FnT &&callback)
Register a conversion function.
LogicalResult convertTypes(TypeRange types, SmallVectorImpl< Type > &results) const
Convert the given set of types, filling 'results' as necessary.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
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.
Converts integer types that are too wide for the target by splitting them in two halves and thus turn...
WideIntEmulationConverter(unsigned widestIntSupportedByTarget)
void populateArithWideIntEmulationPatterns(WideIntEmulationConverter &typeConverter, RewritePatternSet &patterns)
Adds patterns to emulate wide Arith and Function ops over integer types into supported ones.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt abs(const MPInt &x)
This header declares functions that assist transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
void populateCallOpTypeConversionPattern(RewritePatternSet &patterns, TypeConverter &converter)
Add a pattern to the given pattern list to convert the operand and result types of a CallOp with the ...
void populateReturnOpTypeConversionPattern(RewritePatternSet &patterns, TypeConverter &converter)
Add a pattern to the given pattern list to rewrite return ops to use operands that have been legalize...
LogicalResult applyPartialConversion(ArrayRef< Operation * > ops, const ConversionTarget &target, const FrozenRewritePatternSet &patterns, DenseSet< Operation * > *unconvertedOps=nullptr)
Below we define several entry points for operation conversion.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.