27#define GEN_PASS_DEF_ARITHTOLLVMCONVERSIONPASS
28#include "mlir/Conversion/Passes.h.inc"
48template <
typename SourceOp,
typename TargetOp,
bool HasRoundingMode,
49 template <
typename,
typename>
typename AttrConvert =
51 bool FailOnUnsupportedFP =
false>
52struct ConstrainedVectorConvertToLLVMPattern
54 FailOnUnsupportedFP> {
55 using VectorConvertToLLVMPattern<
56 SourceOp, TargetOp, AttrConvert,
57 FailOnUnsupportedFP>::VectorConvertToLLVMPattern;
60 matchAndRewrite(SourceOp op,
typename SourceOp::Adaptor adaptor,
61 ConversionPatternRewriter &rewriter)
const override {
62 if (HasRoundingMode !=
static_cast<bool>(op.getRoundingModeAttr()))
64 return VectorConvertToLLVMPattern<
65 SourceOp, TargetOp, AttrConvert,
66 FailOnUnsupportedFP>::matchAndRewrite(op, adaptor, rewriter);
72struct IdentityBitcastLowering final
73 :
public OpConversionPattern<arith::BitcastOp> {
77 matchAndRewrite(arith::BitcastOp op, OpAdaptor adaptor,
78 ConversionPatternRewriter &rewriter)
const final {
79 Value src = adaptor.getIn();
80 Type resultType = getTypeConverter()->convertType(op.getType());
81 if (src.
getType() != resultType)
82 return rewriter.notifyMatchFailure(op,
"Types are different");
84 rewriter.replaceOp(op, src);
94 ConstrainedVectorConvertToLLVMPattern<arith::AddFOp, LLVM::FAddOp,
98using ConstrainedAddFOpLowering = ConstrainedVectorConvertToLLVMPattern<
99 arith::AddFOp, LLVM::ConstrainedFAddIntr,
true,
101using AddIOpLowering =
105using BitcastOpLowering =
107using DivFOpLowering =
108 ConstrainedVectorConvertToLLVMPattern<arith::DivFOp, LLVM::FDivOp,
112using ConstrainedDivFOpLowering = ConstrainedVectorConvertToLLVMPattern<
113 arith::DivFOp, LLVM::ConstrainedFDivIntr,
true,
115using DivSIOpLowering =
117using DivUIOpLowering =
119using ExtFOpLowering =
123using ExtSIOpLowering =
125using ExtUIOpLowering =
128using FPToSIOpLowering =
132using FPToUIOpLowering =
136using MaximumFOpLowering =
140using MaxNumFOpLowering =
144using MaximumNumFOpLowering =
148using MaxSIOpLowering =
150using MaxUIOpLowering =
152using MinimumFOpLowering =
156using MinNumFOpLowering =
160using MinimumNumFOpLowering =
164using MinSIOpLowering =
166using MinUIOpLowering =
168using MulFOpLowering =
169 ConstrainedVectorConvertToLLVMPattern<arith::MulFOp, LLVM::FMulOp,
173using ConstrainedMulFOpLowering = ConstrainedVectorConvertToLLVMPattern<
174 arith::MulFOp, LLVM::ConstrainedFMulIntr,
true,
176using MulIOpLowering =
179using NegFOpLowering =
184using RemFOpLowering =
188using RemSIOpLowering =
190using RemUIOpLowering =
192using SelectOpLowering =
194using ShLIOpLowering =
197using ShRSIOpLowering =
199using ShRUIOpLowering =
201using SIToFPOpLowering =
205using SubFOpLowering =
206 ConstrainedVectorConvertToLLVMPattern<arith::SubFOp, LLVM::FSubOp,
210using ConstrainedSubFOpLowering = ConstrainedVectorConvertToLLVMPattern<
211 arith::SubFOp, LLVM::ConstrainedFSubIntr,
true,
213using SubIOpLowering =
216using TruncFOpLowering =
217 ConstrainedVectorConvertToLLVMPattern<arith::TruncFOp, LLVM::FPTruncOp,
221using ConstrainedTruncFOpLowering = ConstrainedVectorConvertToLLVMPattern<
222 arith::TruncFOp, LLVM::ConstrainedFPTruncIntr,
true,
224using TruncIOpLowering =
227using UIToFPOpLowering =
242 matchAndRewrite(arith::ConstantOp op, OpAdaptor adaptor,
243 ConversionPatternRewriter &rewriter)
const override;
250template <
typename OpTy,
typename ExtCastTy>
252 using ConvertOpToLLVMPattern<OpTy>::ConvertOpToLLVMPattern;
255 matchAndRewrite(OpTy op,
typename OpTy::Adaptor adaptor,
256 ConversionPatternRewriter &rewriter)
const override;
259using IndexCastOpSILowering =
260 IndexCastOpLowering<arith::IndexCastOp, LLVM::SExtOp>;
261using IndexCastOpUILowering =
262 IndexCastOpLowering<arith::IndexCastUIOp, LLVM::ZExtOp>;
264struct AddUIExtendedOpLowering
269 matchAndRewrite(arith::AddUIExtendedOp op, OpAdaptor adaptor,
270 ConversionPatternRewriter &rewriter)
const override;
273struct SubUIExtendedOpLowering
278 matchAndRewrite(arith::SubUIExtendedOp op, OpAdaptor adaptor,
279 ConversionPatternRewriter &rewriter)
const override;
282template <
typename ArithMulOp,
bool IsSigned>
284 using ConvertOpToLLVMPattern<ArithMulOp>::ConvertOpToLLVMPattern;
287 matchAndRewrite(ArithMulOp op,
typename ArithMulOp::Adaptor adaptor,
288 ConversionPatternRewriter &rewriter)
const override;
291using MulSIExtendedOpLowering =
292 MulIExtendedOpLowering<arith::MulSIExtendedOp, true>;
293using MulUIExtendedOpLowering =
294 MulIExtendedOpLowering<arith::MulUIExtendedOp, false>;
300 matchAndRewrite(arith::CmpIOp op, OpAdaptor adaptor,
301 ConversionPatternRewriter &rewriter)
const override;
308 matchAndRewrite(arith::CmpFOp op, OpAdaptor adaptor,
309 ConversionPatternRewriter &rewriter)
const override;
321 matchAndRewrite(arith::ConvertFOp op, OpAdaptor adaptor,
322 ConversionPatternRewriter &rewriter)
const override {
324 *getTypeConverter()))
325 return rewriter.notifyMatchFailure(op,
"unsupported floating point type");
331 assert(((srcType.isBF16() && dstType.isF16()) ||
332 (srcType.isF16() && dstType.isBF16())) &&
333 "only bf16 <-> f16 conversions are supported");
335 Type convertedType = getTypeConverter()->convertType(op.getType());
337 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
339 Value input = adaptor.getIn();
340 Location loc = op.getLoc();
342 if (!isa<LLVM::LLVMArrayType>(input.
getType())) {
343 rewriter.replaceOp(op,
344 emitConversion(rewriter, loc, input, convertedType));
348 if (!isa<VectorType>(op.getType()))
349 return rewriter.notifyMatchFailure(op,
"expected vector result type");
352 op.getOperation(), adaptor.getOperands(), *getTypeConverter(),
353 [&](Type llvm1DVectorTy,
ValueRange operands) -> Value {
354 return emitConversion(rewriter, loc, operands.front(),
361 static Value emitConversion(ConversionPatternRewriter &rewriter, Location loc,
362 Value input, Type targetType) {
363 Type f32Scalar = Float32Type::get(rewriter.getContext());
364 Type f32Ty = f32Scalar;
365 if (
auto vecTy = dyn_cast<VectorType>(targetType))
366 f32Ty = VectorType::get(vecTy.getShape(), f32Scalar);
368 Value ext = LLVM::FPExtOp::create(rewriter, loc, f32Ty, input);
369 return LLVM::FPTruncOp::create(rewriter, loc, targetType, ext);
378 matchAndRewrite(arith::SelectOp op, Adaptor adaptor,
379 ConversionPatternRewriter &rewriter)
const override;
401 if (sourceElementType == targetElementType)
404 auto targetIntType = dyn_cast<IntegerType>(targetElementType);
411 if (
auto sourceFloatType = dyn_cast<FloatType>(sourceElementType)) {
412 if (sourceFloatType.getWidth() != targetIntType.getWidth())
421 if (!isa<IndexType>(sourceElementType))
425 unsigned width = targetIntType.getWidth();
427 if (
auto intAttr = dyn_cast<IntegerAttr>(attr))
428 return IntegerAttr::get(targetIntType,
429 intAttr.getValue().sextOrTrunc(width));
432 return values.mapValues(targetIntType, [&](
const APInt &value) {
433 return value.sextOrTrunc(width);
437 if (
auto denseAttr = dyn_cast<DenseIntElementsAttr>(attr))
438 return retypeValues(denseAttr);
440 if (
auto sparseAttr = dyn_cast<SparseElementsAttr>(attr))
441 return SparseElementsAttr::get(
442 cast<ShapedType>(attr.getType()).clone(targetIntType),
443 sparseAttr.getIndices(),
444 retypeValues(cast<DenseIntElementsAttr>(sparseAttr.getValues())));
450 if (
auto resourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
451 if (width != IndexType::kInternalStorageBitWidth)
453 return DenseResourceElementsAttr::get(
454 cast<ShapedType>(attr.getType()).clone(targetIntType),
455 resourceAttr.getRawHandle());
462ConstantOpLowering::matchAndRewrite(arith::ConstantOp op, OpAdaptor adaptor,
463 ConversionPatternRewriter &rewriter)
const {
464 Type resultType = getTypeConverter()->convertType(op.getType());
466 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
470 return rewriter.notifyMatchFailure(
471 op,
"failed to convert value attribute to the converted result type");
476 DictionaryAttr discardableAttrs = op->getDiscardableAttrDictionary();
478 LLVM::ConstantOp::create(rewriter, op.getLoc(), resultType, value);
479 constantOp->setDiscardableAttrs(discardableAttrs);
480 rewriter.replaceOp(op, constantOp);
488template <
typename OpTy,
typename ExtCastTy>
489LogicalResult IndexCastOpLowering<OpTy, ExtCastTy>::matchAndRewrite(
490 OpTy op,
typename OpTy::Adaptor adaptor,
491 ConversionPatternRewriter &rewriter)
const {
492 Type resultType = op.getResult().getType();
493 Type targetElementType =
495 Type sourceElementType =
500 if (targetBits == sourceBits) {
501 rewriter.replaceOp(op, adaptor.getIn());
508 if (isa<MemRefType>(op.getIn().getType())) {
509 rewriter.replaceOp(op, adaptor.getIn());
513 bool isNonNeg =
false;
514 if constexpr (std::is_same_v<ExtCastTy, LLVM::ZExtOp>)
515 isNonNeg = op.getNonNeg();
518 Type operandType = adaptor.getIn().getType();
519 if (!isa<LLVM::LLVMArrayType>(operandType)) {
520 Type targetType = this->typeConverter->convertType(resultType);
521 if (targetBits < sourceBits) {
522 rewriter.replaceOpWithNewOp<LLVM::TruncOp>(op, targetType,
525 auto extOp = rewriter.replaceOpWithNewOp<ExtCastTy>(op, targetType,
527 if constexpr (std::is_same_v<ExtCastTy, LLVM::ZExtOp>)
528 extOp.setNonNeg(isNonNeg);
533 if (!isa<VectorType>(resultType))
534 return rewriter.notifyMatchFailure(op,
"expected vector result type");
537 op.getOperation(), adaptor.getOperands(), *(this->getTypeConverter()),
538 [&](Type llvm1DVectorTy,
ValueRange operands) -> Value {
539 typename OpTy::Adaptor adaptor(operands);
540 if (targetBits < sourceBits) {
541 return LLVM::TruncOp::create(rewriter, op.getLoc(), llvm1DVectorTy,
544 auto extOp = ExtCastTy::create(rewriter, op.getLoc(), llvm1DVectorTy,
546 if constexpr (std::is_same_v<ExtCastTy, LLVM::ZExtOp>) {
548 extOp.setNonNeg(
true);
559LogicalResult AddUIExtendedOpLowering::matchAndRewrite(
560 arith::AddUIExtendedOp op, OpAdaptor adaptor,
561 ConversionPatternRewriter &rewriter)
const {
562 Type operandType = adaptor.getLhs().getType();
563 Type sumResultType = op.getSum().getType();
564 Type overflowResultType = op.getOverflow().getType();
569 MLIRContext *ctx = rewriter.getContext();
570 Location loc = op.getLoc();
573 if (!isa<LLVM::LLVMArrayType>(operandType)) {
574 Type newSumType = typeConverter->convertType(sumResultType);
575 Type newOverflowType = typeConverter->convertType(overflowResultType);
577 LLVM::LLVMStructType::getLiteral(ctx, {newSumType, newOverflowType});
578 Value addOverflow = LLVM::UAddWithOverflowOp::create(
579 rewriter, loc, structType, adaptor.getLhs(), adaptor.getRhs());
581 LLVM::ExtractValueOp::create(rewriter, loc, addOverflow, 0);
582 Value overflowExtracted =
583 LLVM::ExtractValueOp::create(rewriter, loc, addOverflow, 1);
584 rewriter.replaceOp(op, {sumExtracted, overflowExtracted});
588 if (!isa<VectorType>(sumResultType))
589 return rewriter.notifyMatchFailure(loc,
"expected vector result types");
591 return rewriter.notifyMatchFailure(loc,
592 "ND vector types are not supported yet");
599LogicalResult SubUIExtendedOpLowering::matchAndRewrite(
600 arith::SubUIExtendedOp op, OpAdaptor adaptor,
601 ConversionPatternRewriter &rewriter)
const {
602 Type operandType = adaptor.getLhs().getType();
603 Type diffResultType = op.getDiff().getType();
604 Type borrowResultType = op.getBorrow().getType();
609 MLIRContext *ctx = rewriter.getContext();
610 Location loc = op.getLoc();
613 if (!isa<LLVM::LLVMArrayType>(operandType)) {
614 Type newBorrowType = typeConverter->convertType(borrowResultType);
616 LLVM::LLVMStructType::getLiteral(ctx, {diffResultType, newBorrowType});
617 Value subOverflow = LLVM::USubWithOverflowOp::create(
618 rewriter, loc, structType, adaptor.getLhs(), adaptor.getRhs());
619 Value diffExtracted =
620 LLVM::ExtractValueOp::create(rewriter, loc, subOverflow, 0);
621 Value borrowExtracted =
622 LLVM::ExtractValueOp::create(rewriter, loc, subOverflow, 1);
623 rewriter.replaceOp(op, {diffExtracted, borrowExtracted});
627 if (!isa<VectorType>(diffResultType))
628 return rewriter.notifyMatchFailure(loc,
"expected vector result types");
630 return rewriter.notifyMatchFailure(loc,
631 "ND vector types are not supported yet");
638template <
typename ArithMulOp,
bool IsSigned>
639LogicalResult MulIExtendedOpLowering<ArithMulOp, IsSigned>::matchAndRewrite(
640 ArithMulOp op,
typename ArithMulOp::Adaptor adaptor,
641 ConversionPatternRewriter &rewriter)
const {
642 Type resultType = adaptor.getLhs().getType();
647 Location loc = op.getLoc();
653 if (!isa<LLVM::LLVMArrayType>(resultType)) {
655 TypedAttr shiftValAttr;
657 if (
auto intTy = dyn_cast<IntegerType>(resultType)) {
658 unsigned resultBitwidth = intTy.getWidth();
659 auto attrTy = rewriter.getIntegerType(resultBitwidth * 2);
660 shiftValAttr = rewriter.getIntegerAttr(attrTy, resultBitwidth);
662 auto vecTy = cast<VectorType>(resultType);
663 unsigned resultBitwidth = vecTy.getElementTypeBitWidth();
664 auto attrTy = VectorType::get(
665 vecTy.getShape(), rewriter.getIntegerType(resultBitwidth * 2));
666 shiftValAttr = SplatElementsAttr::get(
667 attrTy, APInt(resultBitwidth * 2, resultBitwidth));
669 Type wideType = shiftValAttr.getType();
671 "LLVM dialect should support all signless integer types");
673 using LLVMExtOp = std::conditional_t<IsSigned, LLVM::SExtOp, LLVM::ZExtOp>;
674 Value lhsExt = LLVMExtOp::create(rewriter, loc, wideType, adaptor.getLhs());
675 Value rhsExt = LLVMExtOp::create(rewriter, loc, wideType, adaptor.getRhs());
676 Value mulExt = LLVM::MulOp::create(rewriter, loc, wideType, lhsExt, rhsExt);
679 Value low = LLVM::TruncOp::create(rewriter, loc, resultType, mulExt);
680 Value shiftVal = LLVM::ConstantOp::create(rewriter, loc, shiftValAttr);
681 Value highExt = LLVM::LShrOp::create(rewriter, loc, mulExt, shiftVal);
682 Value high = LLVM::TruncOp::create(rewriter, loc, resultType, highExt);
684 rewriter.replaceOp(op, {low, high});
688 if (!isa<VectorType>(resultType))
689 return rewriter.notifyMatchFailure(op,
"expected vector result type");
691 return rewriter.notifyMatchFailure(op,
692 "ND vector types are not supported yet");
701template <
typename LLVMPredType,
typename PredType>
703 return static_cast<LLVMPredType
>(pred);
707CmpIOpLowering::matchAndRewrite(arith::CmpIOp op, OpAdaptor adaptor,
708 ConversionPatternRewriter &rewriter)
const {
709 Type operandType = adaptor.getLhs().getType();
710 Type resultType = op.getResult().getType();
713 if (!isa<LLVM::LLVMArrayType>(operandType)) {
714 rewriter.replaceOpWithNewOp<LLVM::ICmpOp>(
715 op, typeConverter->convertType(resultType),
717 adaptor.getLhs(), adaptor.getRhs());
721 if (!isa<VectorType>(resultType))
722 return rewriter.notifyMatchFailure(op,
"expected vector result type");
725 op.getOperation(), adaptor.getOperands(), *getTypeConverter(),
726 [&](Type llvm1DVectorTy,
ValueRange operands) {
727 OpAdaptor adaptor(operands);
728 return LLVM::ICmpOp::create(
729 rewriter, op.getLoc(), llvm1DVectorTy,
731 adaptor.getLhs(), adaptor.getRhs());
741CmpFOpLowering::matchAndRewrite(arith::CmpFOp op, OpAdaptor adaptor,
742 ConversionPatternRewriter &rewriter)
const {
744 op.getLhs().getType()))
745 return rewriter.notifyMatchFailure(op,
"unsupported floating point type");
747 Type operandType = adaptor.getLhs().getType();
748 Type resultType = op.getResult().getType();
749 LLVM::FastmathFlags fmf =
750 arith::convertArithFastMathFlagsToLLVM(op.getFastmath());
753 if (!isa<LLVM::LLVMArrayType>(operandType)) {
754 rewriter.replaceOpWithNewOp<LLVM::FCmpOp>(
755 op, typeConverter->convertType(resultType),
757 adaptor.getLhs(), adaptor.getRhs(), fmf);
761 if (!isa<VectorType>(resultType))
762 return rewriter.notifyMatchFailure(op,
"expected vector result type");
765 op.getOperation(), adaptor.getOperands(), *getTypeConverter(),
766 [&](Type llvm1DVectorTy,
ValueRange operands) {
767 OpAdaptor adaptor(operands);
768 return LLVM::FCmpOp::create(
769 rewriter, op.getLoc(), llvm1DVectorTy,
771 adaptor.getLhs(), adaptor.getRhs(), fmf);
783LogicalResult SelectOpOneToNLowering::matchAndRewrite(
784 arith::SelectOp op, Adaptor adaptor,
785 ConversionPatternRewriter &rewriter)
const {
787 if (llvm::hasSingleElement(adaptor.getTrueValue()))
788 return rewriter.notifyMatchFailure(
789 op,
"not a 1:N conversion, 1:1 pattern will match");
790 if (!op.getCondition().getType().isInteger(1))
791 return rewriter.notifyMatchFailure(op,
792 "non-i1 conditions are not supported");
793 SmallVector<Value> results;
794 for (
auto [trueValue, falseValue] :
795 llvm::zip_equal(adaptor.getTrueValue(), adaptor.getFalseValue()))
796 results.push_back(arith::SelectOp::create(
797 rewriter, op.getLoc(), op.getCondition(), trueValue, falseValue));
798 rewriter.replaceOpWithMultiple(op, {results});
807struct ArithToLLVMConversionPass
808 :
public impl::ArithToLLVMConversionPassBase<ArithToLLVMConversionPass> {
811 void runOnOperation()
override {
815 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
817 dataLayoutAnalysis.getAtOrAbove(getOperation()));
819 options.overrideIndexBitwidth(indexBitwidth);
822 arith::populateCeilFloorDivExpandOpsPatterns(patterns);
823 arith::populateArithToLLVMConversionPatterns(converter, patterns);
825 if (
failed(applyPartialConversion(getOperation(),
target,
826 std::move(patterns))))
838struct ArithToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
839 ArithToLLVMDialectInterface(Dialect *dialect)
840 : ConvertToLLVMPatternInterface(dialect) {}
842 void loadDependentDialects(MLIRContext *context)
const final {
843 context->loadDialect<LLVM::LLVMDialect>();
848 void populateConvertToLLVMConversionPatterns(
849 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
850 RewritePatternSet &patterns)
const final {
851 arith::populateCeilFloorDivExpandOpsPatterns(patterns);
852 arith::populateArithToLLVMConversionPatterns(typeConverter, patterns);
860 dialect->addInterfaces<ArithToLLVMDialectInterface>();
873 patterns.
add<IdentityBitcastLowering>(converter, patterns.
getContext(),
879 ConstrainedAddFOpLowering,
882 AddUIExtendedOpLowering,
883 SubUIExtendedOpLowering,
889 ConstrainedDivFOpLowering,
898 IndexCastOpSILowering,
899 IndexCastOpUILowering,
902 MaximumNumFOpLowering,
907 MinimumNumFOpLowering,
911 ConstrainedMulFOpLowering,
913 MulSIExtendedOpLowering,
914 MulUIExtendedOpLowering,
921 SelectOpOneToNLowering,
927 ConstrainedSubFOpLowering,
930 ConstrainedTruncFOpLowering,
static LLVMPredType convertCmpPredicate(PredType pred)
static TypedAttr convertConstantValue(TypedAttr attr, Type resultType)
Retypes attr for a llvm.mlir.constant of resultType.
static llvm::ManagedStatic< PassManagerOptions > options
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
ConvertOpToLLVMPattern(const LLVMTypeConverter &typeConverter, PatternBenefit benefit=1)
typename SourceOp::template GenericAdaptor< ArrayRef< ValueRange > > OneToNOpAdaptor
An attribute that represents a reference to a dense integer vector or tensor object.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
Conversion from types to the LLVM IR dialect.
MLIRContext is the top-level object for a collection of MLIR operations.
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.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
Type getType() const
Return the type of this value.
Basic lowering implementation to rewrite Ops with just one result to the LLVM Dialect.
LogicalResult handleMultidimensionalVectors(Operation *op, ValueRange operands, const LLVMTypeConverter &typeConverter, std::function< Value(Type, ValueRange)> createOperand, ConversionPatternRewriter &rewriter)
bool isUnsupportedFloatingPointType(const TypeConverter &typeConverter, Type type)
Return "true" if the given type is an unsupported floating point type.
bool opHasUnsupportedFloatingPointTypes(Operation *op, const TypeConverter &typeConverter)
Return "true" if the given op has any unsupported floating point types (either operands or results).
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Type getConstantElementType(Type type)
Determines the element type of type the way the llvm.mlir.constant verifier does, i....
void populateArithToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns)
void registerConvertArithToLLVMInterface(DialectRegistry ®istry)
Include the generated interface declarations.
static constexpr unsigned kDeriveIndexBitwidthFromDataLayout
Value to pass as bitwidth for the index type when the converter is expected to derive the bitwidth fr...
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.