668 lines · cpp
1//===- ArithToLLVM.cpp - Arithmetic to LLVM dialect conversion -------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"10 11#include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"12#include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"13#include "mlir/Conversion/LLVMCommon/ConversionTarget.h"14#include "mlir/Conversion/LLVMCommon/VectorPattern.h"15#include "mlir/Dialect/Arith/IR/Arith.h"16#include "mlir/Dialect/Arith/Transforms/Passes.h"17#include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"18#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"19#include "mlir/Dialect/LLVMIR/LLVMDialect.h"20#include "mlir/IR/TypeUtilities.h"21#include <type_traits>22 23namespace mlir {24#define GEN_PASS_DEF_ARITHTOLLVMCONVERSIONPASS25#include "mlir/Conversion/Passes.h.inc"26} // namespace mlir27 28using namespace mlir;29 30namespace {31 32/// Operations whose conversion will depend on whether they are passed a33/// rounding mode attribute or not.34///35/// `SourceOp` is the source operation; `TargetOp`, the operation it will lower36/// to; `AttrConvert` is the attribute conversion to convert the rounding mode37/// attribute.38template <typename SourceOp, typename TargetOp, bool Constrained,39 template <typename, typename> typename AttrConvert =40 AttrConvertPassThrough,41 bool FailOnUnsupportedFP = false>42struct ConstrainedVectorConvertToLLVMPattern43 : public VectorConvertToLLVMPattern<SourceOp, TargetOp, AttrConvert,44 FailOnUnsupportedFP> {45 using VectorConvertToLLVMPattern<46 SourceOp, TargetOp, AttrConvert,47 FailOnUnsupportedFP>::VectorConvertToLLVMPattern;48 49 LogicalResult50 matchAndRewrite(SourceOp op, typename SourceOp::Adaptor adaptor,51 ConversionPatternRewriter &rewriter) const override {52 if (Constrained != static_cast<bool>(op.getRoundingModeAttr()))53 return failure();54 return VectorConvertToLLVMPattern<55 SourceOp, TargetOp, AttrConvert,56 FailOnUnsupportedFP>::matchAndRewrite(op, adaptor, rewriter);57 }58};59 60/// No-op bitcast. Propagate type input arg if converted source and dest types61/// are the same.62struct IdentityBitcastLowering final63 : public OpConversionPattern<arith::BitcastOp> {64 using Base::Base;65 66 LogicalResult67 matchAndRewrite(arith::BitcastOp op, OpAdaptor adaptor,68 ConversionPatternRewriter &rewriter) const final {69 Value src = adaptor.getIn();70 Type resultType = getTypeConverter()->convertType(op.getType());71 if (src.getType() != resultType)72 return rewriter.notifyMatchFailure(op, "Types are different");73 74 rewriter.replaceOp(op, src);75 return success();76 }77};78 79//===----------------------------------------------------------------------===//80// Straightforward Op Lowerings81//===----------------------------------------------------------------------===//82 83using AddFOpLowering =84 VectorConvertToLLVMPattern<arith::AddFOp, LLVM::FAddOp,85 arith::AttrConvertFastMathToLLVM,86 /*FailOnUnsupportedFP=*/true>;87using AddIOpLowering =88 VectorConvertToLLVMPattern<arith::AddIOp, LLVM::AddOp,89 arith::AttrConvertOverflowToLLVM>;90using AndIOpLowering = VectorConvertToLLVMPattern<arith::AndIOp, LLVM::AndOp>;91using BitcastOpLowering =92 VectorConvertToLLVMPattern<arith::BitcastOp, LLVM::BitcastOp>;93using DivFOpLowering =94 VectorConvertToLLVMPattern<arith::DivFOp, LLVM::FDivOp,95 arith::AttrConvertFastMathToLLVM,96 /*FailOnUnsupportedFP=*/true>;97using DivSIOpLowering =98 VectorConvertToLLVMPattern<arith::DivSIOp, LLVM::SDivOp>;99using DivUIOpLowering =100 VectorConvertToLLVMPattern<arith::DivUIOp, LLVM::UDivOp>;101using ExtFOpLowering = VectorConvertToLLVMPattern<arith::ExtFOp, LLVM::FPExtOp,102 AttrConvertPassThrough,103 /*FailOnUnsupportedFP=*/true>;104using ExtSIOpLowering =105 VectorConvertToLLVMPattern<arith::ExtSIOp, LLVM::SExtOp>;106using ExtUIOpLowering =107 VectorConvertToLLVMPattern<arith::ExtUIOp, LLVM::ZExtOp>;108using FPToSIOpLowering =109 VectorConvertToLLVMPattern<arith::FPToSIOp, LLVM::FPToSIOp,110 AttrConvertPassThrough,111 /*FailOnUnsupportedFP=*/true>;112using FPToUIOpLowering =113 VectorConvertToLLVMPattern<arith::FPToUIOp, LLVM::FPToUIOp,114 AttrConvertPassThrough,115 /*FailOnUnsupportedFP=*/true>;116using MaximumFOpLowering =117 VectorConvertToLLVMPattern<arith::MaximumFOp, LLVM::MaximumOp,118 arith::AttrConvertFastMathToLLVM,119 /*FailOnUnsupportedFP=*/true>;120using MaxNumFOpLowering =121 VectorConvertToLLVMPattern<arith::MaxNumFOp, LLVM::MaxNumOp,122 arith::AttrConvertFastMathToLLVM,123 /*FailOnUnsupportedFP=*/true>;124using MaxSIOpLowering =125 VectorConvertToLLVMPattern<arith::MaxSIOp, LLVM::SMaxOp>;126using MaxUIOpLowering =127 VectorConvertToLLVMPattern<arith::MaxUIOp, LLVM::UMaxOp>;128using MinimumFOpLowering =129 VectorConvertToLLVMPattern<arith::MinimumFOp, LLVM::MinimumOp,130 arith::AttrConvertFastMathToLLVM,131 /*FailOnUnsupportedFP=*/true>;132using MinNumFOpLowering =133 VectorConvertToLLVMPattern<arith::MinNumFOp, LLVM::MinNumOp,134 arith::AttrConvertFastMathToLLVM,135 /*FailOnUnsupportedFP=*/true>;136using MinSIOpLowering =137 VectorConvertToLLVMPattern<arith::MinSIOp, LLVM::SMinOp>;138using MinUIOpLowering =139 VectorConvertToLLVMPattern<arith::MinUIOp, LLVM::UMinOp>;140using MulFOpLowering =141 VectorConvertToLLVMPattern<arith::MulFOp, LLVM::FMulOp,142 arith::AttrConvertFastMathToLLVM,143 /*FailOnUnsupportedFP=*/true>;144using MulIOpLowering =145 VectorConvertToLLVMPattern<arith::MulIOp, LLVM::MulOp,146 arith::AttrConvertOverflowToLLVM>;147using NegFOpLowering =148 VectorConvertToLLVMPattern<arith::NegFOp, LLVM::FNegOp,149 arith::AttrConvertFastMathToLLVM,150 /*FailOnUnsupportedFP=*/true>;151using OrIOpLowering = VectorConvertToLLVMPattern<arith::OrIOp, LLVM::OrOp>;152using RemFOpLowering =153 VectorConvertToLLVMPattern<arith::RemFOp, LLVM::FRemOp,154 arith::AttrConvertFastMathToLLVM,155 /*FailOnUnsupportedFP=*/true>;156using RemSIOpLowering =157 VectorConvertToLLVMPattern<arith::RemSIOp, LLVM::SRemOp>;158using RemUIOpLowering =159 VectorConvertToLLVMPattern<arith::RemUIOp, LLVM::URemOp>;160using SelectOpLowering =161 VectorConvertToLLVMPattern<arith::SelectOp, LLVM::SelectOp>;162using ShLIOpLowering =163 VectorConvertToLLVMPattern<arith::ShLIOp, LLVM::ShlOp,164 arith::AttrConvertOverflowToLLVM>;165using ShRSIOpLowering =166 VectorConvertToLLVMPattern<arith::ShRSIOp, LLVM::AShrOp>;167using ShRUIOpLowering =168 VectorConvertToLLVMPattern<arith::ShRUIOp, LLVM::LShrOp>;169using SIToFPOpLowering =170 VectorConvertToLLVMPattern<arith::SIToFPOp, LLVM::SIToFPOp>;171using SubFOpLowering =172 VectorConvertToLLVMPattern<arith::SubFOp, LLVM::FSubOp,173 arith::AttrConvertFastMathToLLVM,174 /*FailOnUnsupportedFP=*/true>;175using SubIOpLowering =176 VectorConvertToLLVMPattern<arith::SubIOp, LLVM::SubOp,177 arith::AttrConvertOverflowToLLVM>;178using TruncFOpLowering =179 ConstrainedVectorConvertToLLVMPattern<arith::TruncFOp, LLVM::FPTruncOp,180 false, AttrConvertPassThrough,181 /*FailOnUnsupportedFP=*/true>;182using ConstrainedTruncFOpLowering = ConstrainedVectorConvertToLLVMPattern<183 arith::TruncFOp, LLVM::ConstrainedFPTruncIntr, true,184 arith::AttrConverterConstrainedFPToLLVM, /*FailOnUnsupportedFP=*/true>;185using TruncIOpLowering =186 VectorConvertToLLVMPattern<arith::TruncIOp, LLVM::TruncOp,187 arith::AttrConvertOverflowToLLVM>;188using UIToFPOpLowering =189 VectorConvertToLLVMPattern<arith::UIToFPOp, LLVM::UIToFPOp,190 AttrConvertPassThrough,191 /*FailOnUnsupportedFP=*/true>;192using XOrIOpLowering = VectorConvertToLLVMPattern<arith::XOrIOp, LLVM::XOrOp>;193 194//===----------------------------------------------------------------------===//195// Op Lowering Patterns196//===----------------------------------------------------------------------===//197 198/// Directly lower to LLVM op.199struct ConstantOpLowering : public ConvertOpToLLVMPattern<arith::ConstantOp> {200 using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern;201 202 LogicalResult203 matchAndRewrite(arith::ConstantOp op, OpAdaptor adaptor,204 ConversionPatternRewriter &rewriter) const override;205};206 207/// The lowering of index_cast becomes an integer conversion since index208/// becomes an integer. If the bit width of the source and target integer209/// types is the same, just erase the cast. If the target type is wider,210/// sign-extend the value, otherwise truncate it.211template <typename OpTy, typename ExtCastTy>212struct IndexCastOpLowering : public ConvertOpToLLVMPattern<OpTy> {213 using ConvertOpToLLVMPattern<OpTy>::ConvertOpToLLVMPattern;214 215 LogicalResult216 matchAndRewrite(OpTy op, typename OpTy::Adaptor adaptor,217 ConversionPatternRewriter &rewriter) const override;218};219 220using IndexCastOpSILowering =221 IndexCastOpLowering<arith::IndexCastOp, LLVM::SExtOp>;222using IndexCastOpUILowering =223 IndexCastOpLowering<arith::IndexCastUIOp, LLVM::ZExtOp>;224 225struct AddUIExtendedOpLowering226 : public ConvertOpToLLVMPattern<arith::AddUIExtendedOp> {227 using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern;228 229 LogicalResult230 matchAndRewrite(arith::AddUIExtendedOp op, OpAdaptor adaptor,231 ConversionPatternRewriter &rewriter) const override;232};233 234template <typename ArithMulOp, bool IsSigned>235struct MulIExtendedOpLowering : public ConvertOpToLLVMPattern<ArithMulOp> {236 using ConvertOpToLLVMPattern<ArithMulOp>::ConvertOpToLLVMPattern;237 238 LogicalResult239 matchAndRewrite(ArithMulOp op, typename ArithMulOp::Adaptor adaptor,240 ConversionPatternRewriter &rewriter) const override;241};242 243using MulSIExtendedOpLowering =244 MulIExtendedOpLowering<arith::MulSIExtendedOp, true>;245using MulUIExtendedOpLowering =246 MulIExtendedOpLowering<arith::MulUIExtendedOp, false>;247 248struct CmpIOpLowering : public ConvertOpToLLVMPattern<arith::CmpIOp> {249 using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern;250 251 LogicalResult252 matchAndRewrite(arith::CmpIOp op, OpAdaptor adaptor,253 ConversionPatternRewriter &rewriter) const override;254};255 256struct CmpFOpLowering : public ConvertOpToLLVMPattern<arith::CmpFOp> {257 using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern;258 259 LogicalResult260 matchAndRewrite(arith::CmpFOp op, OpAdaptor adaptor,261 ConversionPatternRewriter &rewriter) const override;262};263 264struct SelectOpOneToNLowering : public ConvertOpToLLVMPattern<arith::SelectOp> {265 using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern;266 using Adaptor = ConvertOpToLLVMPattern<arith::SelectOp>::OneToNOpAdaptor;267 268 LogicalResult269 matchAndRewrite(arith::SelectOp op, Adaptor adaptor,270 ConversionPatternRewriter &rewriter) const override;271};272 273} // namespace274 275//===----------------------------------------------------------------------===//276// ConstantOpLowering277//===----------------------------------------------------------------------===//278 279LogicalResult280ConstantOpLowering::matchAndRewrite(arith::ConstantOp op, OpAdaptor adaptor,281 ConversionPatternRewriter &rewriter) const {282 return LLVM::detail::oneToOneRewrite(op, LLVM::ConstantOp::getOperationName(),283 adaptor.getOperands(), op->getAttrs(),284 /*propAttr=*/Attribute{},285 *getTypeConverter(), rewriter);286}287 288//===----------------------------------------------------------------------===//289// IndexCastOpLowering290//===----------------------------------------------------------------------===//291 292template <typename OpTy, typename ExtCastTy>293LogicalResult IndexCastOpLowering<OpTy, ExtCastTy>::matchAndRewrite(294 OpTy op, typename OpTy::Adaptor adaptor,295 ConversionPatternRewriter &rewriter) const {296 Type resultType = op.getResult().getType();297 Type targetElementType =298 this->typeConverter->convertType(getElementTypeOrSelf(resultType));299 Type sourceElementType =300 this->typeConverter->convertType(getElementTypeOrSelf(op.getIn()));301 unsigned targetBits = targetElementType.getIntOrFloatBitWidth();302 unsigned sourceBits = sourceElementType.getIntOrFloatBitWidth();303 304 if (targetBits == sourceBits) {305 rewriter.replaceOp(op, adaptor.getIn());306 return success();307 }308 309 // Handle the scalar and 1D vector cases.310 Type operandType = adaptor.getIn().getType();311 if (!isa<LLVM::LLVMArrayType>(operandType)) {312 Type targetType = this->typeConverter->convertType(resultType);313 if (targetBits < sourceBits)314 rewriter.replaceOpWithNewOp<LLVM::TruncOp>(op, targetType,315 adaptor.getIn());316 else317 rewriter.replaceOpWithNewOp<ExtCastTy>(op, targetType, adaptor.getIn());318 return success();319 }320 321 if (!isa<VectorType>(resultType))322 return rewriter.notifyMatchFailure(op, "expected vector result type");323 324 return LLVM::detail::handleMultidimensionalVectors(325 op.getOperation(), adaptor.getOperands(), *(this->getTypeConverter()),326 [&](Type llvm1DVectorTy, ValueRange operands) -> Value {327 typename OpTy::Adaptor adaptor(operands);328 if (targetBits < sourceBits) {329 return LLVM::TruncOp::create(rewriter, op.getLoc(), llvm1DVectorTy,330 adaptor.getIn());331 }332 return ExtCastTy::create(rewriter, op.getLoc(), llvm1DVectorTy,333 adaptor.getIn());334 },335 rewriter);336}337 338//===----------------------------------------------------------------------===//339// AddUIExtendedOpLowering340//===----------------------------------------------------------------------===//341 342LogicalResult AddUIExtendedOpLowering::matchAndRewrite(343 arith::AddUIExtendedOp op, OpAdaptor adaptor,344 ConversionPatternRewriter &rewriter) const {345 Type operandType = adaptor.getLhs().getType();346 Type sumResultType = op.getSum().getType();347 Type overflowResultType = op.getOverflow().getType();348 349 if (!LLVM::isCompatibleType(operandType))350 return failure();351 352 MLIRContext *ctx = rewriter.getContext();353 Location loc = op.getLoc();354 355 // Handle the scalar and 1D vector cases.356 if (!isa<LLVM::LLVMArrayType>(operandType)) {357 Type newOverflowType = typeConverter->convertType(overflowResultType);358 Type structType =359 LLVM::LLVMStructType::getLiteral(ctx, {sumResultType, newOverflowType});360 Value addOverflow = LLVM::UAddWithOverflowOp::create(361 rewriter, loc, structType, adaptor.getLhs(), adaptor.getRhs());362 Value sumExtracted =363 LLVM::ExtractValueOp::create(rewriter, loc, addOverflow, 0);364 Value overflowExtracted =365 LLVM::ExtractValueOp::create(rewriter, loc, addOverflow, 1);366 rewriter.replaceOp(op, {sumExtracted, overflowExtracted});367 return success();368 }369 370 if (!isa<VectorType>(sumResultType))371 return rewriter.notifyMatchFailure(loc, "expected vector result types");372 373 return rewriter.notifyMatchFailure(loc,374 "ND vector types are not supported yet");375}376 377//===----------------------------------------------------------------------===//378// MulIExtendedOpLowering379//===----------------------------------------------------------------------===//380 381template <typename ArithMulOp, bool IsSigned>382LogicalResult MulIExtendedOpLowering<ArithMulOp, IsSigned>::matchAndRewrite(383 ArithMulOp op, typename ArithMulOp::Adaptor adaptor,384 ConversionPatternRewriter &rewriter) const {385 Type resultType = adaptor.getLhs().getType();386 387 if (!LLVM::isCompatibleType(resultType))388 return failure();389 390 Location loc = op.getLoc();391 392 // Handle the scalar and 1D vector cases. Because LLVM does not have a393 // matching extended multiplication intrinsic, perform regular multiplication394 // on operands zero-extended to i(2*N) bits, and truncate the results back to395 // iN types.396 if (!isa<LLVM::LLVMArrayType>(resultType)) {397 // Shift amount necessary to extract the high bits from widened result.398 TypedAttr shiftValAttr;399 400 if (auto intTy = dyn_cast<IntegerType>(resultType)) {401 unsigned resultBitwidth = intTy.getWidth();402 auto attrTy = rewriter.getIntegerType(resultBitwidth * 2);403 shiftValAttr = rewriter.getIntegerAttr(attrTy, resultBitwidth);404 } else {405 auto vecTy = cast<VectorType>(resultType);406 unsigned resultBitwidth = vecTy.getElementTypeBitWidth();407 auto attrTy = VectorType::get(408 vecTy.getShape(), rewriter.getIntegerType(resultBitwidth * 2));409 shiftValAttr = SplatElementsAttr::get(410 attrTy, APInt(resultBitwidth * 2, resultBitwidth));411 }412 Type wideType = shiftValAttr.getType();413 assert(LLVM::isCompatibleType(wideType) &&414 "LLVM dialect should support all signless integer types");415 416 using LLVMExtOp = std::conditional_t<IsSigned, LLVM::SExtOp, LLVM::ZExtOp>;417 Value lhsExt = LLVMExtOp::create(rewriter, loc, wideType, adaptor.getLhs());418 Value rhsExt = LLVMExtOp::create(rewriter, loc, wideType, adaptor.getRhs());419 Value mulExt = LLVM::MulOp::create(rewriter, loc, wideType, lhsExt, rhsExt);420 421 // Split the 2*N-bit wide result into two N-bit values.422 Value low = LLVM::TruncOp::create(rewriter, loc, resultType, mulExt);423 Value shiftVal = LLVM::ConstantOp::create(rewriter, loc, shiftValAttr);424 Value highExt = LLVM::LShrOp::create(rewriter, loc, mulExt, shiftVal);425 Value high = LLVM::TruncOp::create(rewriter, loc, resultType, highExt);426 427 rewriter.replaceOp(op, {low, high});428 return success();429 }430 431 if (!isa<VectorType>(resultType))432 return rewriter.notifyMatchFailure(op, "expected vector result type");433 434 return rewriter.notifyMatchFailure(op,435 "ND vector types are not supported yet");436}437 438//===----------------------------------------------------------------------===//439// CmpIOpLowering440//===----------------------------------------------------------------------===//441 442// Convert arith.cmp predicate into the LLVM dialect CmpPredicate. The two enums443// share numerical values so just cast.444template <typename LLVMPredType, typename PredType>445static LLVMPredType convertCmpPredicate(PredType pred) {446 return static_cast<LLVMPredType>(pred);447}448 449LogicalResult450CmpIOpLowering::matchAndRewrite(arith::CmpIOp op, OpAdaptor adaptor,451 ConversionPatternRewriter &rewriter) const {452 Type operandType = adaptor.getLhs().getType();453 Type resultType = op.getResult().getType();454 455 // Handle the scalar and 1D vector cases.456 if (!isa<LLVM::LLVMArrayType>(operandType)) {457 rewriter.replaceOpWithNewOp<LLVM::ICmpOp>(458 op, typeConverter->convertType(resultType),459 convertCmpPredicate<LLVM::ICmpPredicate>(op.getPredicate()),460 adaptor.getLhs(), adaptor.getRhs());461 return success();462 }463 464 if (!isa<VectorType>(resultType))465 return rewriter.notifyMatchFailure(op, "expected vector result type");466 467 return LLVM::detail::handleMultidimensionalVectors(468 op.getOperation(), adaptor.getOperands(), *getTypeConverter(),469 [&](Type llvm1DVectorTy, ValueRange operands) {470 OpAdaptor adaptor(operands);471 return LLVM::ICmpOp::create(472 rewriter, op.getLoc(), llvm1DVectorTy,473 convertCmpPredicate<LLVM::ICmpPredicate>(op.getPredicate()),474 adaptor.getLhs(), adaptor.getRhs());475 },476 rewriter);477}478 479//===----------------------------------------------------------------------===//480// CmpFOpLowering481//===----------------------------------------------------------------------===//482 483LogicalResult484CmpFOpLowering::matchAndRewrite(arith::CmpFOp op, OpAdaptor adaptor,485 ConversionPatternRewriter &rewriter) const {486 if (LLVM::detail::isUnsupportedFloatingPointType(*this->getTypeConverter(),487 op.getLhs().getType()))488 return rewriter.notifyMatchFailure(op, "unsupported floating point type");489 490 Type operandType = adaptor.getLhs().getType();491 Type resultType = op.getResult().getType();492 LLVM::FastmathFlags fmf =493 arith::convertArithFastMathFlagsToLLVM(op.getFastmath());494 495 // Handle the scalar and 1D vector cases.496 if (!isa<LLVM::LLVMArrayType>(operandType)) {497 rewriter.replaceOpWithNewOp<LLVM::FCmpOp>(498 op, typeConverter->convertType(resultType),499 convertCmpPredicate<LLVM::FCmpPredicate>(op.getPredicate()),500 adaptor.getLhs(), adaptor.getRhs(), fmf);501 return success();502 }503 504 if (!isa<VectorType>(resultType))505 return rewriter.notifyMatchFailure(op, "expected vector result type");506 507 return LLVM::detail::handleMultidimensionalVectors(508 op.getOperation(), adaptor.getOperands(), *getTypeConverter(),509 [&](Type llvm1DVectorTy, ValueRange operands) {510 OpAdaptor adaptor(operands);511 return LLVM::FCmpOp::create(512 rewriter, op.getLoc(), llvm1DVectorTy,513 convertCmpPredicate<LLVM::FCmpPredicate>(op.getPredicate()),514 adaptor.getLhs(), adaptor.getRhs(), fmf);515 },516 rewriter);517}518 519//===----------------------------------------------------------------------===//520// SelectOpOneToNLowering521//===----------------------------------------------------------------------===//522 523/// Pattern for arith.select where the true/false values lower to multiple524/// SSA values (1:N conversion). This pattern generates multiple arith.select525/// than can be lowered by the 1:1 arith.select pattern.526LogicalResult SelectOpOneToNLowering::matchAndRewrite(527 arith::SelectOp op, Adaptor adaptor,528 ConversionPatternRewriter &rewriter) const {529 // In case of a 1:1 conversion, the 1:1 pattern will match.530 if (llvm::hasSingleElement(adaptor.getTrueValue()))531 return rewriter.notifyMatchFailure(532 op, "not a 1:N conversion, 1:1 pattern will match");533 if (!op.getCondition().getType().isInteger(1))534 return rewriter.notifyMatchFailure(op,535 "non-i1 conditions are not supported");536 SmallVector<Value> results;537 for (auto [trueValue, falseValue] :538 llvm::zip_equal(adaptor.getTrueValue(), adaptor.getFalseValue()))539 results.push_back(arith::SelectOp::create(540 rewriter, op.getLoc(), op.getCondition(), trueValue, falseValue));541 rewriter.replaceOpWithMultiple(op, {results});542 return success();543}544 545//===----------------------------------------------------------------------===//546// Pass Definition547//===----------------------------------------------------------------------===//548 549namespace {550struct ArithToLLVMConversionPass551 : public impl::ArithToLLVMConversionPassBase<ArithToLLVMConversionPass> {552 using Base::Base;553 554 void runOnOperation() override {555 LLVMConversionTarget target(getContext());556 RewritePatternSet patterns(&getContext());557 558 LowerToLLVMOptions options(&getContext());559 if (indexBitwidth != kDeriveIndexBitwidthFromDataLayout)560 options.overrideIndexBitwidth(indexBitwidth);561 562 LLVMTypeConverter converter(&getContext(), options);563 arith::populateCeilFloorDivExpandOpsPatterns(patterns);564 arith::populateArithToLLVMConversionPatterns(converter, patterns);565 566 if (failed(applyPartialConversion(getOperation(), target,567 std::move(patterns))))568 signalPassFailure();569 }570};571} // namespace572 573//===----------------------------------------------------------------------===//574// ConvertToLLVMPatternInterface implementation575//===----------------------------------------------------------------------===//576 577namespace {578/// Implement the interface to convert MemRef to LLVM.579struct ArithToLLVMDialectInterface : public ConvertToLLVMPatternInterface {580 using ConvertToLLVMPatternInterface::ConvertToLLVMPatternInterface;581 void loadDependentDialects(MLIRContext *context) const final {582 context->loadDialect<LLVM::LLVMDialect>();583 }584 585 /// Hook for derived dialect interface to provide conversion patterns586 /// and mark dialect legal for the conversion target.587 void populateConvertToLLVMConversionPatterns(588 ConversionTarget &target, LLVMTypeConverter &typeConverter,589 RewritePatternSet &patterns) const final {590 arith::populateCeilFloorDivExpandOpsPatterns(patterns);591 arith::populateArithToLLVMConversionPatterns(typeConverter, patterns);592 }593};594} // namespace595 596void mlir::arith::registerConvertArithToLLVMInterface(597 DialectRegistry ®istry) {598 registry.addExtension(+[](MLIRContext *ctx, arith::ArithDialect *dialect) {599 dialect->addInterfaces<ArithToLLVMDialectInterface>();600 });601}602 603//===----------------------------------------------------------------------===//604// Pattern Population605//===----------------------------------------------------------------------===//606 607void mlir::arith::populateArithToLLVMConversionPatterns(608 const LLVMTypeConverter &converter, RewritePatternSet &patterns) {609 610 // Set a higher pattern benefit for IdentityBitcastLowering so it will run611 // before BitcastOpLowering.612 patterns.add<IdentityBitcastLowering>(converter, patterns.getContext(),613 /*patternBenefit*/ 10);614 615 // clang-format off616 patterns.add<617 AddFOpLowering,618 AddIOpLowering,619 AndIOpLowering,620 AddUIExtendedOpLowering,621 BitcastOpLowering,622 ConstantOpLowering,623 CmpFOpLowering,624 CmpIOpLowering,625 DivFOpLowering,626 DivSIOpLowering,627 DivUIOpLowering,628 ExtFOpLowering,629 ExtSIOpLowering,630 ExtUIOpLowering,631 FPToSIOpLowering,632 FPToUIOpLowering,633 IndexCastOpSILowering,634 IndexCastOpUILowering,635 MaximumFOpLowering,636 MaxNumFOpLowering,637 MaxSIOpLowering,638 MaxUIOpLowering,639 MinimumFOpLowering,640 MinNumFOpLowering,641 MinSIOpLowering,642 MinUIOpLowering,643 MulFOpLowering,644 MulIOpLowering,645 MulSIExtendedOpLowering,646 MulUIExtendedOpLowering,647 NegFOpLowering,648 OrIOpLowering,649 RemFOpLowering,650 RemSIOpLowering,651 RemUIOpLowering,652 SelectOpLowering,653 SelectOpOneToNLowering,654 ShLIOpLowering,655 ShRSIOpLowering,656 ShRUIOpLowering,657 SIToFPOpLowering,658 SubFOpLowering,659 SubIOpLowering,660 TruncFOpLowering,661 ConstrainedTruncFOpLowering,662 TruncIOpLowering,663 UIToFPOpLowering,664 XOrIOpLowering665 >(converter);666 // clang-format on667}668