brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.7 KiB · 220826d Raw
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 &registry) {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