brintos

brintos / llvm-project-archived public Read only

0
0
Text · 277.4 KiB · 3a5f149 Raw
6884 lines · cpp
1//===-- AArch64TargetTransformInfo.cpp - AArch64 specific TTI -------------===//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 "AArch64TargetTransformInfo.h"10#include "AArch64ExpandImm.h"11#include "AArch64PerfectShuffle.h"12#include "AArch64SMEAttributes.h"13#include "MCTargetDesc/AArch64AddressingModes.h"14#include "llvm/ADT/DenseMap.h"15#include "llvm/Analysis/LoopInfo.h"16#include "llvm/Analysis/TargetTransformInfo.h"17#include "llvm/CodeGen/BasicTTIImpl.h"18#include "llvm/CodeGen/CostTable.h"19#include "llvm/CodeGen/TargetLowering.h"20#include "llvm/IR/DerivedTypes.h"21#include "llvm/IR/IntrinsicInst.h"22#include "llvm/IR/Intrinsics.h"23#include "llvm/IR/IntrinsicsAArch64.h"24#include "llvm/IR/PatternMatch.h"25#include "llvm/Support/Debug.h"26#include "llvm/TargetParser/AArch64TargetParser.h"27#include "llvm/Transforms/InstCombine/InstCombiner.h"28#include "llvm/Transforms/Utils/UnrollLoop.h"29#include "llvm/Transforms/Vectorize/LoopVectorizationLegality.h"30#include <algorithm>31#include <optional>32using namespace llvm;33using namespace llvm::PatternMatch;34 35#define DEBUG_TYPE "aarch64tti"36 37static cl::opt<bool> EnableFalkorHWPFUnrollFix("enable-falkor-hwpf-unroll-fix",38                                               cl::init(true), cl::Hidden);39 40static cl::opt<bool> SVEPreferFixedOverScalableIfEqualCost(41    "sve-prefer-fixed-over-scalable-if-equal", cl::Hidden);42 43static cl::opt<unsigned> SVEGatherOverhead("sve-gather-overhead", cl::init(10),44                                           cl::Hidden);45 46static cl::opt<unsigned> SVEScatterOverhead("sve-scatter-overhead",47                                            cl::init(10), cl::Hidden);48 49static cl::opt<unsigned> SVETailFoldInsnThreshold("sve-tail-folding-insn-threshold",50                                                  cl::init(15), cl::Hidden);51 52static cl::opt<unsigned>53    NeonNonConstStrideOverhead("neon-nonconst-stride-overhead", cl::init(10),54                               cl::Hidden);55 56static cl::opt<unsigned> CallPenaltyChangeSM(57    "call-penalty-sm-change", cl::init(5), cl::Hidden,58    cl::desc(59        "Penalty of calling a function that requires a change to PSTATE.SM"));60 61static cl::opt<unsigned> InlineCallPenaltyChangeSM(62    "inline-call-penalty-sm-change", cl::init(10), cl::Hidden,63    cl::desc("Penalty of inlining a call that requires a change to PSTATE.SM"));64 65static cl::opt<bool> EnableOrLikeSelectOpt("enable-aarch64-or-like-select",66                                           cl::init(true), cl::Hidden);67 68static cl::opt<bool> EnableLSRCostOpt("enable-aarch64-lsr-cost-opt",69                                      cl::init(true), cl::Hidden);70 71// A complete guess as to a reasonable cost.72static cl::opt<unsigned>73    BaseHistCntCost("aarch64-base-histcnt-cost", cl::init(8), cl::Hidden,74                    cl::desc("The cost of a histcnt instruction"));75 76static cl::opt<unsigned> DMBLookaheadThreshold(77    "dmb-lookahead-threshold", cl::init(10), cl::Hidden,78    cl::desc("The number of instructions to search for a redundant dmb"));79 80static cl::opt<int> Aarch64ForceUnrollThreshold(81    "aarch64-force-unroll-threshold", cl::init(0), cl::Hidden,82    cl::desc("Threshold for forced unrolling of small loops in AArch64"));83 84namespace {85class TailFoldingOption {86  // These bitfields will only ever be set to something non-zero in operator=,87  // when setting the -sve-tail-folding option. This option should always be of88  // the form (default|simple|all|disable)[+(Flag1|Flag2|etc)], where here89  // InitialBits is one of (disabled|all|simple). EnableBits represents90  // additional flags we're enabling, and DisableBits for those flags we're91  // disabling. The default flag is tracked in the variable NeedsDefault, since92  // at the time of setting the option we may not know what the default value93  // for the CPU is.94  TailFoldingOpts InitialBits = TailFoldingOpts::Disabled;95  TailFoldingOpts EnableBits = TailFoldingOpts::Disabled;96  TailFoldingOpts DisableBits = TailFoldingOpts::Disabled;97 98  // This value needs to be initialised to true in case the user does not99  // explicitly set the -sve-tail-folding option.100  bool NeedsDefault = true;101 102  void setInitialBits(TailFoldingOpts Bits) { InitialBits = Bits; }103 104  void setNeedsDefault(bool V) { NeedsDefault = V; }105 106  void setEnableBit(TailFoldingOpts Bit) {107    EnableBits |= Bit;108    DisableBits &= ~Bit;109  }110 111  void setDisableBit(TailFoldingOpts Bit) {112    EnableBits &= ~Bit;113    DisableBits |= Bit;114  }115 116  TailFoldingOpts getBits(TailFoldingOpts DefaultBits) const {117    TailFoldingOpts Bits = TailFoldingOpts::Disabled;118 119    assert((InitialBits == TailFoldingOpts::Disabled || !NeedsDefault) &&120           "Initial bits should only include one of "121           "(disabled|all|simple|default)");122    Bits = NeedsDefault ? DefaultBits : InitialBits;123    Bits |= EnableBits;124    Bits &= ~DisableBits;125 126    return Bits;127  }128 129  void reportError(std::string Opt) {130    errs() << "invalid argument '" << Opt131           << "' to -sve-tail-folding=; the option should be of the form\n"132              "  (disabled|all|default|simple)[+(reductions|recurrences"133              "|reverse|noreductions|norecurrences|noreverse)]\n";134    report_fatal_error("Unrecognised tail-folding option");135  }136 137public:138 139  void operator=(const std::string &Val) {140    // If the user explicitly sets -sve-tail-folding= then treat as an error.141    if (Val.empty()) {142      reportError("");143      return;144    }145 146    // Since the user is explicitly setting the option we don't automatically147    // need the default unless they require it.148    setNeedsDefault(false);149 150    SmallVector<StringRef, 4> TailFoldTypes;151    StringRef(Val).split(TailFoldTypes, '+', -1, false);152 153    unsigned StartIdx = 1;154    if (TailFoldTypes[0] == "disabled")155      setInitialBits(TailFoldingOpts::Disabled);156    else if (TailFoldTypes[0] == "all")157      setInitialBits(TailFoldingOpts::All);158    else if (TailFoldTypes[0] == "default")159      setNeedsDefault(true);160    else if (TailFoldTypes[0] == "simple")161      setInitialBits(TailFoldingOpts::Simple);162    else {163      StartIdx = 0;164      setInitialBits(TailFoldingOpts::Disabled);165    }166 167    for (unsigned I = StartIdx; I < TailFoldTypes.size(); I++) {168      if (TailFoldTypes[I] == "reductions")169        setEnableBit(TailFoldingOpts::Reductions);170      else if (TailFoldTypes[I] == "recurrences")171        setEnableBit(TailFoldingOpts::Recurrences);172      else if (TailFoldTypes[I] == "reverse")173        setEnableBit(TailFoldingOpts::Reverse);174      else if (TailFoldTypes[I] == "noreductions")175        setDisableBit(TailFoldingOpts::Reductions);176      else if (TailFoldTypes[I] == "norecurrences")177        setDisableBit(TailFoldingOpts::Recurrences);178      else if (TailFoldTypes[I] == "noreverse")179        setDisableBit(TailFoldingOpts::Reverse);180      else181        reportError(Val);182    }183  }184 185  bool satisfies(TailFoldingOpts DefaultBits, TailFoldingOpts Required) const {186    return (getBits(DefaultBits) & Required) == Required;187  }188};189} // namespace190 191TailFoldingOption TailFoldingOptionLoc;192 193static cl::opt<TailFoldingOption, true, cl::parser<std::string>> SVETailFolding(194    "sve-tail-folding",195    cl::desc(196        "Control the use of vectorisation using tail-folding for SVE where the"197        " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"198        "\ndisabled      (Initial) No loop types will vectorize using "199        "tail-folding"200        "\ndefault       (Initial) Uses the default tail-folding settings for "201        "the target CPU"202        "\nall           (Initial) All legal loop types will vectorize using "203        "tail-folding"204        "\nsimple        (Initial) Use tail-folding for simple loops (not "205        "reductions or recurrences)"206        "\nreductions    Use tail-folding for loops containing reductions"207        "\nnoreductions  Inverse of above"208        "\nrecurrences   Use tail-folding for loops containing fixed order "209        "recurrences"210        "\nnorecurrences Inverse of above"211        "\nreverse       Use tail-folding for loops requiring reversed "212        "predicates"213        "\nnoreverse     Inverse of above"),214    cl::location(TailFoldingOptionLoc));215 216// Experimental option that will only be fully functional when the217// code-generator is changed to use SVE instead of NEON for all fixed-width218// operations.219static cl::opt<bool> EnableFixedwidthAutovecInStreamingMode(220    "enable-fixedwidth-autovec-in-streaming-mode", cl::init(false), cl::Hidden);221 222// Experimental option that will only be fully functional when the cost-model223// and code-generator have been changed to avoid using scalable vector224// instructions that are not legal in streaming SVE mode.225static cl::opt<bool> EnableScalableAutovecInStreamingMode(226    "enable-scalable-autovec-in-streaming-mode", cl::init(false), cl::Hidden);227 228static bool isSMEABIRoutineCall(const CallInst &CI,229                                const AArch64TargetLowering &TLI) {230  const auto *F = CI.getCalledFunction();231  return F &&232         SMEAttrs(F->getName(), TLI.getRuntimeLibcallsInfo()).isSMEABIRoutine();233}234 235/// Returns true if the function has explicit operations that can only be236/// lowered using incompatible instructions for the selected mode. This also237/// returns true if the function F may use or modify ZA state.238static bool hasPossibleIncompatibleOps(const Function *F,239                                       const AArch64TargetLowering &TLI) {240  for (const BasicBlock &BB : *F) {241    for (const Instruction &I : BB) {242      // Be conservative for now and assume that any call to inline asm or to243      // intrinsics could could result in non-streaming ops (e.g. calls to244      // @llvm.aarch64.* or @llvm.gather/scatter intrinsics). We can assume that245      // all native LLVM instructions can be lowered to compatible instructions.246      if (isa<CallInst>(I) && !I.isDebugOrPseudoInst() &&247          (cast<CallInst>(I).isInlineAsm() || isa<IntrinsicInst>(I) ||248           isSMEABIRoutineCall(cast<CallInst>(I), TLI)))249        return true;250    }251  }252  return false;253}254 255APInt AArch64TTIImpl::getFeatureMask(const Function &F) const {256  StringRef AttributeStr =257      isMultiversionedFunction(F) ? "fmv-features" : "target-features";258  StringRef FeatureStr = F.getFnAttribute(AttributeStr).getValueAsString();259  SmallVector<StringRef, 8> Features;260  FeatureStr.split(Features, ",");261  return AArch64::getFMVPriority(Features);262}263 264bool AArch64TTIImpl::isMultiversionedFunction(const Function &F) const {265  return F.hasFnAttribute("fmv-features");266}267 268const FeatureBitset AArch64TTIImpl::InlineInverseFeatures = {269    AArch64::FeatureExecuteOnly,270};271 272bool AArch64TTIImpl::areInlineCompatible(const Function *Caller,273                                         const Function *Callee) const {274  SMECallAttrs CallAttrs(*Caller, *Callee);275 276  // Never inline a function explicitly marked as being streaming,277  // into a non-streaming function. Assume it was marked as streaming278  // for a reason.279  if (CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&280      CallAttrs.callee().hasStreamingInterfaceOrBody())281    return false;282 283  // When inlining, we should consider the body of the function, not the284  // interface.285  if (CallAttrs.callee().hasStreamingBody()) {286    CallAttrs.callee().set(SMEAttrs::SM_Compatible, false);287    CallAttrs.callee().set(SMEAttrs::SM_Enabled, true);288  }289 290  if (CallAttrs.callee().isNewZA() || CallAttrs.callee().isNewZT0())291    return false;292 293  if (CallAttrs.requiresLazySave() || CallAttrs.requiresSMChange() ||294      CallAttrs.requiresPreservingZT0() ||295      CallAttrs.requiresPreservingAllZAState()) {296    if (hasPossibleIncompatibleOps(Callee, *getTLI()))297      return false;298  }299 300  const TargetMachine &TM = getTLI()->getTargetMachine();301  const FeatureBitset &CallerBits =302      TM.getSubtargetImpl(*Caller)->getFeatureBits();303  const FeatureBitset &CalleeBits =304      TM.getSubtargetImpl(*Callee)->getFeatureBits();305  // Adjust the feature bitsets by inverting some of the bits. This is needed306  // for target features that represent restrictions rather than capabilities,307  // for example a "+execute-only" callee can be inlined into a caller without308  // "+execute-only", but not vice versa.309  FeatureBitset EffectiveCallerBits = CallerBits ^ InlineInverseFeatures;310  FeatureBitset EffectiveCalleeBits = CalleeBits ^ InlineInverseFeatures;311 312  return (EffectiveCallerBits & EffectiveCalleeBits) == EffectiveCalleeBits;313}314 315bool AArch64TTIImpl::areTypesABICompatible(const Function *Caller,316                                           const Function *Callee,317                                           ArrayRef<Type *> Types) const {318  if (!BaseT::areTypesABICompatible(Caller, Callee, Types))319    return false;320 321  // We need to ensure that argument promotion does not attempt to promote322  // pointers to fixed-length vector types larger than 128 bits like323  // <8 x float> (and pointers to aggregate types which have such fixed-length324  // vector type members) into the values of the pointees. Such vector types325  // are used for SVE VLS but there is no ABI for SVE VLS arguments and the326  // backend cannot lower such value arguments. The 128-bit fixed-length SVE327  // types can be safely treated as 128-bit NEON types and they cannot be328  // distinguished in IR.329  if (ST->useSVEForFixedLengthVectors() && llvm::any_of(Types, [](Type *Ty) {330        auto FVTy = dyn_cast<FixedVectorType>(Ty);331        return FVTy &&332               FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;333      }))334    return false;335 336  return true;337}338 339unsigned340AArch64TTIImpl::getInlineCallPenalty(const Function *F, const CallBase &Call,341                                     unsigned DefaultCallPenalty) const {342  // This function calculates a penalty for executing Call in F.343  //344  // There are two ways this function can be called:345  // (1)  F:346  //       call from F -> G (the call here is Call)347  //348  // For (1), Call.getCaller() == F, so it will always return a high cost if349  // a streaming-mode change is required (thus promoting the need to inline the350  // function)351  //352  // (2)  F:353  //       call from F -> G (the call here is not Call)354  //      G:355  //       call from G -> H (the call here is Call)356  //357  // For (2), if after inlining the body of G into F the call to H requires a358  // streaming-mode change, and the call to G from F would also require a359  // streaming-mode change, then there is benefit to do the streaming-mode360  // change only once and avoid inlining of G into F.361 362  SMEAttrs FAttrs(*F);363  SMECallAttrs CallAttrs(Call, &getTLI()->getRuntimeLibcallsInfo());364 365  if (SMECallAttrs(FAttrs, CallAttrs.callee()).requiresSMChange()) {366    if (F == Call.getCaller()) // (1)367      return CallPenaltyChangeSM * DefaultCallPenalty;368    if (SMECallAttrs(FAttrs, CallAttrs.caller()).requiresSMChange()) // (2)369      return InlineCallPenaltyChangeSM * DefaultCallPenalty;370  }371 372  return DefaultCallPenalty;373}374 375bool AArch64TTIImpl::shouldMaximizeVectorBandwidth(376    TargetTransformInfo::RegisterKind K) const {377  assert(K != TargetTransformInfo::RGK_Scalar);378 379  if (K == TargetTransformInfo::RGK_FixedWidthVector && ST->isNeonAvailable())380    return true;381 382  return K == TargetTransformInfo::RGK_ScalableVector &&383         ST->isSVEorStreamingSVEAvailable() &&384         !ST->disableMaximizeScalableBandwidth();385}386 387/// Calculate the cost of materializing a 64-bit value. This helper388/// method might only calculate a fraction of a larger immediate. Therefore it389/// is valid to return a cost of ZERO.390InstructionCost AArch64TTIImpl::getIntImmCost(int64_t Val) const {391  // Check if the immediate can be encoded within an instruction.392  if (Val == 0 || AArch64_AM::isLogicalImmediate(Val, 64))393    return 0;394 395  if (Val < 0)396    Val = ~Val;397 398  // Calculate how many moves we will need to materialize this constant.399  SmallVector<AArch64_IMM::ImmInsnModel, 4> Insn;400  AArch64_IMM::expandMOVImm(Val, 64, Insn);401  return Insn.size();402}403 404/// Calculate the cost of materializing the given constant.405InstructionCost406AArch64TTIImpl::getIntImmCost(const APInt &Imm, Type *Ty,407                              TTI::TargetCostKind CostKind) const {408  assert(Ty->isIntegerTy());409 410  unsigned BitSize = Ty->getPrimitiveSizeInBits();411  if (BitSize == 0)412    return ~0U;413 414  // Sign-extend all constants to a multiple of 64-bit.415  APInt ImmVal = Imm;416  if (BitSize & 0x3f)417    ImmVal = Imm.sext((BitSize + 63) & ~0x3fU);418 419  // Split the constant into 64-bit chunks and calculate the cost for each420  // chunk.421  InstructionCost Cost = 0;422  for (unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {423    APInt Tmp = ImmVal.ashr(ShiftVal).sextOrTrunc(64);424    int64_t Val = Tmp.getSExtValue();425    Cost += getIntImmCost(Val);426  }427  // We need at least one instruction to materialze the constant.428  return std::max<InstructionCost>(1, Cost);429}430 431InstructionCost AArch64TTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx,432                                                  const APInt &Imm, Type *Ty,433                                                  TTI::TargetCostKind CostKind,434                                                  Instruction *Inst) const {435  assert(Ty->isIntegerTy());436 437  unsigned BitSize = Ty->getPrimitiveSizeInBits();438  // There is no cost model for constants with a bit size of 0. Return TCC_Free439  // here, so that constant hoisting will ignore this constant.440  if (BitSize == 0)441    return TTI::TCC_Free;442 443  unsigned ImmIdx = ~0U;444  switch (Opcode) {445  default:446    return TTI::TCC_Free;447  case Instruction::GetElementPtr:448    // Always hoist the base address of a GetElementPtr.449    if (Idx == 0)450      return 2 * TTI::TCC_Basic;451    return TTI::TCC_Free;452  case Instruction::Store:453    ImmIdx = 0;454    break;455  case Instruction::Add:456  case Instruction::Sub:457  case Instruction::Mul:458  case Instruction::UDiv:459  case Instruction::SDiv:460  case Instruction::URem:461  case Instruction::SRem:462  case Instruction::And:463  case Instruction::Or:464  case Instruction::Xor:465  case Instruction::ICmp:466    ImmIdx = 1;467    break;468  // Always return TCC_Free for the shift value of a shift instruction.469  case Instruction::Shl:470  case Instruction::LShr:471  case Instruction::AShr:472    if (Idx == 1)473      return TTI::TCC_Free;474    break;475  case Instruction::Trunc:476  case Instruction::ZExt:477  case Instruction::SExt:478  case Instruction::IntToPtr:479  case Instruction::PtrToInt:480  case Instruction::BitCast:481  case Instruction::PHI:482  case Instruction::Call:483  case Instruction::Select:484  case Instruction::Ret:485  case Instruction::Load:486    break;487  }488 489  if (Idx == ImmIdx) {490    int NumConstants = (BitSize + 63) / 64;491    InstructionCost Cost = AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind);492    return (Cost <= NumConstants * TTI::TCC_Basic)493               ? static_cast<int>(TTI::TCC_Free)494               : Cost;495  }496  return AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind);497}498 499InstructionCost500AArch64TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,501                                    const APInt &Imm, Type *Ty,502                                    TTI::TargetCostKind CostKind) const {503  assert(Ty->isIntegerTy());504 505  unsigned BitSize = Ty->getPrimitiveSizeInBits();506  // There is no cost model for constants with a bit size of 0. Return TCC_Free507  // here, so that constant hoisting will ignore this constant.508  if (BitSize == 0)509    return TTI::TCC_Free;510 511  // Most (all?) AArch64 intrinsics do not support folding immediates into the512  // selected instruction, so we compute the materialization cost for the513  // immediate directly.514  if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)515    return AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind);516 517  switch (IID) {518  default:519    return TTI::TCC_Free;520  case Intrinsic::sadd_with_overflow:521  case Intrinsic::uadd_with_overflow:522  case Intrinsic::ssub_with_overflow:523  case Intrinsic::usub_with_overflow:524  case Intrinsic::smul_with_overflow:525  case Intrinsic::umul_with_overflow:526    if (Idx == 1) {527      int NumConstants = (BitSize + 63) / 64;528      InstructionCost Cost = AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind);529      return (Cost <= NumConstants * TTI::TCC_Basic)530                 ? static_cast<int>(TTI::TCC_Free)531                 : Cost;532    }533    break;534  case Intrinsic::experimental_stackmap:535    if ((Idx < 2) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))536      return TTI::TCC_Free;537    break;538  case Intrinsic::experimental_patchpoint_void:539  case Intrinsic::experimental_patchpoint:540    if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))541      return TTI::TCC_Free;542    break;543  case Intrinsic::experimental_gc_statepoint:544    if ((Idx < 5) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))545      return TTI::TCC_Free;546    break;547  }548  return AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind);549}550 551TargetTransformInfo::PopcntSupportKind552AArch64TTIImpl::getPopcntSupport(unsigned TyWidth) const {553  assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");554  if (TyWidth == 32 || TyWidth == 64)555    return TTI::PSK_FastHardware;556  // TODO: AArch64TargetLowering::LowerCTPOP() supports 128bit popcount.557  return TTI::PSK_Software;558}559 560static bool isUnpackedVectorVT(EVT VecVT) {561  return VecVT.isScalableVector() &&562         VecVT.getSizeInBits().getKnownMinValue() < AArch64::SVEBitsPerBlock;563}564 565static InstructionCost getHistogramCost(const AArch64Subtarget *ST,566                                        const IntrinsicCostAttributes &ICA) {567  // We need to know at least the number of elements in the vector of buckets568  // and the size of each element to update.569  if (ICA.getArgTypes().size() < 2)570    return InstructionCost::getInvalid();571 572  // Only interested in costing for the hardware instruction from SVE2.573  if (!ST->hasSVE2())574    return InstructionCost::getInvalid();575 576  Type *BucketPtrsTy = ICA.getArgTypes()[0]; // Type of vector of pointers577  Type *EltTy = ICA.getArgTypes()[1];        // Type of bucket elements578  unsigned TotalHistCnts = 1;579 580  unsigned EltSize = EltTy->getScalarSizeInBits();581  // Only allow (up to 64b) integers or pointers582  if ((!EltTy->isIntegerTy() && !EltTy->isPointerTy()) || EltSize > 64)583    return InstructionCost::getInvalid();584 585  // FIXME: We should be able to generate histcnt for fixed-length vectors586  //        using ptrue with a specific VL.587  if (VectorType *VTy = dyn_cast<VectorType>(BucketPtrsTy)) {588    unsigned EC = VTy->getElementCount().getKnownMinValue();589    if (!isPowerOf2_64(EC) || !VTy->isScalableTy())590      return InstructionCost::getInvalid();591 592    // HistCnt only supports 32b and 64b element types593    unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;594 595    if (EC == 2 || (LegalEltSize == 32 && EC == 4))596      return InstructionCost(BaseHistCntCost);597 598    unsigned NaturalVectorWidth = AArch64::SVEBitsPerBlock / LegalEltSize;599    TotalHistCnts = EC / NaturalVectorWidth;600 601    return InstructionCost(BaseHistCntCost * TotalHistCnts);602  }603 604  return InstructionCost::getInvalid();605}606 607InstructionCost608AArch64TTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,609                                      TTI::TargetCostKind CostKind) const {610  // The code-generator is currently not able to handle scalable vectors611  // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting612  // it. This change will be removed when code-generation for these types is613  // sufficiently reliable.614  auto *RetTy = ICA.getReturnType();615  if (auto *VTy = dyn_cast<ScalableVectorType>(RetTy))616    if (VTy->getElementCount() == ElementCount::getScalable(1))617      return InstructionCost::getInvalid();618 619  switch (ICA.getID()) {620  case Intrinsic::experimental_vector_histogram_add: {621    InstructionCost HistCost = getHistogramCost(ST, ICA);622    // If the cost isn't valid, we may still be able to scalarize623    if (HistCost.isValid())624      return HistCost;625    break;626  }627  case Intrinsic::umin:628  case Intrinsic::umax:629  case Intrinsic::smin:630  case Intrinsic::smax: {631    static const auto ValidMinMaxTys = {MVT::v8i8,  MVT::v16i8, MVT::v4i16,632                                        MVT::v8i16, MVT::v2i32, MVT::v4i32,633                                        MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,634                                        MVT::nxv2i64};635    auto LT = getTypeLegalizationCost(RetTy);636    // v2i64 types get converted to cmp+bif hence the cost of 2637    if (LT.second == MVT::v2i64)638      return LT.first * 2;639    if (any_of(ValidMinMaxTys, [&LT](MVT M) { return M == LT.second; }))640      return LT.first;641    break;642  }643  case Intrinsic::sadd_sat:644  case Intrinsic::ssub_sat:645  case Intrinsic::uadd_sat:646  case Intrinsic::usub_sat: {647    static const auto ValidSatTys = {MVT::v8i8,  MVT::v16i8, MVT::v4i16,648                                     MVT::v8i16, MVT::v2i32, MVT::v4i32,649                                     MVT::v2i64};650    auto LT = getTypeLegalizationCost(RetTy);651    // This is a base cost of 1 for the vadd, plus 3 extract shifts if we652    // need to extend the type, as it uses shr(qadd(shl, shl)).653    unsigned Instrs =654        LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;655    if (any_of(ValidSatTys, [&LT](MVT M) { return M == LT.second; }))656      return LT.first * Instrs;657 658    TypeSize TS = getDataLayout().getTypeSizeInBits(RetTy);659    uint64_t VectorSize = TS.getKnownMinValue();660 661    if (ST->isSVEAvailable() && VectorSize >= 128 && isPowerOf2_64(VectorSize))662      return LT.first * Instrs;663 664    break;665  }666  case Intrinsic::abs: {667    static const auto ValidAbsTys = {MVT::v8i8,  MVT::v16i8, MVT::v4i16,668                                     MVT::v8i16, MVT::v2i32, MVT::v4i32,669                                     MVT::v2i64};670    auto LT = getTypeLegalizationCost(RetTy);671    if (any_of(ValidAbsTys, [&LT](MVT M) { return M == LT.second; }))672      return LT.first;673    break;674  }675  case Intrinsic::bswap: {676    static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,677                                     MVT::v4i32, MVT::v2i64};678    auto LT = getTypeLegalizationCost(RetTy);679    if (any_of(ValidAbsTys, [&LT](MVT M) { return M == LT.second; }) &&680        LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())681      return LT.first;682    break;683  }684  case Intrinsic::fma:685  case Intrinsic::fmuladd: {686    // Given a fma or fmuladd, cost it the same as a fmul instruction which are687    // usually the same for costs. TODO: Add fp16 and bf16 expansion costs.688    Type *EltTy = RetTy->getScalarType();689    if (EltTy->isFloatTy() || EltTy->isDoubleTy() ||690        (EltTy->isHalfTy() && ST->hasFullFP16()))691      return getArithmeticInstrCost(Instruction::FMul, RetTy, CostKind);692    break;693  }694  case Intrinsic::stepvector: {695    InstructionCost Cost = 1; // Cost of the `index' instruction696    auto LT = getTypeLegalizationCost(RetTy);697    // Legalisation of illegal vectors involves an `index' instruction plus698    // (LT.first - 1) vector adds.699    if (LT.first > 1) {700      Type *LegalVTy = EVT(LT.second).getTypeForEVT(RetTy->getContext());701      InstructionCost AddCost =702          getArithmeticInstrCost(Instruction::Add, LegalVTy, CostKind);703      Cost += AddCost * (LT.first - 1);704    }705    return Cost;706  }707  case Intrinsic::vector_extract:708  case Intrinsic::vector_insert: {709    // If both the vector and subvector types are legal types and the index710    // is 0, then this should be a no-op or simple operation; return a711    // relatively low cost.712 713    // If arguments aren't actually supplied, then we cannot determine the714    // value of the index. We also want to skip predicate types.715    if (ICA.getArgs().size() != ICA.getArgTypes().size() ||716        ICA.getReturnType()->getScalarType()->isIntegerTy(1))717      break;718 719    LLVMContext &C = RetTy->getContext();720    EVT VecVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);721    bool IsExtract = ICA.getID() == Intrinsic::vector_extract;722    EVT SubVecVT = IsExtract ? getTLI()->getValueType(DL, RetTy)723                             : getTLI()->getValueType(DL, ICA.getArgTypes()[1]);724    // Skip this if either the vector or subvector types are unpacked725    // SVE types; they may get lowered to stack stores and loads.726    if (isUnpackedVectorVT(VecVT) || isUnpackedVectorVT(SubVecVT))727      break;728 729    TargetLoweringBase::LegalizeKind SubVecLK =730        getTLI()->getTypeConversion(C, SubVecVT);731    TargetLoweringBase::LegalizeKind VecLK =732        getTLI()->getTypeConversion(C, VecVT);733    const Value *Idx = IsExtract ? ICA.getArgs()[1] : ICA.getArgs()[2];734    const ConstantInt *CIdx = cast<ConstantInt>(Idx);735    if (SubVecLK.first == TargetLoweringBase::TypeLegal &&736        VecLK.first == TargetLoweringBase::TypeLegal && CIdx->isZero())737      return TTI::TCC_Free;738    break;739  }740  case Intrinsic::bitreverse: {741    static const CostTblEntry BitreverseTbl[] = {742        {Intrinsic::bitreverse, MVT::i32, 1},743        {Intrinsic::bitreverse, MVT::i64, 1},744        {Intrinsic::bitreverse, MVT::v8i8, 1},745        {Intrinsic::bitreverse, MVT::v16i8, 1},746        {Intrinsic::bitreverse, MVT::v4i16, 2},747        {Intrinsic::bitreverse, MVT::v8i16, 2},748        {Intrinsic::bitreverse, MVT::v2i32, 2},749        {Intrinsic::bitreverse, MVT::v4i32, 2},750        {Intrinsic::bitreverse, MVT::v1i64, 2},751        {Intrinsic::bitreverse, MVT::v2i64, 2},752    };753    const auto LegalisationCost = getTypeLegalizationCost(RetTy);754    const auto *Entry =755        CostTableLookup(BitreverseTbl, ICA.getID(), LegalisationCost.second);756    if (Entry) {757      // Cost Model is using the legal type(i32) that i8 and i16 will be758      // converted to +1 so that we match the actual lowering cost759      if (TLI->getValueType(DL, RetTy, true) == MVT::i8 ||760          TLI->getValueType(DL, RetTy, true) == MVT::i16)761        return LegalisationCost.first * Entry->Cost + 1;762 763      return LegalisationCost.first * Entry->Cost;764    }765    break;766  }767  case Intrinsic::ctpop: {768    if (!ST->hasNEON()) {769      // 32-bit or 64-bit ctpop without NEON is 12 instructions.770      return getTypeLegalizationCost(RetTy).first * 12;771    }772    static const CostTblEntry CtpopCostTbl[] = {773        {ISD::CTPOP, MVT::v2i64, 4},774        {ISD::CTPOP, MVT::v4i32, 3},775        {ISD::CTPOP, MVT::v8i16, 2},776        {ISD::CTPOP, MVT::v16i8, 1},777        {ISD::CTPOP, MVT::i64,   4},778        {ISD::CTPOP, MVT::v2i32, 3},779        {ISD::CTPOP, MVT::v4i16, 2},780        {ISD::CTPOP, MVT::v8i8,  1},781        {ISD::CTPOP, MVT::i32,   5},782    };783    auto LT = getTypeLegalizationCost(RetTy);784    MVT MTy = LT.second;785    if (const auto *Entry = CostTableLookup(CtpopCostTbl, ISD::CTPOP, MTy)) {786      // Extra cost of +1 when illegal vector types are legalized by promoting787      // the integer type.788      int ExtraCost = MTy.isVector() && MTy.getScalarSizeInBits() !=789                                            RetTy->getScalarSizeInBits()790                          ? 1791                          : 0;792      return LT.first * Entry->Cost + ExtraCost;793    }794    break;795  }796  case Intrinsic::sadd_with_overflow:797  case Intrinsic::uadd_with_overflow:798  case Intrinsic::ssub_with_overflow:799  case Intrinsic::usub_with_overflow:800  case Intrinsic::smul_with_overflow:801  case Intrinsic::umul_with_overflow: {802    static const CostTblEntry WithOverflowCostTbl[] = {803        {Intrinsic::sadd_with_overflow, MVT::i8, 3},804        {Intrinsic::uadd_with_overflow, MVT::i8, 3},805        {Intrinsic::sadd_with_overflow, MVT::i16, 3},806        {Intrinsic::uadd_with_overflow, MVT::i16, 3},807        {Intrinsic::sadd_with_overflow, MVT::i32, 1},808        {Intrinsic::uadd_with_overflow, MVT::i32, 1},809        {Intrinsic::sadd_with_overflow, MVT::i64, 1},810        {Intrinsic::uadd_with_overflow, MVT::i64, 1},811        {Intrinsic::ssub_with_overflow, MVT::i8, 3},812        {Intrinsic::usub_with_overflow, MVT::i8, 3},813        {Intrinsic::ssub_with_overflow, MVT::i16, 3},814        {Intrinsic::usub_with_overflow, MVT::i16, 3},815        {Intrinsic::ssub_with_overflow, MVT::i32, 1},816        {Intrinsic::usub_with_overflow, MVT::i32, 1},817        {Intrinsic::ssub_with_overflow, MVT::i64, 1},818        {Intrinsic::usub_with_overflow, MVT::i64, 1},819        {Intrinsic::smul_with_overflow, MVT::i8, 5},820        {Intrinsic::umul_with_overflow, MVT::i8, 4},821        {Intrinsic::smul_with_overflow, MVT::i16, 5},822        {Intrinsic::umul_with_overflow, MVT::i16, 4},823        {Intrinsic::smul_with_overflow, MVT::i32, 2}, // eg umull;tst824        {Intrinsic::umul_with_overflow, MVT::i32, 2}, // eg umull;cmp sxtw825        {Intrinsic::smul_with_overflow, MVT::i64, 3}, // eg mul;smulh;cmp826        {Intrinsic::umul_with_overflow, MVT::i64, 3}, // eg mul;umulh;cmp asr827    };828    EVT MTy = TLI->getValueType(DL, RetTy->getContainedType(0), true);829    if (MTy.isSimple())830      if (const auto *Entry = CostTableLookup(WithOverflowCostTbl, ICA.getID(),831                                              MTy.getSimpleVT()))832        return Entry->Cost;833    break;834  }835  case Intrinsic::fptosi_sat:836  case Intrinsic::fptoui_sat: {837    if (ICA.getArgTypes().empty())838      break;839    bool IsSigned = ICA.getID() == Intrinsic::fptosi_sat;840    auto LT = getTypeLegalizationCost(ICA.getArgTypes()[0]);841    EVT MTy = TLI->getValueType(DL, RetTy);842    // Check for the legal types, which are where the size of the input and the843    // output are the same, or we are using cvt f64->i32 or f32->i64.844    if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||845         LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||846         LT.second == MVT::v2f64)) {847      if ((LT.second.getScalarSizeInBits() == MTy.getScalarSizeInBits() ||848           (LT.second == MVT::f64 && MTy == MVT::i32) ||849           (LT.second == MVT::f32 && MTy == MVT::i64)))850        return LT.first;851      // Extending vector types v2f32->v2i64, fcvtl*2 + fcvt*2852      if (LT.second.getScalarType() == MVT::f32 && MTy.isFixedLengthVector() &&853          MTy.getScalarSizeInBits() == 64)854        return LT.first * (MTy.getVectorNumElements() > 2 ? 4 : 2);855    }856    // Similarly for fp16 sizes. Without FullFP16 we generally need to fcvt to857    // f32.858    if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())859      return LT.first + getIntrinsicInstrCost(860                            {ICA.getID(),861                             RetTy,862                             {ICA.getArgTypes()[0]->getWithNewType(863                                 Type::getFloatTy(RetTy->getContext()))}},864                            CostKind);865    if ((LT.second == MVT::f16 && MTy == MVT::i32) ||866        (LT.second == MVT::f16 && MTy == MVT::i64) ||867        ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&868         (LT.second.getScalarSizeInBits() == MTy.getScalarSizeInBits())))869      return LT.first;870    // Extending vector types v8f16->v8i32, fcvtl*2 + fcvt*2871    if (LT.second.getScalarType() == MVT::f16 && MTy.isFixedLengthVector() &&872        MTy.getScalarSizeInBits() == 32)873      return LT.first * (MTy.getVectorNumElements() > 4 ? 4 : 2);874    // Extending vector types v8f16->v8i32. These current scalarize but the875    // codegen could be better.876    if (LT.second.getScalarType() == MVT::f16 && MTy.isFixedLengthVector() &&877        MTy.getScalarSizeInBits() == 64)878      return MTy.getVectorNumElements() * 3;879 880    // If we can we use a legal convert followed by a min+max881    if ((LT.second.getScalarType() == MVT::f32 ||882         LT.second.getScalarType() == MVT::f64 ||883         LT.second.getScalarType() == MVT::f16) &&884        LT.second.getScalarSizeInBits() >= MTy.getScalarSizeInBits()) {885      Type *LegalTy =886          Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());887      if (LT.second.isVector())888        LegalTy = VectorType::get(LegalTy, LT.second.getVectorElementCount());889      InstructionCost Cost = 1;890      IntrinsicCostAttributes Attrs1(IsSigned ? Intrinsic::smin : Intrinsic::umin,891                                    LegalTy, {LegalTy, LegalTy});892      Cost += getIntrinsicInstrCost(Attrs1, CostKind);893      IntrinsicCostAttributes Attrs2(IsSigned ? Intrinsic::smax : Intrinsic::umax,894                                    LegalTy, {LegalTy, LegalTy});895      Cost += getIntrinsicInstrCost(Attrs2, CostKind);896      return LT.first * Cost +897             ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0898                                                                           : 1);899    }900    // Otherwise we need to follow the default expansion that clamps the value901    // using a float min/max with a fcmp+sel for nan handling when signed.902    Type *FPTy = ICA.getArgTypes()[0]->getScalarType();903    RetTy = RetTy->getScalarType();904    if (LT.second.isVector()) {905      FPTy = VectorType::get(FPTy, LT.second.getVectorElementCount());906      RetTy = VectorType::get(RetTy, LT.second.getVectorElementCount());907    }908    IntrinsicCostAttributes Attrs1(Intrinsic::minnum, FPTy, {FPTy, FPTy});909    InstructionCost Cost = getIntrinsicInstrCost(Attrs1, CostKind);910    IntrinsicCostAttributes Attrs2(Intrinsic::maxnum, FPTy, {FPTy, FPTy});911    Cost += getIntrinsicInstrCost(Attrs2, CostKind);912    Cost +=913        getCastInstrCost(IsSigned ? Instruction::FPToSI : Instruction::FPToUI,914                         RetTy, FPTy, TTI::CastContextHint::None, CostKind);915    if (IsSigned) {916      Type *CondTy = RetTy->getWithNewBitWidth(1);917      Cost += getCmpSelInstrCost(BinaryOperator::FCmp, FPTy, CondTy,918                                 CmpInst::FCMP_UNO, CostKind);919      Cost += getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy,920                                 CmpInst::FCMP_UNO, CostKind);921    }922    return LT.first * Cost;923  }924  case Intrinsic::fshl:925  case Intrinsic::fshr: {926    if (ICA.getArgs().empty())927      break;928 929    const TTI::OperandValueInfo OpInfoZ = TTI::getOperandInfo(ICA.getArgs()[2]);930 931    // ROTR / ROTL is a funnel shift with equal first and second operand. For932    // ROTR on integer registers (i32/i64) this can be done in a single ror933    // instruction. A fshl with a non-constant shift uses a neg + ror.934    if (RetTy->isIntegerTy() && ICA.getArgs()[0] == ICA.getArgs()[1] &&935        (RetTy->getPrimitiveSizeInBits() == 32 ||936         RetTy->getPrimitiveSizeInBits() == 64)) {937      InstructionCost NegCost =938          (ICA.getID() == Intrinsic::fshl && !OpInfoZ.isConstant()) ? 1 : 0;939      return 1 + NegCost;940    }941 942    // TODO: Add handling for fshl where third argument is not a constant.943    if (!OpInfoZ.isConstant())944      break;945 946    const auto LegalisationCost = getTypeLegalizationCost(RetTy);947    if (OpInfoZ.isUniform()) {948      static const CostTblEntry FshlTbl[] = {949          {Intrinsic::fshl, MVT::v4i32, 2}, // shl + usra950          {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},951          {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},952          {Intrinsic::fshl, MVT::v8i8, 2},  {Intrinsic::fshl, MVT::v4i16, 2}};953      // Costs for both fshl & fshr are the same, so just pass Intrinsic::fshl954      // to avoid having to duplicate the costs.955      const auto *Entry =956          CostTableLookup(FshlTbl, Intrinsic::fshl, LegalisationCost.second);957      if (Entry)958        return LegalisationCost.first * Entry->Cost;959    }960 961    auto TyL = getTypeLegalizationCost(RetTy);962    if (!RetTy->isIntegerTy())963      break;964 965    // Estimate cost manually, as types like i8 and i16 will get promoted to966    // i32 and CostTableLookup will ignore the extra conversion cost.967    bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&968                       RetTy->getScalarSizeInBits() < 64) ||969                      (RetTy->getScalarSizeInBits() % 64 != 0);970    unsigned ExtraCost = HigherCost ? 1 : 0;971    if (RetTy->getScalarSizeInBits() == 32 ||972        RetTy->getScalarSizeInBits() == 64)973      ExtraCost = 0; // fhsl/fshr for i32 and i64 can be lowered to a single974                     // extr instruction.975    else if (HigherCost)976      ExtraCost = 1;977    else978      break;979    return TyL.first + ExtraCost;980  }981  case Intrinsic::get_active_lane_mask: {982    auto RetTy = cast<VectorType>(ICA.getReturnType());983    EVT RetVT = getTLI()->getValueType(DL, RetTy);984    EVT OpVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);985    if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))986      break;987 988    if (RetTy->isScalableTy()) {989      if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=990          TargetLowering::TypeSplitVector)991        break;992 993      auto LT = getTypeLegalizationCost(RetTy);994      InstructionCost Cost = LT.first;995      // When SVE2p1 or SME2 is available, we can halve getTypeLegalizationCost996      // as get_active_lane_mask may lower to the sve_whilelo_x2 intrinsic, e.g.997      //   nxv32i1 = get_active_lane_mask(base, idx) ->998      //    {nxv16i1, nxv16i1} = sve_whilelo_x2(base, idx)999      if (ST->hasSVE2p1() || ST->hasSME2()) {1000        Cost /= 2;1001        if (Cost == 1)1002          return Cost;1003      }1004 1005      // If more than one whilelo intrinsic is required, include the extra cost1006      // required by the saturating add & select required to increment the1007      // start value after the first intrinsic call.1008      Type *OpTy = ICA.getArgTypes()[0];1009      IntrinsicCostAttributes AddAttrs(Intrinsic::uadd_sat, OpTy, {OpTy, OpTy});1010      InstructionCost SplitCost = getIntrinsicInstrCost(AddAttrs, CostKind);1011      Type *CondTy = OpTy->getWithNewBitWidth(1);1012      SplitCost += getCmpSelInstrCost(Instruction::Select, OpTy, CondTy,1013                                      CmpInst::ICMP_UGT, CostKind);1014      return Cost + (SplitCost * (Cost - 1));1015    } else if (!getTLI()->isTypeLegal(RetVT)) {1016      // We don't have enough context at this point to determine if the mask1017      // is going to be kept live after the block, which will force the vXi11018      // type to be expanded to legal vectors of integers, e.g. v4i1->v4i32.1019      // For now, we just assume the vectorizer created this intrinsic and1020      // the result will be the input for a PHI. In this case the cost will1021      // be extremely high for fixed-width vectors.1022      // NOTE: getScalarizationOverhead returns a cost that's far too1023      // pessimistic for the actual generated codegen. In reality there are1024      // two instructions generated per lane.1025      return cast<FixedVectorType>(RetTy)->getNumElements() * 2;1026    }1027    break;1028  }1029  case Intrinsic::experimental_vector_match: {1030    auto *NeedleTy = cast<FixedVectorType>(ICA.getArgTypes()[1]);1031    EVT SearchVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);1032    unsigned SearchSize = NeedleTy->getNumElements();1033    if (!getTLI()->shouldExpandVectorMatch(SearchVT, SearchSize)) {1034      // Base cost for MATCH instructions. At least on the Neoverse V2 and1035      // Neoverse V3, these are cheap operations with the same latency as a1036      // vector ADD. In most cases, however, we also need to do an extra DUP.1037      // For fixed-length vectors we currently need an extra five--six1038      // instructions besides the MATCH.1039      InstructionCost Cost = 4;1040      if (isa<FixedVectorType>(RetTy))1041        Cost += 10;1042      return Cost;1043    }1044    break;1045  }1046  case Intrinsic::experimental_cttz_elts: {1047    EVT ArgVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);1048    if (!getTLI()->shouldExpandCttzElements(ArgVT)) {1049      // This will consist of a SVE brkb and a cntp instruction. These1050      // typically have the same latency and half the throughput as a vector1051      // add instruction.1052      return 4;1053    }1054    break;1055  }1056  case Intrinsic::experimental_vector_extract_last_active:1057    if (ST->isSVEorStreamingSVEAvailable()) {1058      auto [LegalCost, _] = getTypeLegalizationCost(ICA.getArgTypes()[0]);1059      // This should turn into chained clastb instructions.1060      return LegalCost;1061    }1062    break;1063  default:1064    break;1065  }1066  return BaseT::getIntrinsicInstrCost(ICA, CostKind);1067}1068 1069/// The function will remove redundant reinterprets casting in the presence1070/// of the control flow1071static std::optional<Instruction *> processPhiNode(InstCombiner &IC,1072                                                   IntrinsicInst &II) {1073  SmallVector<Instruction *, 32> Worklist;1074  auto RequiredType = II.getType();1075 1076  auto *PN = dyn_cast<PHINode>(II.getArgOperand(0));1077  assert(PN && "Expected Phi Node!");1078 1079  // Don't create a new Phi unless we can remove the old one.1080  if (!PN->hasOneUse())1081    return std::nullopt;1082 1083  for (Value *IncValPhi : PN->incoming_values()) {1084    auto *Reinterpret = dyn_cast<IntrinsicInst>(IncValPhi);1085    if (!Reinterpret ||1086        Reinterpret->getIntrinsicID() !=1087            Intrinsic::aarch64_sve_convert_to_svbool ||1088        RequiredType != Reinterpret->getArgOperand(0)->getType())1089      return std::nullopt;1090  }1091 1092  // Create the new Phi1093  IC.Builder.SetInsertPoint(PN);1094  PHINode *NPN = IC.Builder.CreatePHI(RequiredType, PN->getNumIncomingValues());1095  Worklist.push_back(PN);1096 1097  for (unsigned I = 0; I < PN->getNumIncomingValues(); I++) {1098    auto *Reinterpret = cast<Instruction>(PN->getIncomingValue(I));1099    NPN->addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(I));1100    Worklist.push_back(Reinterpret);1101  }1102 1103  // Cleanup Phi Node and reinterprets1104  return IC.replaceInstUsesWith(II, NPN);1105}1106 1107// A collection of properties common to SVE intrinsics that allow for combines1108// to be written without needing to know the specific intrinsic.1109struct SVEIntrinsicInfo {1110  //1111  // Helper routines for common intrinsic definitions.1112  //1113 1114  // e.g. llvm.aarch64.sve.add pg, op1, op21115  //        with IID ==> llvm.aarch64.sve.add_u1116  static SVEIntrinsicInfo1117  defaultMergingOp(Intrinsic::ID IID = Intrinsic::not_intrinsic) {1118    return SVEIntrinsicInfo()1119        .setGoverningPredicateOperandIdx(0)1120        .setOperandIdxInactiveLanesTakenFrom(1)1121        .setMatchingUndefIntrinsic(IID);1122  }1123 1124  // e.g. llvm.aarch64.sve.neg inactive, pg, op1125  static SVEIntrinsicInfo defaultMergingUnaryOp() {1126    return SVEIntrinsicInfo()1127        .setGoverningPredicateOperandIdx(1)1128        .setOperandIdxInactiveLanesTakenFrom(0)1129        .setOperandIdxWithNoActiveLanes(0);1130  }1131 1132  // e.g. llvm.aarch64.sve.fcvtnt inactive, pg, op1133  static SVEIntrinsicInfo defaultMergingUnaryNarrowingTopOp() {1134    return SVEIntrinsicInfo()1135        .setGoverningPredicateOperandIdx(1)1136        .setOperandIdxInactiveLanesTakenFrom(0);1137  }1138 1139  // e.g. llvm.aarch64.sve.add_u pg, op1, op21140  static SVEIntrinsicInfo defaultUndefOp() {1141    return SVEIntrinsicInfo()1142        .setGoverningPredicateOperandIdx(0)1143        .setInactiveLanesAreNotDefined();1144  }1145 1146  // e.g. llvm.aarch64.sve.prf pg, ptr        (GPIndex = 0)1147  //      llvm.aarch64.sve.st1 data, pg, ptr  (GPIndex = 1)1148  static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex) {1149    return SVEIntrinsicInfo()1150        .setGoverningPredicateOperandIdx(GPIndex)1151        .setInactiveLanesAreUnused();1152  }1153 1154  // e.g. llvm.aarch64.sve.cmpeq pg, op1, op21155  //      llvm.aarch64.sve.ld1 pg, ptr1156  static SVEIntrinsicInfo defaultZeroingOp() {1157    return SVEIntrinsicInfo()1158        .setGoverningPredicateOperandIdx(0)1159        .setInactiveLanesAreUnused()1160        .setResultIsZeroInitialized();1161  }1162 1163  // All properties relate to predication and thus having a general predicate1164  // is the minimum requirement to say there is intrinsic info to act on.1165  explicit operator bool() const { return hasGoverningPredicate(); }1166 1167  //1168  // Properties relating to the governing predicate.1169  //1170 1171  bool hasGoverningPredicate() const {1172    return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();1173  }1174 1175  unsigned getGoverningPredicateOperandIdx() const {1176    assert(hasGoverningPredicate() && "Propery not set!");1177    return GoverningPredicateIdx;1178  }1179 1180  SVEIntrinsicInfo &setGoverningPredicateOperandIdx(unsigned Index) {1181    assert(!hasGoverningPredicate() && "Cannot set property twice!");1182    GoverningPredicateIdx = Index;1183    return *this;1184  }1185 1186  //1187  // Properties relating to operations the intrinsic could be transformed into.1188  // NOTE: This does not mean such a transformation is always possible, but the1189  // knowledge makes it possible to reuse existing optimisations without needing1190  // to embed specific handling for each intrinsic. For example, instruction1191  // simplification can be used to optimise an intrinsic's active lanes.1192  //1193 1194  bool hasMatchingUndefIntrinsic() const {1195    return UndefIntrinsic != Intrinsic::not_intrinsic;1196  }1197 1198  Intrinsic::ID getMatchingUndefIntrinsic() const {1199    assert(hasMatchingUndefIntrinsic() && "Propery not set!");1200    return UndefIntrinsic;1201  }1202 1203  SVEIntrinsicInfo &setMatchingUndefIntrinsic(Intrinsic::ID IID) {1204    assert(!hasMatchingUndefIntrinsic() && "Cannot set property twice!");1205    UndefIntrinsic = IID;1206    return *this;1207  }1208 1209  bool hasMatchingIROpode() const { return IROpcode != 0; }1210 1211  unsigned getMatchingIROpode() const {1212    assert(hasMatchingIROpode() && "Propery not set!");1213    return IROpcode;1214  }1215 1216  SVEIntrinsicInfo &setMatchingIROpcode(unsigned Opcode) {1217    assert(!hasMatchingIROpode() && "Cannot set property twice!");1218    IROpcode = Opcode;1219    return *this;1220  }1221 1222  //1223  // Properties relating to the result of inactive lanes.1224  //1225 1226  bool inactiveLanesTakenFromOperand() const {1227    return ResultLanes == InactiveLanesTakenFromOperand;1228  }1229 1230  unsigned getOperandIdxInactiveLanesTakenFrom() const {1231    assert(inactiveLanesTakenFromOperand() && "Propery not set!");1232    return OperandIdxForInactiveLanes;1233  }1234 1235  SVEIntrinsicInfo &setOperandIdxInactiveLanesTakenFrom(unsigned Index) {1236    assert(ResultLanes == Uninitialized && "Cannot set property twice!");1237    ResultLanes = InactiveLanesTakenFromOperand;1238    OperandIdxForInactiveLanes = Index;1239    return *this;1240  }1241 1242  bool inactiveLanesAreNotDefined() const {1243    return ResultLanes == InactiveLanesAreNotDefined;1244  }1245 1246  SVEIntrinsicInfo &setInactiveLanesAreNotDefined() {1247    assert(ResultLanes == Uninitialized && "Cannot set property twice!");1248    ResultLanes = InactiveLanesAreNotDefined;1249    return *this;1250  }1251 1252  bool inactiveLanesAreUnused() const {1253    return ResultLanes == InactiveLanesAreUnused;1254  }1255 1256  SVEIntrinsicInfo &setInactiveLanesAreUnused() {1257    assert(ResultLanes == Uninitialized && "Cannot set property twice!");1258    ResultLanes = InactiveLanesAreUnused;1259    return *this;1260  }1261 1262  // NOTE: Whilst not limited to only inactive lanes, the common use case is:1263  // inactiveLanesAreZeroed =1264  //     resultIsZeroInitialized() && inactiveLanesAreUnused()1265  bool resultIsZeroInitialized() const { return ResultIsZeroInitialized; }1266 1267  SVEIntrinsicInfo &setResultIsZeroInitialized() {1268    ResultIsZeroInitialized = true;1269    return *this;1270  }1271 1272  //1273  // The first operand of unary merging operations is typically only used to1274  // set the result for inactive lanes. Knowing this allows us to deadcode the1275  // operand when we can prove there are no inactive lanes.1276  //1277 1278  bool hasOperandWithNoActiveLanes() const {1279    return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();1280  }1281 1282  unsigned getOperandIdxWithNoActiveLanes() const {1283    assert(hasOperandWithNoActiveLanes() && "Propery not set!");1284    return OperandIdxWithNoActiveLanes;1285  }1286 1287  SVEIntrinsicInfo &setOperandIdxWithNoActiveLanes(unsigned Index) {1288    assert(!hasOperandWithNoActiveLanes() && "Cannot set property twice!");1289    OperandIdxWithNoActiveLanes = Index;1290    return *this;1291  }1292 1293private:1294  unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();1295 1296  Intrinsic::ID UndefIntrinsic = Intrinsic::not_intrinsic;1297  unsigned IROpcode = 0;1298 1299  enum PredicationStyle {1300    Uninitialized,1301    InactiveLanesTakenFromOperand,1302    InactiveLanesAreNotDefined,1303    InactiveLanesAreUnused1304  } ResultLanes = Uninitialized;1305 1306  bool ResultIsZeroInitialized = false;1307  unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();1308  unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();1309};1310 1311static SVEIntrinsicInfo constructSVEIntrinsicInfo(IntrinsicInst &II) {1312  // Some SVE intrinsics do not use scalable vector types, but since they are1313  // not relevant from an SVEIntrinsicInfo perspective, they are also ignored.1314  if (!isa<ScalableVectorType>(II.getType()) &&1315      all_of(II.args(), [&](const Value *V) {1316        return !isa<ScalableVectorType>(V->getType());1317      }))1318    return SVEIntrinsicInfo();1319 1320  Intrinsic::ID IID = II.getIntrinsicID();1321  switch (IID) {1322  default:1323    break;1324  case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:1325  case Intrinsic::aarch64_sve_fcvt_f16f32:1326  case Intrinsic::aarch64_sve_fcvt_f16f64:1327  case Intrinsic::aarch64_sve_fcvt_f32f16:1328  case Intrinsic::aarch64_sve_fcvt_f32f64:1329  case Intrinsic::aarch64_sve_fcvt_f64f16:1330  case Intrinsic::aarch64_sve_fcvt_f64f32:1331  case Intrinsic::aarch64_sve_fcvtlt_f32f16:1332  case Intrinsic::aarch64_sve_fcvtlt_f64f32:1333  case Intrinsic::aarch64_sve_fcvtx_f32f64:1334  case Intrinsic::aarch64_sve_fcvtzs:1335  case Intrinsic::aarch64_sve_fcvtzs_i32f16:1336  case Intrinsic::aarch64_sve_fcvtzs_i32f64:1337  case Intrinsic::aarch64_sve_fcvtzs_i64f16:1338  case Intrinsic::aarch64_sve_fcvtzs_i64f32:1339  case Intrinsic::aarch64_sve_fcvtzu:1340  case Intrinsic::aarch64_sve_fcvtzu_i32f16:1341  case Intrinsic::aarch64_sve_fcvtzu_i32f64:1342  case Intrinsic::aarch64_sve_fcvtzu_i64f16:1343  case Intrinsic::aarch64_sve_fcvtzu_i64f32:1344  case Intrinsic::aarch64_sve_scvtf:1345  case Intrinsic::aarch64_sve_scvtf_f16i32:1346  case Intrinsic::aarch64_sve_scvtf_f16i64:1347  case Intrinsic::aarch64_sve_scvtf_f32i64:1348  case Intrinsic::aarch64_sve_scvtf_f64i32:1349  case Intrinsic::aarch64_sve_ucvtf:1350  case Intrinsic::aarch64_sve_ucvtf_f16i32:1351  case Intrinsic::aarch64_sve_ucvtf_f16i64:1352  case Intrinsic::aarch64_sve_ucvtf_f32i64:1353  case Intrinsic::aarch64_sve_ucvtf_f64i32:1354    return SVEIntrinsicInfo::defaultMergingUnaryOp();1355 1356  case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:1357  case Intrinsic::aarch64_sve_fcvtnt_f16f32:1358  case Intrinsic::aarch64_sve_fcvtnt_f32f64:1359  case Intrinsic::aarch64_sve_fcvtxnt_f32f64:1360    return SVEIntrinsicInfo::defaultMergingUnaryNarrowingTopOp();1361 1362  case Intrinsic::aarch64_sve_fabd:1363    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fabd_u);1364  case Intrinsic::aarch64_sve_fadd:1365    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fadd_u)1366        .setMatchingIROpcode(Instruction::FAdd);1367  case Intrinsic::aarch64_sve_fdiv:1368    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fdiv_u)1369        .setMatchingIROpcode(Instruction::FDiv);1370  case Intrinsic::aarch64_sve_fmax:1371    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmax_u);1372  case Intrinsic::aarch64_sve_fmaxnm:1373    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmaxnm_u);1374  case Intrinsic::aarch64_sve_fmin:1375    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmin_u);1376  case Intrinsic::aarch64_sve_fminnm:1377    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fminnm_u);1378  case Intrinsic::aarch64_sve_fmla:1379    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmla_u);1380  case Intrinsic::aarch64_sve_fmls:1381    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmls_u);1382  case Intrinsic::aarch64_sve_fmul:1383    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmul_u)1384        .setMatchingIROpcode(Instruction::FMul);1385  case Intrinsic::aarch64_sve_fmulx:1386    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmulx_u);1387  case Intrinsic::aarch64_sve_fnmla:1388    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fnmla_u);1389  case Intrinsic::aarch64_sve_fnmls:1390    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fnmls_u);1391  case Intrinsic::aarch64_sve_fsub:1392    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fsub_u)1393        .setMatchingIROpcode(Instruction::FSub);1394  case Intrinsic::aarch64_sve_add:1395    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_add_u)1396        .setMatchingIROpcode(Instruction::Add);1397  case Intrinsic::aarch64_sve_mla:1398    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_mla_u);1399  case Intrinsic::aarch64_sve_mls:1400    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_mls_u);1401  case Intrinsic::aarch64_sve_mul:1402    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_mul_u)1403        .setMatchingIROpcode(Instruction::Mul);1404  case Intrinsic::aarch64_sve_sabd:1405    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sabd_u);1406  case Intrinsic::aarch64_sve_sdiv:1407    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sdiv_u)1408        .setMatchingIROpcode(Instruction::SDiv);1409  case Intrinsic::aarch64_sve_smax:1410    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_smax_u);1411  case Intrinsic::aarch64_sve_smin:1412    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_smin_u);1413  case Intrinsic::aarch64_sve_smulh:1414    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_smulh_u);1415  case Intrinsic::aarch64_sve_sub:1416    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sub_u)1417        .setMatchingIROpcode(Instruction::Sub);1418  case Intrinsic::aarch64_sve_uabd:1419    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uabd_u);1420  case Intrinsic::aarch64_sve_udiv:1421    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_udiv_u)1422        .setMatchingIROpcode(Instruction::UDiv);1423  case Intrinsic::aarch64_sve_umax:1424    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_umax_u);1425  case Intrinsic::aarch64_sve_umin:1426    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_umin_u);1427  case Intrinsic::aarch64_sve_umulh:1428    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_umulh_u);1429  case Intrinsic::aarch64_sve_asr:1430    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_asr_u)1431        .setMatchingIROpcode(Instruction::AShr);1432  case Intrinsic::aarch64_sve_lsl:1433    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_lsl_u)1434        .setMatchingIROpcode(Instruction::Shl);1435  case Intrinsic::aarch64_sve_lsr:1436    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_lsr_u)1437        .setMatchingIROpcode(Instruction::LShr);1438  case Intrinsic::aarch64_sve_and:1439    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_and_u)1440        .setMatchingIROpcode(Instruction::And);1441  case Intrinsic::aarch64_sve_bic:1442    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_bic_u);1443  case Intrinsic::aarch64_sve_eor:1444    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_eor_u)1445        .setMatchingIROpcode(Instruction::Xor);1446  case Intrinsic::aarch64_sve_orr:1447    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_orr_u)1448        .setMatchingIROpcode(Instruction::Or);1449  case Intrinsic::aarch64_sve_sqsub:1450    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sqsub_u);1451  case Intrinsic::aarch64_sve_uqsub:1452    return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uqsub_u);1453 1454  case Intrinsic::aarch64_sve_add_u:1455    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1456        Instruction::Add);1457  case Intrinsic::aarch64_sve_and_u:1458    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1459        Instruction::And);1460  case Intrinsic::aarch64_sve_asr_u:1461    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1462        Instruction::AShr);1463  case Intrinsic::aarch64_sve_eor_u:1464    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1465        Instruction::Xor);1466  case Intrinsic::aarch64_sve_fadd_u:1467    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1468        Instruction::FAdd);1469  case Intrinsic::aarch64_sve_fdiv_u:1470    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1471        Instruction::FDiv);1472  case Intrinsic::aarch64_sve_fmul_u:1473    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1474        Instruction::FMul);1475  case Intrinsic::aarch64_sve_fsub_u:1476    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1477        Instruction::FSub);1478  case Intrinsic::aarch64_sve_lsl_u:1479    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1480        Instruction::Shl);1481  case Intrinsic::aarch64_sve_lsr_u:1482    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1483        Instruction::LShr);1484  case Intrinsic::aarch64_sve_mul_u:1485    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1486        Instruction::Mul);1487  case Intrinsic::aarch64_sve_orr_u:1488    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1489        Instruction::Or);1490  case Intrinsic::aarch64_sve_sdiv_u:1491    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1492        Instruction::SDiv);1493  case Intrinsic::aarch64_sve_sub_u:1494    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1495        Instruction::Sub);1496  case Intrinsic::aarch64_sve_udiv_u:1497    return SVEIntrinsicInfo::defaultUndefOp().setMatchingIROpcode(1498        Instruction::UDiv);1499 1500  case Intrinsic::aarch64_sve_addqv:1501  case Intrinsic::aarch64_sve_and_z:1502  case Intrinsic::aarch64_sve_bic_z:1503  case Intrinsic::aarch64_sve_brka_z:1504  case Intrinsic::aarch64_sve_brkb_z:1505  case Intrinsic::aarch64_sve_brkn_z:1506  case Intrinsic::aarch64_sve_brkpa_z:1507  case Intrinsic::aarch64_sve_brkpb_z:1508  case Intrinsic::aarch64_sve_cntp:1509  case Intrinsic::aarch64_sve_compact:1510  case Intrinsic::aarch64_sve_eor_z:1511  case Intrinsic::aarch64_sve_eorv:1512  case Intrinsic::aarch64_sve_eorqv:1513  case Intrinsic::aarch64_sve_nand_z:1514  case Intrinsic::aarch64_sve_nor_z:1515  case Intrinsic::aarch64_sve_orn_z:1516  case Intrinsic::aarch64_sve_orr_z:1517  case Intrinsic::aarch64_sve_orv:1518  case Intrinsic::aarch64_sve_orqv:1519  case Intrinsic::aarch64_sve_pnext:1520  case Intrinsic::aarch64_sve_rdffr_z:1521  case Intrinsic::aarch64_sve_saddv:1522  case Intrinsic::aarch64_sve_uaddv:1523  case Intrinsic::aarch64_sve_umaxv:1524  case Intrinsic::aarch64_sve_umaxqv:1525  case Intrinsic::aarch64_sve_cmpeq:1526  case Intrinsic::aarch64_sve_cmpeq_wide:1527  case Intrinsic::aarch64_sve_cmpge:1528  case Intrinsic::aarch64_sve_cmpge_wide:1529  case Intrinsic::aarch64_sve_cmpgt:1530  case Intrinsic::aarch64_sve_cmpgt_wide:1531  case Intrinsic::aarch64_sve_cmphi:1532  case Intrinsic::aarch64_sve_cmphi_wide:1533  case Intrinsic::aarch64_sve_cmphs:1534  case Intrinsic::aarch64_sve_cmphs_wide:1535  case Intrinsic::aarch64_sve_cmple_wide:1536  case Intrinsic::aarch64_sve_cmplo_wide:1537  case Intrinsic::aarch64_sve_cmpls_wide:1538  case Intrinsic::aarch64_sve_cmplt_wide:1539  case Intrinsic::aarch64_sve_cmpne:1540  case Intrinsic::aarch64_sve_cmpne_wide:1541  case Intrinsic::aarch64_sve_facge:1542  case Intrinsic::aarch64_sve_facgt:1543  case Intrinsic::aarch64_sve_fcmpeq:1544  case Intrinsic::aarch64_sve_fcmpge:1545  case Intrinsic::aarch64_sve_fcmpgt:1546  case Intrinsic::aarch64_sve_fcmpne:1547  case Intrinsic::aarch64_sve_fcmpuo:1548  case Intrinsic::aarch64_sve_ld1:1549  case Intrinsic::aarch64_sve_ld1_gather:1550  case Intrinsic::aarch64_sve_ld1_gather_index:1551  case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:1552  case Intrinsic::aarch64_sve_ld1_gather_sxtw:1553  case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:1554  case Intrinsic::aarch64_sve_ld1_gather_uxtw:1555  case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:1556  case Intrinsic::aarch64_sve_ld1q_gather_index:1557  case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:1558  case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:1559  case Intrinsic::aarch64_sve_ld1ro:1560  case Intrinsic::aarch64_sve_ld1rq:1561  case Intrinsic::aarch64_sve_ld1udq:1562  case Intrinsic::aarch64_sve_ld1uwq:1563  case Intrinsic::aarch64_sve_ld2_sret:1564  case Intrinsic::aarch64_sve_ld2q_sret:1565  case Intrinsic::aarch64_sve_ld3_sret:1566  case Intrinsic::aarch64_sve_ld3q_sret:1567  case Intrinsic::aarch64_sve_ld4_sret:1568  case Intrinsic::aarch64_sve_ld4q_sret:1569  case Intrinsic::aarch64_sve_ldff1:1570  case Intrinsic::aarch64_sve_ldff1_gather:1571  case Intrinsic::aarch64_sve_ldff1_gather_index:1572  case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:1573  case Intrinsic::aarch64_sve_ldff1_gather_sxtw:1574  case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:1575  case Intrinsic::aarch64_sve_ldff1_gather_uxtw:1576  case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:1577  case Intrinsic::aarch64_sve_ldnf1:1578  case Intrinsic::aarch64_sve_ldnt1:1579  case Intrinsic::aarch64_sve_ldnt1_gather:1580  case Intrinsic::aarch64_sve_ldnt1_gather_index:1581  case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:1582  case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:1583    return SVEIntrinsicInfo::defaultZeroingOp();1584 1585  case Intrinsic::aarch64_sve_prf:1586  case Intrinsic::aarch64_sve_prfb_gather_index:1587  case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:1588  case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:1589  case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:1590  case Intrinsic::aarch64_sve_prfd_gather_index:1591  case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:1592  case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:1593  case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:1594  case Intrinsic::aarch64_sve_prfh_gather_index:1595  case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:1596  case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:1597  case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:1598  case Intrinsic::aarch64_sve_prfw_gather_index:1599  case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:1600  case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:1601  case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:1602    return SVEIntrinsicInfo::defaultVoidOp(0);1603 1604  case Intrinsic::aarch64_sve_st1_scatter:1605  case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:1606  case Intrinsic::aarch64_sve_st1_scatter_sxtw:1607  case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:1608  case Intrinsic::aarch64_sve_st1_scatter_uxtw:1609  case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:1610  case Intrinsic::aarch64_sve_st1dq:1611  case Intrinsic::aarch64_sve_st1q_scatter_index:1612  case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:1613  case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:1614  case Intrinsic::aarch64_sve_st1wq:1615  case Intrinsic::aarch64_sve_stnt1:1616  case Intrinsic::aarch64_sve_stnt1_scatter:1617  case Intrinsic::aarch64_sve_stnt1_scatter_index:1618  case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:1619  case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:1620    return SVEIntrinsicInfo::defaultVoidOp(1);1621  case Intrinsic::aarch64_sve_st2:1622  case Intrinsic::aarch64_sve_st2q:1623    return SVEIntrinsicInfo::defaultVoidOp(2);1624  case Intrinsic::aarch64_sve_st3:1625  case Intrinsic::aarch64_sve_st3q:1626    return SVEIntrinsicInfo::defaultVoidOp(3);1627  case Intrinsic::aarch64_sve_st4:1628  case Intrinsic::aarch64_sve_st4q:1629    return SVEIntrinsicInfo::defaultVoidOp(4);1630  }1631 1632  return SVEIntrinsicInfo();1633}1634 1635static bool isAllActivePredicate(Value *Pred) {1636  Value *UncastedPred;1637 1638  // Look through predicate casts that only remove lanes.1639  if (match(Pred, m_Intrinsic<Intrinsic::aarch64_sve_convert_from_svbool>(1640                      m_Value(UncastedPred)))) {1641    auto *OrigPredTy = cast<ScalableVectorType>(Pred->getType());1642    Pred = UncastedPred;1643 1644    if (match(Pred, m_Intrinsic<Intrinsic::aarch64_sve_convert_to_svbool>(1645                        m_Value(UncastedPred))))1646      // If the predicate has the same or less lanes than the uncasted predicate1647      // then we know the casting has no effect.1648      if (OrigPredTy->getMinNumElements() <=1649          cast<ScalableVectorType>(UncastedPred->getType())1650              ->getMinNumElements())1651        Pred = UncastedPred;1652  }1653 1654  auto *C = dyn_cast<Constant>(Pred);1655  return C && C->isAllOnesValue();1656}1657 1658// Simplify `V` by only considering the operations that affect active lanes.1659// This function should only return existing Values or newly created Constants.1660static Value *stripInactiveLanes(Value *V, const Value *Pg) {1661  auto *Dup = dyn_cast<IntrinsicInst>(V);1662  if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&1663      Dup->getOperand(1) == Pg && isa<Constant>(Dup->getOperand(2)))1664    return ConstantVector::getSplat(1665        cast<VectorType>(V->getType())->getElementCount(),1666        cast<Constant>(Dup->getOperand(2)));1667 1668  return V;1669}1670 1671static std::optional<Instruction *>1672simplifySVEIntrinsicBinOp(InstCombiner &IC, IntrinsicInst &II,1673                          const SVEIntrinsicInfo &IInfo) {1674  const unsigned Opc = IInfo.getMatchingIROpode();1675  assert(Instruction::isBinaryOp(Opc) && "Expected a binary operation!");1676 1677  Value *Pg = II.getOperand(0);1678  Value *Op1 = II.getOperand(1);1679  Value *Op2 = II.getOperand(2);1680  const DataLayout &DL = II.getDataLayout();1681 1682  // Canonicalise constants to the RHS.1683  if (Instruction::isCommutative(Opc) && IInfo.inactiveLanesAreNotDefined() &&1684      isa<Constant>(Op1) && !isa<Constant>(Op2)) {1685    IC.replaceOperand(II, 1, Op2);1686    IC.replaceOperand(II, 2, Op1);1687    return &II;1688  }1689 1690  // Only active lanes matter when simplifying the operation.1691  Op1 = stripInactiveLanes(Op1, Pg);1692  Op2 = stripInactiveLanes(Op2, Pg);1693 1694  Value *SimpleII;1695  if (auto FII = dyn_cast<FPMathOperator>(&II))1696    SimpleII = simplifyBinOp(Opc, Op1, Op2, FII->getFastMathFlags(), DL);1697  else1698    SimpleII = simplifyBinOp(Opc, Op1, Op2, DL);1699 1700  // An SVE intrinsic's result is always defined. However, this is not the case1701  // for its equivalent IR instruction (e.g. when shifting by an amount more1702  // than the data's bitwidth). Simplifications to an undefined result must be1703  // ignored to preserve the intrinsic's expected behaviour.1704  if (!SimpleII || isa<UndefValue>(SimpleII))1705    return std::nullopt;1706 1707  if (IInfo.inactiveLanesAreNotDefined())1708    return IC.replaceInstUsesWith(II, SimpleII);1709 1710  Value *Inactive = II.getOperand(IInfo.getOperandIdxInactiveLanesTakenFrom());1711 1712  // The intrinsic does nothing (e.g. sve.mul(pg, A, 1.0)).1713  if (SimpleII == Inactive)1714    return IC.replaceInstUsesWith(II, SimpleII);1715 1716  // Inactive lanes must be preserved.1717  SimpleII = IC.Builder.CreateSelect(Pg, SimpleII, Inactive);1718  return IC.replaceInstUsesWith(II, SimpleII);1719}1720 1721// Use SVE intrinsic info to eliminate redundant operands and/or canonicalise1722// to operations with less strict inactive lane requirements.1723static std::optional<Instruction *>1724simplifySVEIntrinsic(InstCombiner &IC, IntrinsicInst &II,1725                     const SVEIntrinsicInfo &IInfo) {1726  if (!IInfo.hasGoverningPredicate())1727    return std::nullopt;1728 1729  auto *OpPredicate = II.getOperand(IInfo.getGoverningPredicateOperandIdx());1730 1731  // If there are no active lanes.1732  if (match(OpPredicate, m_ZeroInt())) {1733    if (IInfo.inactiveLanesTakenFromOperand())1734      return IC.replaceInstUsesWith(1735          II, II.getOperand(IInfo.getOperandIdxInactiveLanesTakenFrom()));1736 1737    if (IInfo.inactiveLanesAreUnused()) {1738      if (IInfo.resultIsZeroInitialized())1739        IC.replaceInstUsesWith(II, Constant::getNullValue(II.getType()));1740 1741      return IC.eraseInstFromFunction(II);1742    }1743  }1744 1745  // If there are no inactive lanes.1746  if (isAllActivePredicate(OpPredicate)) {1747    if (IInfo.hasOperandWithNoActiveLanes()) {1748      unsigned OpIdx = IInfo.getOperandIdxWithNoActiveLanes();1749      if (!isa<UndefValue>(II.getOperand(OpIdx)))1750        return IC.replaceOperand(II, OpIdx, UndefValue::get(II.getType()));1751    }1752 1753    if (IInfo.hasMatchingUndefIntrinsic()) {1754      auto *NewDecl = Intrinsic::getOrInsertDeclaration(1755          II.getModule(), IInfo.getMatchingUndefIntrinsic(), {II.getType()});1756      II.setCalledFunction(NewDecl);1757      return &II;1758    }1759  }1760 1761  // Operation specific simplifications.1762  if (IInfo.hasMatchingIROpode() &&1763      Instruction::isBinaryOp(IInfo.getMatchingIROpode()))1764    return simplifySVEIntrinsicBinOp(IC, II, IInfo);1765 1766  return std::nullopt;1767}1768 1769// (from_svbool (binop (to_svbool pred) (svbool_t _) (svbool_t _))))1770// => (binop (pred) (from_svbool _) (from_svbool _))1771//1772// The above transformation eliminates a `to_svbool` in the predicate1773// operand of bitwise operation `binop` by narrowing the vector width of1774// the operation. For example, it would convert a `<vscale x 16 x i1>1775// and` into a `<vscale x 4 x i1> and`. This is profitable because1776// to_svbool must zero the new lanes during widening, whereas1777// from_svbool is free.1778static std::optional<Instruction *>1779tryCombineFromSVBoolBinOp(InstCombiner &IC, IntrinsicInst &II) {1780  auto BinOp = dyn_cast<IntrinsicInst>(II.getOperand(0));1781  if (!BinOp)1782    return std::nullopt;1783 1784  auto IntrinsicID = BinOp->getIntrinsicID();1785  switch (IntrinsicID) {1786  case Intrinsic::aarch64_sve_and_z:1787  case Intrinsic::aarch64_sve_bic_z:1788  case Intrinsic::aarch64_sve_eor_z:1789  case Intrinsic::aarch64_sve_nand_z:1790  case Intrinsic::aarch64_sve_nor_z:1791  case Intrinsic::aarch64_sve_orn_z:1792  case Intrinsic::aarch64_sve_orr_z:1793    break;1794  default:1795    return std::nullopt;1796  }1797 1798  auto BinOpPred = BinOp->getOperand(0);1799  auto BinOpOp1 = BinOp->getOperand(1);1800  auto BinOpOp2 = BinOp->getOperand(2);1801 1802  auto PredIntr = dyn_cast<IntrinsicInst>(BinOpPred);1803  if (!PredIntr ||1804      PredIntr->getIntrinsicID() != Intrinsic::aarch64_sve_convert_to_svbool)1805    return std::nullopt;1806 1807  auto PredOp = PredIntr->getOperand(0);1808  auto PredOpTy = cast<VectorType>(PredOp->getType());1809  if (PredOpTy != II.getType())1810    return std::nullopt;1811 1812  SmallVector<Value *> NarrowedBinOpArgs = {PredOp};1813  auto NarrowBinOpOp1 = IC.Builder.CreateIntrinsic(1814      Intrinsic::aarch64_sve_convert_from_svbool, {PredOpTy}, {BinOpOp1});1815  NarrowedBinOpArgs.push_back(NarrowBinOpOp1);1816  if (BinOpOp1 == BinOpOp2)1817    NarrowedBinOpArgs.push_back(NarrowBinOpOp1);1818  else1819    NarrowedBinOpArgs.push_back(IC.Builder.CreateIntrinsic(1820        Intrinsic::aarch64_sve_convert_from_svbool, {PredOpTy}, {BinOpOp2}));1821 1822  auto NarrowedBinOp =1823      IC.Builder.CreateIntrinsic(IntrinsicID, {PredOpTy}, NarrowedBinOpArgs);1824  return IC.replaceInstUsesWith(II, NarrowedBinOp);1825}1826 1827static std::optional<Instruction *>1828instCombineConvertFromSVBool(InstCombiner &IC, IntrinsicInst &II) {1829  // If the reinterpret instruction operand is a PHI Node1830  if (isa<PHINode>(II.getArgOperand(0)))1831    return processPhiNode(IC, II);1832 1833  if (auto BinOpCombine = tryCombineFromSVBoolBinOp(IC, II))1834    return BinOpCombine;1835 1836  // Ignore converts to/from svcount_t.1837  if (isa<TargetExtType>(II.getArgOperand(0)->getType()) ||1838      isa<TargetExtType>(II.getType()))1839    return std::nullopt;1840 1841  SmallVector<Instruction *, 32> CandidatesForRemoval;1842  Value *Cursor = II.getOperand(0), *EarliestReplacement = nullptr;1843 1844  const auto *IVTy = cast<VectorType>(II.getType());1845 1846  // Walk the chain of conversions.1847  while (Cursor) {1848    // If the type of the cursor has fewer lanes than the final result, zeroing1849    // must take place, which breaks the equivalence chain.1850    const auto *CursorVTy = cast<VectorType>(Cursor->getType());1851    if (CursorVTy->getElementCount().getKnownMinValue() <1852        IVTy->getElementCount().getKnownMinValue())1853      break;1854 1855    // If the cursor has the same type as I, it is a viable replacement.1856    if (Cursor->getType() == IVTy)1857      EarliestReplacement = Cursor;1858 1859    auto *IntrinsicCursor = dyn_cast<IntrinsicInst>(Cursor);1860 1861    // If this is not an SVE conversion intrinsic, this is the end of the chain.1862    if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==1863                                  Intrinsic::aarch64_sve_convert_to_svbool ||1864                              IntrinsicCursor->getIntrinsicID() ==1865                                  Intrinsic::aarch64_sve_convert_from_svbool))1866      break;1867 1868    CandidatesForRemoval.insert(CandidatesForRemoval.begin(), IntrinsicCursor);1869    Cursor = IntrinsicCursor->getOperand(0);1870  }1871 1872  // If no viable replacement in the conversion chain was found, there is1873  // nothing to do.1874  if (!EarliestReplacement)1875    return std::nullopt;1876 1877  return IC.replaceInstUsesWith(II, EarliestReplacement);1878}1879 1880static std::optional<Instruction *> instCombineSVESel(InstCombiner &IC,1881                                                      IntrinsicInst &II) {1882  // svsel(ptrue, x, y) => x1883  auto *OpPredicate = II.getOperand(0);1884  if (isAllActivePredicate(OpPredicate))1885    return IC.replaceInstUsesWith(II, II.getOperand(1));1886 1887  auto Select =1888      IC.Builder.CreateSelect(OpPredicate, II.getOperand(1), II.getOperand(2));1889  return IC.replaceInstUsesWith(II, Select);1890}1891 1892static std::optional<Instruction *> instCombineSVEDup(InstCombiner &IC,1893                                                      IntrinsicInst &II) {1894  IntrinsicInst *Pg = dyn_cast<IntrinsicInst>(II.getArgOperand(1));1895  if (!Pg)1896    return std::nullopt;1897 1898  if (Pg->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)1899    return std::nullopt;1900 1901  const auto PTruePattern =1902      cast<ConstantInt>(Pg->getOperand(0))->getZExtValue();1903  if (PTruePattern != AArch64SVEPredPattern::vl1)1904    return std::nullopt;1905 1906  // The intrinsic is inserting into lane zero so use an insert instead.1907  auto *IdxTy = Type::getInt64Ty(II.getContext());1908  auto *Insert = InsertElementInst::Create(1909      II.getArgOperand(0), II.getArgOperand(2), ConstantInt::get(IdxTy, 0));1910  Insert->insertBefore(II.getIterator());1911  Insert->takeName(&II);1912 1913  return IC.replaceInstUsesWith(II, Insert);1914}1915 1916static std::optional<Instruction *> instCombineSVEDupX(InstCombiner &IC,1917                                                       IntrinsicInst &II) {1918  // Replace DupX with a regular IR splat.1919  auto *RetTy = cast<ScalableVectorType>(II.getType());1920  Value *Splat = IC.Builder.CreateVectorSplat(RetTy->getElementCount(),1921                                              II.getArgOperand(0));1922  Splat->takeName(&II);1923  return IC.replaceInstUsesWith(II, Splat);1924}1925 1926static std::optional<Instruction *> instCombineSVECmpNE(InstCombiner &IC,1927                                                        IntrinsicInst &II) {1928  LLVMContext &Ctx = II.getContext();1929 1930  if (!isAllActivePredicate(II.getArgOperand(0)))1931    return std::nullopt;1932 1933  // Check that we have a compare of zero..1934  auto *SplatValue =1935      dyn_cast_or_null<ConstantInt>(getSplatValue(II.getArgOperand(2)));1936  if (!SplatValue || !SplatValue->isZero())1937    return std::nullopt;1938 1939  // ..against a dupq1940  auto *DupQLane = dyn_cast<IntrinsicInst>(II.getArgOperand(1));1941  if (!DupQLane ||1942      DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)1943    return std::nullopt;1944 1945  // Where the dupq is a lane 0 replicate of a vector insert1946  auto *DupQLaneIdx = dyn_cast<ConstantInt>(DupQLane->getArgOperand(1));1947  if (!DupQLaneIdx || !DupQLaneIdx->isZero())1948    return std::nullopt;1949 1950  auto *VecIns = dyn_cast<IntrinsicInst>(DupQLane->getArgOperand(0));1951  if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)1952    return std::nullopt;1953 1954  // Where the vector insert is a fixed constant vector insert into undef at1955  // index zero1956  if (!isa<UndefValue>(VecIns->getArgOperand(0)))1957    return std::nullopt;1958 1959  if (!cast<ConstantInt>(VecIns->getArgOperand(2))->isZero())1960    return std::nullopt;1961 1962  auto *ConstVec = dyn_cast<Constant>(VecIns->getArgOperand(1));1963  if (!ConstVec)1964    return std::nullopt;1965 1966  auto *VecTy = dyn_cast<FixedVectorType>(ConstVec->getType());1967  auto *OutTy = dyn_cast<ScalableVectorType>(II.getType());1968  if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())1969    return std::nullopt;1970 1971  unsigned NumElts = VecTy->getNumElements();1972  unsigned PredicateBits = 0;1973 1974  // Expand intrinsic operands to a 16-bit byte level predicate1975  for (unsigned I = 0; I < NumElts; ++I) {1976    auto *Arg = dyn_cast<ConstantInt>(ConstVec->getAggregateElement(I));1977    if (!Arg)1978      return std::nullopt;1979    if (!Arg->isZero())1980      PredicateBits |= 1 << (I * (16 / NumElts));1981  }1982 1983  // If all bits are zero bail early with an empty predicate1984  if (PredicateBits == 0) {1985    auto *PFalse = Constant::getNullValue(II.getType());1986    PFalse->takeName(&II);1987    return IC.replaceInstUsesWith(II, PFalse);1988  }1989 1990  // Calculate largest predicate type used (where byte predicate is largest)1991  unsigned Mask = 8;1992  for (unsigned I = 0; I < 16; ++I)1993    if ((PredicateBits & (1 << I)) != 0)1994      Mask |= (I % 8);1995 1996  unsigned PredSize = Mask & -Mask;1997  auto *PredType = ScalableVectorType::get(1998      Type::getInt1Ty(Ctx), AArch64::SVEBitsPerBlock / (PredSize * 8));1999 2000  // Ensure all relevant bits are set2001  for (unsigned I = 0; I < 16; I += PredSize)2002    if ((PredicateBits & (1 << I)) == 0)2003      return std::nullopt;2004 2005  auto *PTruePat =2006      ConstantInt::get(Type::getInt32Ty(Ctx), AArch64SVEPredPattern::all);2007  auto *PTrue = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue,2008                                           {PredType}, {PTruePat});2009  auto *ConvertToSVBool = IC.Builder.CreateIntrinsic(2010      Intrinsic::aarch64_sve_convert_to_svbool, {PredType}, {PTrue});2011  auto *ConvertFromSVBool =2012      IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_convert_from_svbool,2013                                 {II.getType()}, {ConvertToSVBool});2014 2015  ConvertFromSVBool->takeName(&II);2016  return IC.replaceInstUsesWith(II, ConvertFromSVBool);2017}2018 2019static std::optional<Instruction *> instCombineSVELast(InstCombiner &IC,2020                                                       IntrinsicInst &II) {2021  Value *Pg = II.getArgOperand(0);2022  Value *Vec = II.getArgOperand(1);2023  auto IntrinsicID = II.getIntrinsicID();2024  bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;2025 2026  // lastX(splat(X)) --> X2027  if (auto *SplatVal = getSplatValue(Vec))2028    return IC.replaceInstUsesWith(II, SplatVal);2029 2030  // If x and/or y is a splat value then:2031  // lastX (binop (x, y)) --> binop(lastX(x), lastX(y))2032  Value *LHS, *RHS;2033  if (match(Vec, m_OneUse(m_BinOp(m_Value(LHS), m_Value(RHS))))) {2034    if (isSplatValue(LHS) || isSplatValue(RHS)) {2035      auto *OldBinOp = cast<BinaryOperator>(Vec);2036      auto OpC = OldBinOp->getOpcode();2037      auto *NewLHS =2038          IC.Builder.CreateIntrinsic(IntrinsicID, {Vec->getType()}, {Pg, LHS});2039      auto *NewRHS =2040          IC.Builder.CreateIntrinsic(IntrinsicID, {Vec->getType()}, {Pg, RHS});2041      auto *NewBinOp = BinaryOperator::CreateWithCopiedFlags(2042          OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(), II.getIterator());2043      return IC.replaceInstUsesWith(II, NewBinOp);2044    }2045  }2046 2047  auto *C = dyn_cast<Constant>(Pg);2048  if (IsAfter && C && C->isNullValue()) {2049    // The intrinsic is extracting lane 0 so use an extract instead.2050    auto *IdxTy = Type::getInt64Ty(II.getContext());2051    auto *Extract = ExtractElementInst::Create(Vec, ConstantInt::get(IdxTy, 0));2052    Extract->insertBefore(II.getIterator());2053    Extract->takeName(&II);2054    return IC.replaceInstUsesWith(II, Extract);2055  }2056 2057  auto *IntrPG = dyn_cast<IntrinsicInst>(Pg);2058  if (!IntrPG)2059    return std::nullopt;2060 2061  if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)2062    return std::nullopt;2063 2064  const auto PTruePattern =2065      cast<ConstantInt>(IntrPG->getOperand(0))->getZExtValue();2066 2067  // Can the intrinsic's predicate be converted to a known constant index?2068  unsigned MinNumElts = getNumElementsFromSVEPredPattern(PTruePattern);2069  if (!MinNumElts)2070    return std::nullopt;2071 2072  unsigned Idx = MinNumElts - 1;2073  // Increment the index if extracting the element after the last active2074  // predicate element.2075  if (IsAfter)2076    ++Idx;2077 2078  // Ignore extracts whose index is larger than the known minimum vector2079  // length. NOTE: This is an artificial constraint where we prefer to2080  // maintain what the user asked for until an alternative is proven faster.2081  auto *PgVTy = cast<ScalableVectorType>(Pg->getType());2082  if (Idx >= PgVTy->getMinNumElements())2083    return std::nullopt;2084 2085  // The intrinsic is extracting a fixed lane so use an extract instead.2086  auto *IdxTy = Type::getInt64Ty(II.getContext());2087  auto *Extract = ExtractElementInst::Create(Vec, ConstantInt::get(IdxTy, Idx));2088  Extract->insertBefore(II.getIterator());2089  Extract->takeName(&II);2090  return IC.replaceInstUsesWith(II, Extract);2091}2092 2093static std::optional<Instruction *> instCombineSVECondLast(InstCombiner &IC,2094                                                           IntrinsicInst &II) {2095  // The SIMD&FP variant of CLAST[AB] is significantly faster than the scalar2096  // integer variant across a variety of micro-architectures. Replace scalar2097  // integer CLAST[AB] intrinsic with optimal SIMD&FP variant. A simple2098  // bitcast-to-fp + clast[ab] + bitcast-to-int will cost a cycle or two more2099  // depending on the micro-architecture, but has been observed as generally2100  // being faster, particularly when the CLAST[AB] op is a loop-carried2101  // dependency.2102  Value *Pg = II.getArgOperand(0);2103  Value *Fallback = II.getArgOperand(1);2104  Value *Vec = II.getArgOperand(2);2105  Type *Ty = II.getType();2106 2107  if (!Ty->isIntegerTy())2108    return std::nullopt;2109 2110  Type *FPTy;2111  switch (cast<IntegerType>(Ty)->getBitWidth()) {2112  default:2113    return std::nullopt;2114  case 16:2115    FPTy = IC.Builder.getHalfTy();2116    break;2117  case 32:2118    FPTy = IC.Builder.getFloatTy();2119    break;2120  case 64:2121    FPTy = IC.Builder.getDoubleTy();2122    break;2123  }2124 2125  Value *FPFallBack = IC.Builder.CreateBitCast(Fallback, FPTy);2126  auto *FPVTy = VectorType::get(2127      FPTy, cast<VectorType>(Vec->getType())->getElementCount());2128  Value *FPVec = IC.Builder.CreateBitCast(Vec, FPVTy);2129  auto *FPII = IC.Builder.CreateIntrinsic(2130      II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});2131  Value *FPIItoInt = IC.Builder.CreateBitCast(FPII, II.getType());2132  return IC.replaceInstUsesWith(II, FPIItoInt);2133}2134 2135static std::optional<Instruction *> instCombineRDFFR(InstCombiner &IC,2136                                                     IntrinsicInst &II) {2137  LLVMContext &Ctx = II.getContext();2138  // Replace rdffr with predicated rdffr.z intrinsic, so that optimizePTestInstr2139  // can work with RDFFR_PP for ptest elimination.2140  auto *AllPat =2141      ConstantInt::get(Type::getInt32Ty(Ctx), AArch64SVEPredPattern::all);2142  auto *PTrue = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue,2143                                           {II.getType()}, {AllPat});2144  auto *RDFFR =2145      IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_rdffr_z, {PTrue});2146  RDFFR->takeName(&II);2147  return IC.replaceInstUsesWith(II, RDFFR);2148}2149 2150static std::optional<Instruction *>2151instCombineSVECntElts(InstCombiner &IC, IntrinsicInst &II, unsigned NumElts) {2152  const auto Pattern = cast<ConstantInt>(II.getArgOperand(0))->getZExtValue();2153 2154  if (Pattern == AArch64SVEPredPattern::all) {2155    Value *Cnt = IC.Builder.CreateElementCount(2156        II.getType(), ElementCount::getScalable(NumElts));2157    Cnt->takeName(&II);2158    return IC.replaceInstUsesWith(II, Cnt);2159  }2160 2161  unsigned MinNumElts = getNumElementsFromSVEPredPattern(Pattern);2162 2163  return MinNumElts && NumElts >= MinNumElts2164             ? std::optional<Instruction *>(IC.replaceInstUsesWith(2165                   II, ConstantInt::get(II.getType(), MinNumElts)))2166             : std::nullopt;2167}2168 2169static std::optional<Instruction *>2170instCombineSMECntsd(InstCombiner &IC, IntrinsicInst &II,2171                    const AArch64Subtarget *ST) {2172  if (!ST->isStreaming())2173    return std::nullopt;2174 2175  // In streaming-mode, aarch64_sme_cntds is equivalent to aarch64_sve_cntd2176  // with SVEPredPattern::all2177  Value *Cnt =2178      IC.Builder.CreateElementCount(II.getType(), ElementCount::getScalable(2));2179  Cnt->takeName(&II);2180  return IC.replaceInstUsesWith(II, Cnt);2181}2182 2183static std::optional<Instruction *> instCombineSVEPTest(InstCombiner &IC,2184                                                        IntrinsicInst &II) {2185  Value *PgVal = II.getArgOperand(0);2186  Value *OpVal = II.getArgOperand(1);2187 2188  // PTEST_<FIRST|LAST>(X, X) is equivalent to PTEST_ANY(X, X).2189  // Later optimizations prefer this form.2190  if (PgVal == OpVal &&2191      (II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||2192       II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {2193    Value *Ops[] = {PgVal, OpVal};2194    Type *Tys[] = {PgVal->getType()};2195 2196    auto *PTest =2197        IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptest_any, Tys, Ops);2198    PTest->takeName(&II);2199 2200    return IC.replaceInstUsesWith(II, PTest);2201  }2202 2203  IntrinsicInst *Pg = dyn_cast<IntrinsicInst>(PgVal);2204  IntrinsicInst *Op = dyn_cast<IntrinsicInst>(OpVal);2205 2206  if (!Pg || !Op)2207    return std::nullopt;2208 2209  Intrinsic::ID OpIID = Op->getIntrinsicID();2210 2211  if (Pg->getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&2212      OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&2213      Pg->getArgOperand(0)->getType() == Op->getArgOperand(0)->getType()) {2214    Value *Ops[] = {Pg->getArgOperand(0), Op->getArgOperand(0)};2215    Type *Tys[] = {Pg->getArgOperand(0)->getType()};2216 2217    auto *PTest = IC.Builder.CreateIntrinsic(II.getIntrinsicID(), Tys, Ops);2218 2219    PTest->takeName(&II);2220    return IC.replaceInstUsesWith(II, PTest);2221  }2222 2223  // Transform PTEST_ANY(X=OP(PG,...), X) -> PTEST_ANY(PG, X)).2224  // Later optimizations may rewrite sequence to use the flag-setting variant2225  // of instruction X to remove PTEST.2226  if ((Pg == Op) && (II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&2227      ((OpIID == Intrinsic::aarch64_sve_brka_z) ||2228       (OpIID == Intrinsic::aarch64_sve_brkb_z) ||2229       (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||2230       (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||2231       (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||2232       (OpIID == Intrinsic::aarch64_sve_and_z) ||2233       (OpIID == Intrinsic::aarch64_sve_bic_z) ||2234       (OpIID == Intrinsic::aarch64_sve_eor_z) ||2235       (OpIID == Intrinsic::aarch64_sve_nand_z) ||2236       (OpIID == Intrinsic::aarch64_sve_nor_z) ||2237       (OpIID == Intrinsic::aarch64_sve_orn_z) ||2238       (OpIID == Intrinsic::aarch64_sve_orr_z))) {2239    Value *Ops[] = {Pg->getArgOperand(0), Pg};2240    Type *Tys[] = {Pg->getType()};2241 2242    auto *PTest = IC.Builder.CreateIntrinsic(II.getIntrinsicID(), Tys, Ops);2243    PTest->takeName(&II);2244 2245    return IC.replaceInstUsesWith(II, PTest);2246  }2247 2248  return std::nullopt;2249}2250 2251template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>2252static std::optional<Instruction *>2253instCombineSVEVectorFuseMulAddSub(InstCombiner &IC, IntrinsicInst &II,2254                                  bool MergeIntoAddendOp) {2255  Value *P = II.getOperand(0);2256  Value *MulOp0, *MulOp1, *AddendOp, *Mul;2257  if (MergeIntoAddendOp) {2258    AddendOp = II.getOperand(1);2259    Mul = II.getOperand(2);2260  } else {2261    AddendOp = II.getOperand(2);2262    Mul = II.getOperand(1);2263  }2264 2265  if (!match(Mul, m_Intrinsic<MulOpc>(m_Specific(P), m_Value(MulOp0),2266                                      m_Value(MulOp1))))2267    return std::nullopt;2268 2269  if (!Mul->hasOneUse())2270    return std::nullopt;2271 2272  Instruction *FMFSource = nullptr;2273  if (II.getType()->isFPOrFPVectorTy()) {2274    llvm::FastMathFlags FAddFlags = II.getFastMathFlags();2275    // Stop the combine when the flags on the inputs differ in case dropping2276    // flags would lead to us missing out on more beneficial optimizations.2277    if (FAddFlags != cast<CallInst>(Mul)->getFastMathFlags())2278      return std::nullopt;2279    if (!FAddFlags.allowContract())2280      return std::nullopt;2281    FMFSource = &II;2282  }2283 2284  CallInst *Res;2285  if (MergeIntoAddendOp)2286    Res = IC.Builder.CreateIntrinsic(FuseOpc, {II.getType()},2287                                     {P, AddendOp, MulOp0, MulOp1}, FMFSource);2288  else2289    Res = IC.Builder.CreateIntrinsic(FuseOpc, {II.getType()},2290                                     {P, MulOp0, MulOp1, AddendOp}, FMFSource);2291 2292  return IC.replaceInstUsesWith(II, Res);2293}2294 2295static std::optional<Instruction *>2296instCombineSVELD1(InstCombiner &IC, IntrinsicInst &II, const DataLayout &DL) {2297  Value *Pred = II.getOperand(0);2298  Value *PtrOp = II.getOperand(1);2299  Type *VecTy = II.getType();2300 2301  if (isAllActivePredicate(Pred)) {2302    LoadInst *Load = IC.Builder.CreateLoad(VecTy, PtrOp);2303    Load->copyMetadata(II);2304    return IC.replaceInstUsesWith(II, Load);2305  }2306 2307  CallInst *MaskedLoad =2308      IC.Builder.CreateMaskedLoad(VecTy, PtrOp, PtrOp->getPointerAlignment(DL),2309                                  Pred, ConstantAggregateZero::get(VecTy));2310  MaskedLoad->copyMetadata(II);2311  return IC.replaceInstUsesWith(II, MaskedLoad);2312}2313 2314static std::optional<Instruction *>2315instCombineSVEST1(InstCombiner &IC, IntrinsicInst &II, const DataLayout &DL) {2316  Value *VecOp = II.getOperand(0);2317  Value *Pred = II.getOperand(1);2318  Value *PtrOp = II.getOperand(2);2319 2320  if (isAllActivePredicate(Pred)) {2321    StoreInst *Store = IC.Builder.CreateStore(VecOp, PtrOp);2322    Store->copyMetadata(II);2323    return IC.eraseInstFromFunction(II);2324  }2325 2326  CallInst *MaskedStore = IC.Builder.CreateMaskedStore(2327      VecOp, PtrOp, PtrOp->getPointerAlignment(DL), Pred);2328  MaskedStore->copyMetadata(II);2329  return IC.eraseInstFromFunction(II);2330}2331 2332static Instruction::BinaryOps intrinsicIDToBinOpCode(unsigned Intrinsic) {2333  switch (Intrinsic) {2334  case Intrinsic::aarch64_sve_fmul_u:2335    return Instruction::BinaryOps::FMul;2336  case Intrinsic::aarch64_sve_fadd_u:2337    return Instruction::BinaryOps::FAdd;2338  case Intrinsic::aarch64_sve_fsub_u:2339    return Instruction::BinaryOps::FSub;2340  default:2341    return Instruction::BinaryOpsEnd;2342  }2343}2344 2345static std::optional<Instruction *>2346instCombineSVEVectorBinOp(InstCombiner &IC, IntrinsicInst &II) {2347  // Bail due to missing support for ISD::STRICT_ scalable vector operations.2348  if (II.isStrictFP())2349    return std::nullopt;2350 2351  auto *OpPredicate = II.getOperand(0);2352  auto BinOpCode = intrinsicIDToBinOpCode(II.getIntrinsicID());2353  if (BinOpCode == Instruction::BinaryOpsEnd ||2354      !isAllActivePredicate(OpPredicate))2355    return std::nullopt;2356  auto BinOp = IC.Builder.CreateBinOpFMF(2357      BinOpCode, II.getOperand(1), II.getOperand(2), II.getFastMathFlags());2358  return IC.replaceInstUsesWith(II, BinOp);2359}2360 2361static std::optional<Instruction *> instCombineSVEVectorAdd(InstCombiner &IC,2362                                                            IntrinsicInst &II) {2363  if (auto MLA = instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul,2364                                                   Intrinsic::aarch64_sve_mla>(2365          IC, II, true))2366    return MLA;2367  if (auto MAD = instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul,2368                                                   Intrinsic::aarch64_sve_mad>(2369          IC, II, false))2370    return MAD;2371  return std::nullopt;2372}2373 2374static std::optional<Instruction *>2375instCombineSVEVectorFAdd(InstCombiner &IC, IntrinsicInst &II) {2376  if (auto FMLA =2377          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,2378                                            Intrinsic::aarch64_sve_fmla>(IC, II,2379                                                                         true))2380    return FMLA;2381  if (auto FMAD =2382          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,2383                                            Intrinsic::aarch64_sve_fmad>(IC, II,2384                                                                         false))2385    return FMAD;2386  if (auto FMLA =2387          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,2388                                            Intrinsic::aarch64_sve_fmla>(IC, II,2389                                                                         true))2390    return FMLA;2391  return std::nullopt;2392}2393 2394static std::optional<Instruction *>2395instCombineSVEVectorFAddU(InstCombiner &IC, IntrinsicInst &II) {2396  if (auto FMLA =2397          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,2398                                            Intrinsic::aarch64_sve_fmla>(IC, II,2399                                                                         true))2400    return FMLA;2401  if (auto FMAD =2402          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,2403                                            Intrinsic::aarch64_sve_fmad>(IC, II,2404                                                                         false))2405    return FMAD;2406  if (auto FMLA_U =2407          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,2408                                            Intrinsic::aarch64_sve_fmla_u>(2409              IC, II, true))2410    return FMLA_U;2411  return instCombineSVEVectorBinOp(IC, II);2412}2413 2414static std::optional<Instruction *>2415instCombineSVEVectorFSub(InstCombiner &IC, IntrinsicInst &II) {2416  if (auto FMLS =2417          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,2418                                            Intrinsic::aarch64_sve_fmls>(IC, II,2419                                                                         true))2420    return FMLS;2421  if (auto FMSB =2422          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,2423                                            Intrinsic::aarch64_sve_fnmsb>(2424              IC, II, false))2425    return FMSB;2426  if (auto FMLS =2427          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,2428                                            Intrinsic::aarch64_sve_fmls>(IC, II,2429                                                                         true))2430    return FMLS;2431  return std::nullopt;2432}2433 2434static std::optional<Instruction *>2435instCombineSVEVectorFSubU(InstCombiner &IC, IntrinsicInst &II) {2436  if (auto FMLS =2437          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,2438                                            Intrinsic::aarch64_sve_fmls>(IC, II,2439                                                                         true))2440    return FMLS;2441  if (auto FMSB =2442          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,2443                                            Intrinsic::aarch64_sve_fnmsb>(2444              IC, II, false))2445    return FMSB;2446  if (auto FMLS_U =2447          instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,2448                                            Intrinsic::aarch64_sve_fmls_u>(2449              IC, II, true))2450    return FMLS_U;2451  return instCombineSVEVectorBinOp(IC, II);2452}2453 2454static std::optional<Instruction *> instCombineSVEVectorSub(InstCombiner &IC,2455                                                            IntrinsicInst &II) {2456  if (auto MLS = instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul,2457                                                   Intrinsic::aarch64_sve_mls>(2458          IC, II, true))2459    return MLS;2460  return std::nullopt;2461}2462 2463static std::optional<Instruction *> instCombineSVEUnpack(InstCombiner &IC,2464                                                         IntrinsicInst &II) {2465  Value *UnpackArg = II.getArgOperand(0);2466  auto *RetTy = cast<ScalableVectorType>(II.getType());2467  bool IsSigned = II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||2468                  II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;2469 2470  // Hi = uunpkhi(splat(X)) --> Hi = splat(extend(X))2471  // Lo = uunpklo(splat(X)) --> Lo = splat(extend(X))2472  if (auto *ScalarArg = getSplatValue(UnpackArg)) {2473    ScalarArg =2474        IC.Builder.CreateIntCast(ScalarArg, RetTy->getScalarType(), IsSigned);2475    Value *NewVal =2476        IC.Builder.CreateVectorSplat(RetTy->getElementCount(), ScalarArg);2477    NewVal->takeName(&II);2478    return IC.replaceInstUsesWith(II, NewVal);2479  }2480 2481  return std::nullopt;2482}2483static std::optional<Instruction *> instCombineSVETBL(InstCombiner &IC,2484                                                      IntrinsicInst &II) {2485  auto *OpVal = II.getOperand(0);2486  auto *OpIndices = II.getOperand(1);2487  VectorType *VTy = cast<VectorType>(II.getType());2488 2489  // Check whether OpIndices is a constant splat value < minimal element count2490  // of result.2491  auto *SplatValue = dyn_cast_or_null<ConstantInt>(getSplatValue(OpIndices));2492  if (!SplatValue ||2493      SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))2494    return std::nullopt;2495 2496  // Convert sve_tbl(OpVal sve_dup_x(SplatValue)) to2497  // splat_vector(extractelement(OpVal, SplatValue)) for further optimization.2498  auto *Extract = IC.Builder.CreateExtractElement(OpVal, SplatValue);2499  auto *VectorSplat =2500      IC.Builder.CreateVectorSplat(VTy->getElementCount(), Extract);2501 2502  VectorSplat->takeName(&II);2503  return IC.replaceInstUsesWith(II, VectorSplat);2504}2505 2506static std::optional<Instruction *> instCombineSVEUzp1(InstCombiner &IC,2507                                                       IntrinsicInst &II) {2508  Value *A, *B;2509  Type *RetTy = II.getType();2510  constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;2511  constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;2512 2513  // uzp1(to_svbool(A), to_svbool(B)) --> <A, B>2514  // uzp1(from_svbool(to_svbool(A)), from_svbool(to_svbool(B))) --> <A, B>2515  if ((match(II.getArgOperand(0),2516             m_Intrinsic<FromSVB>(m_Intrinsic<ToSVB>(m_Value(A)))) &&2517       match(II.getArgOperand(1),2518             m_Intrinsic<FromSVB>(m_Intrinsic<ToSVB>(m_Value(B))))) ||2519      (match(II.getArgOperand(0), m_Intrinsic<ToSVB>(m_Value(A))) &&2520       match(II.getArgOperand(1), m_Intrinsic<ToSVB>(m_Value(B))))) {2521    auto *TyA = cast<ScalableVectorType>(A->getType());2522    if (TyA == B->getType() &&2523        RetTy == ScalableVectorType::getDoubleElementsVectorType(TyA)) {2524      auto *SubVec = IC.Builder.CreateInsertVector(2525          RetTy, PoisonValue::get(RetTy), A, uint64_t(0));2526      auto *ConcatVec = IC.Builder.CreateInsertVector(RetTy, SubVec, B,2527                                                      TyA->getMinNumElements());2528      ConcatVec->takeName(&II);2529      return IC.replaceInstUsesWith(II, ConcatVec);2530    }2531  }2532 2533  return std::nullopt;2534}2535 2536static std::optional<Instruction *> instCombineSVEZip(InstCombiner &IC,2537                                                      IntrinsicInst &II) {2538  // zip1(uzp1(A, B), uzp2(A, B)) --> A2539  // zip2(uzp1(A, B), uzp2(A, B)) --> B2540  Value *A, *B;2541  if (match(II.getArgOperand(0),2542            m_Intrinsic<Intrinsic::aarch64_sve_uzp1>(m_Value(A), m_Value(B))) &&2543      match(II.getArgOperand(1), m_Intrinsic<Intrinsic::aarch64_sve_uzp2>(2544                                     m_Specific(A), m_Specific(B))))2545    return IC.replaceInstUsesWith(2546        II, (II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ? A : B));2547 2548  return std::nullopt;2549}2550 2551static std::optional<Instruction *>2552instCombineLD1GatherIndex(InstCombiner &IC, IntrinsicInst &II) {2553  Value *Mask = II.getOperand(0);2554  Value *BasePtr = II.getOperand(1);2555  Value *Index = II.getOperand(2);2556  Type *Ty = II.getType();2557  Value *PassThru = ConstantAggregateZero::get(Ty);2558 2559  // Contiguous gather => masked load.2560  // (sve.ld1.gather.index Mask BasePtr (sve.index IndexBase 1))2561  // => (masked.load (gep BasePtr IndexBase) Align Mask zeroinitializer)2562  Value *IndexBase;2563  if (match(Index, m_Intrinsic<Intrinsic::aarch64_sve_index>(2564                       m_Value(IndexBase), m_SpecificInt(1)))) {2565    Align Alignment =2566        BasePtr->getPointerAlignment(II.getDataLayout());2567 2568    Value *Ptr = IC.Builder.CreateGEP(cast<VectorType>(Ty)->getElementType(),2569                                      BasePtr, IndexBase);2570    CallInst *MaskedLoad =2571        IC.Builder.CreateMaskedLoad(Ty, Ptr, Alignment, Mask, PassThru);2572    MaskedLoad->takeName(&II);2573    return IC.replaceInstUsesWith(II, MaskedLoad);2574  }2575 2576  return std::nullopt;2577}2578 2579static std::optional<Instruction *>2580instCombineST1ScatterIndex(InstCombiner &IC, IntrinsicInst &II) {2581  Value *Val = II.getOperand(0);2582  Value *Mask = II.getOperand(1);2583  Value *BasePtr = II.getOperand(2);2584  Value *Index = II.getOperand(3);2585  Type *Ty = Val->getType();2586 2587  // Contiguous scatter => masked store.2588  // (sve.st1.scatter.index Value Mask BasePtr (sve.index IndexBase 1))2589  // => (masked.store Value (gep BasePtr IndexBase) Align Mask)2590  Value *IndexBase;2591  if (match(Index, m_Intrinsic<Intrinsic::aarch64_sve_index>(2592                       m_Value(IndexBase), m_SpecificInt(1)))) {2593    Align Alignment =2594        BasePtr->getPointerAlignment(II.getDataLayout());2595 2596    Value *Ptr = IC.Builder.CreateGEP(cast<VectorType>(Ty)->getElementType(),2597                                      BasePtr, IndexBase);2598    (void)IC.Builder.CreateMaskedStore(Val, Ptr, Alignment, Mask);2599 2600    return IC.eraseInstFromFunction(II);2601  }2602 2603  return std::nullopt;2604}2605 2606static std::optional<Instruction *> instCombineSVESDIV(InstCombiner &IC,2607                                                       IntrinsicInst &II) {2608  Type *Int32Ty = IC.Builder.getInt32Ty();2609  Value *Pred = II.getOperand(0);2610  Value *Vec = II.getOperand(1);2611  Value *DivVec = II.getOperand(2);2612 2613  Value *SplatValue = getSplatValue(DivVec);2614  ConstantInt *SplatConstantInt = dyn_cast_or_null<ConstantInt>(SplatValue);2615  if (!SplatConstantInt)2616    return std::nullopt;2617 2618  APInt Divisor = SplatConstantInt->getValue();2619  const int64_t DivisorValue = Divisor.getSExtValue();2620  if (DivisorValue == -1)2621    return std::nullopt;2622  if (DivisorValue == 1)2623    IC.replaceInstUsesWith(II, Vec);2624 2625  if (Divisor.isPowerOf2()) {2626    Constant *DivisorLog2 = ConstantInt::get(Int32Ty, Divisor.logBase2());2627    auto ASRD = IC.Builder.CreateIntrinsic(2628        Intrinsic::aarch64_sve_asrd, {II.getType()}, {Pred, Vec, DivisorLog2});2629    return IC.replaceInstUsesWith(II, ASRD);2630  }2631  if (Divisor.isNegatedPowerOf2()) {2632    Divisor.negate();2633    Constant *DivisorLog2 = ConstantInt::get(Int32Ty, Divisor.logBase2());2634    auto ASRD = IC.Builder.CreateIntrinsic(2635        Intrinsic::aarch64_sve_asrd, {II.getType()}, {Pred, Vec, DivisorLog2});2636    auto NEG = IC.Builder.CreateIntrinsic(2637        Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});2638    return IC.replaceInstUsesWith(II, NEG);2639  }2640 2641  return std::nullopt;2642}2643 2644bool SimplifyValuePattern(SmallVector<Value *> &Vec, bool AllowPoison) {2645  size_t VecSize = Vec.size();2646  if (VecSize == 1)2647    return true;2648  if (!isPowerOf2_64(VecSize))2649    return false;2650  size_t HalfVecSize = VecSize / 2;2651 2652  for (auto LHS = Vec.begin(), RHS = Vec.begin() + HalfVecSize;2653       RHS != Vec.end(); LHS++, RHS++) {2654    if (*LHS != nullptr && *RHS != nullptr) {2655      if (*LHS == *RHS)2656        continue;2657      else2658        return false;2659    }2660    if (!AllowPoison)2661      return false;2662    if (*LHS == nullptr && *RHS != nullptr)2663      *LHS = *RHS;2664  }2665 2666  Vec.resize(HalfVecSize);2667  SimplifyValuePattern(Vec, AllowPoison);2668  return true;2669}2670 2671// Try to simplify dupqlane patterns like dupqlane(f32 A, f32 B, f32 A, f32 B)2672// to dupqlane(f64(C)) where C is A concatenated with B2673static std::optional<Instruction *> instCombineSVEDupqLane(InstCombiner &IC,2674                                                           IntrinsicInst &II) {2675  Value *CurrentInsertElt = nullptr, *Default = nullptr;2676  if (!match(II.getOperand(0),2677             m_Intrinsic<Intrinsic::vector_insert>(2678                 m_Value(Default), m_Value(CurrentInsertElt), m_Value())) ||2679      !isa<FixedVectorType>(CurrentInsertElt->getType()))2680    return std::nullopt;2681  auto IIScalableTy = cast<ScalableVectorType>(II.getType());2682 2683  // Insert the scalars into a container ordered by InsertElement index2684  SmallVector<Value *> Elts(IIScalableTy->getMinNumElements(), nullptr);2685  while (auto InsertElt = dyn_cast<InsertElementInst>(CurrentInsertElt)) {2686    auto Idx = cast<ConstantInt>(InsertElt->getOperand(2));2687    Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);2688    CurrentInsertElt = InsertElt->getOperand(0);2689  }2690 2691  bool AllowPoison =2692      isa<PoisonValue>(CurrentInsertElt) && isa<PoisonValue>(Default);2693  if (!SimplifyValuePattern(Elts, AllowPoison))2694    return std::nullopt;2695 2696  // Rebuild the simplified chain of InsertElements. e.g. (a, b, a, b) as (a, b)2697  Value *InsertEltChain = PoisonValue::get(CurrentInsertElt->getType());2698  for (size_t I = 0; I < Elts.size(); I++) {2699    if (Elts[I] == nullptr)2700      continue;2701    InsertEltChain = IC.Builder.CreateInsertElement(InsertEltChain, Elts[I],2702                                                    IC.Builder.getInt64(I));2703  }2704  if (InsertEltChain == nullptr)2705    return std::nullopt;2706 2707  // Splat the simplified sequence, e.g. (f16 a, f16 b, f16 c, f16 d) as one i642708  // value or (f16 a, f16 b) as one i32 value. This requires an InsertSubvector2709  // be bitcast to a type wide enough to fit the sequence, be splatted, and then2710  // be narrowed back to the original type.2711  unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.size();2712  unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *2713                                 IIScalableTy->getMinNumElements() /2714                                 PatternWidth;2715 2716  IntegerType *WideTy = IC.Builder.getIntNTy(PatternWidth);2717  auto *WideScalableTy = ScalableVectorType::get(WideTy, PatternElementCount);2718  auto *WideShuffleMaskTy =2719      ScalableVectorType::get(IC.Builder.getInt32Ty(), PatternElementCount);2720 2721  auto InsertSubvector = IC.Builder.CreateInsertVector(2722      II.getType(), PoisonValue::get(II.getType()), InsertEltChain,2723      uint64_t(0));2724  auto WideBitcast =2725      IC.Builder.CreateBitOrPointerCast(InsertSubvector, WideScalableTy);2726  auto WideShuffleMask = ConstantAggregateZero::get(WideShuffleMaskTy);2727  auto WideShuffle = IC.Builder.CreateShuffleVector(2728      WideBitcast, PoisonValue::get(WideScalableTy), WideShuffleMask);2729  auto NarrowBitcast =2730      IC.Builder.CreateBitOrPointerCast(WideShuffle, II.getType());2731 2732  return IC.replaceInstUsesWith(II, NarrowBitcast);2733}2734 2735static std::optional<Instruction *> instCombineMaxMinNM(InstCombiner &IC,2736                                                        IntrinsicInst &II) {2737  Value *A = II.getArgOperand(0);2738  Value *B = II.getArgOperand(1);2739  if (A == B)2740    return IC.replaceInstUsesWith(II, A);2741 2742  return std::nullopt;2743}2744 2745static std::optional<Instruction *> instCombineSVESrshl(InstCombiner &IC,2746                                                        IntrinsicInst &II) {2747  Value *Pred = II.getOperand(0);2748  Value *Vec = II.getOperand(1);2749  Value *Shift = II.getOperand(2);2750 2751  // Convert SRSHL into the simpler LSL intrinsic when fed by an ABS intrinsic.2752  Value *AbsPred, *MergedValue;2753  if (!match(Vec, m_Intrinsic<Intrinsic::aarch64_sve_sqabs>(2754                      m_Value(MergedValue), m_Value(AbsPred), m_Value())) &&2755      !match(Vec, m_Intrinsic<Intrinsic::aarch64_sve_abs>(2756                      m_Value(MergedValue), m_Value(AbsPred), m_Value())))2757 2758    return std::nullopt;2759 2760  // Transform is valid if any of the following are true:2761  // * The ABS merge value is an undef or non-negative2762  // * The ABS predicate is all active2763  // * The ABS predicate and the SRSHL predicates are the same2764  if (!isa<UndefValue>(MergedValue) && !match(MergedValue, m_NonNegative()) &&2765      AbsPred != Pred && !isAllActivePredicate(AbsPred))2766    return std::nullopt;2767 2768  // Only valid when the shift amount is non-negative, otherwise the rounding2769  // behaviour of SRSHL cannot be ignored.2770  if (!match(Shift, m_NonNegative()))2771    return std::nullopt;2772 2773  auto LSL = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_lsl,2774                                        {II.getType()}, {Pred, Vec, Shift});2775 2776  return IC.replaceInstUsesWith(II, LSL);2777}2778 2779static std::optional<Instruction *> instCombineSVEInsr(InstCombiner &IC,2780                                                       IntrinsicInst &II) {2781  Value *Vec = II.getOperand(0);2782 2783  if (getSplatValue(Vec) == II.getOperand(1))2784    return IC.replaceInstUsesWith(II, Vec);2785 2786  return std::nullopt;2787}2788 2789static std::optional<Instruction *> instCombineDMB(InstCombiner &IC,2790                                                   IntrinsicInst &II) {2791  // If this barrier is post-dominated by identical one we can remove it2792  auto *NI = II.getNextNode();2793  unsigned LookaheadThreshold = DMBLookaheadThreshold;2794  auto CanSkipOver = [](Instruction *I) {2795    return !I->mayReadOrWriteMemory() && !I->mayHaveSideEffects();2796  };2797  while (LookaheadThreshold-- && CanSkipOver(NI)) {2798    auto *NIBB = NI->getParent();2799    NI = NI->getNextNode();2800    if (!NI) {2801      if (auto *SuccBB = NIBB->getUniqueSuccessor())2802        NI = &*SuccBB->getFirstNonPHIOrDbgOrLifetime();2803      else2804        break;2805    }2806  }2807  auto *NextII = dyn_cast_or_null<IntrinsicInst>(NI);2808  if (NextII && II.isIdenticalTo(NextII))2809    return IC.eraseInstFromFunction(II);2810 2811  return std::nullopt;2812}2813 2814static std::optional<Instruction *> instCombineWhilelo(InstCombiner &IC,2815                                                       IntrinsicInst &II) {2816  return IC.replaceInstUsesWith(2817      II,2818      IC.Builder.CreateIntrinsic(Intrinsic::get_active_lane_mask,2819                                 {II.getType(), II.getOperand(0)->getType()},2820                                 {II.getOperand(0), II.getOperand(1)}));2821}2822 2823static std::optional<Instruction *> instCombinePTrue(InstCombiner &IC,2824                                                     IntrinsicInst &II) {2825  if (match(II.getOperand(0), m_ConstantInt<AArch64SVEPredPattern::all>()))2826    return IC.replaceInstUsesWith(II, Constant::getAllOnesValue(II.getType()));2827  return std::nullopt;2828}2829 2830static std::optional<Instruction *> instCombineSVEUxt(InstCombiner &IC,2831                                                      IntrinsicInst &II,2832                                                      unsigned NumBits) {2833  Value *Passthru = II.getOperand(0);2834  Value *Pg = II.getOperand(1);2835  Value *Op = II.getOperand(2);2836 2837  // Convert UXT[BHW] to AND.2838  if (isa<UndefValue>(Passthru) || isAllActivePredicate(Pg)) {2839    auto *Ty = cast<VectorType>(II.getType());2840    auto MaskValue = APInt::getLowBitsSet(Ty->getScalarSizeInBits(), NumBits);2841    auto *Mask = ConstantInt::get(Ty, MaskValue);2842    auto *And = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_and_u, {Ty},2843                                           {Pg, Op, Mask});2844    return IC.replaceInstUsesWith(II, And);2845  }2846 2847  return std::nullopt;2848}2849 2850static std::optional<Instruction *>2851instCombineInStreamingMode(InstCombiner &IC, IntrinsicInst &II) {2852  SMEAttrs FnSMEAttrs(*II.getFunction());2853  bool IsStreaming = FnSMEAttrs.hasStreamingInterfaceOrBody();2854  if (IsStreaming || !FnSMEAttrs.hasStreamingCompatibleInterface())2855    return IC.replaceInstUsesWith(2856        II, ConstantInt::getBool(II.getType(), IsStreaming));2857  return std::nullopt;2858}2859 2860std::optional<Instruction *>2861AArch64TTIImpl::instCombineIntrinsic(InstCombiner &IC,2862                                     IntrinsicInst &II) const {2863  const SVEIntrinsicInfo &IInfo = constructSVEIntrinsicInfo(II);2864  if (std::optional<Instruction *> I = simplifySVEIntrinsic(IC, II, IInfo))2865    return I;2866 2867  Intrinsic::ID IID = II.getIntrinsicID();2868  switch (IID) {2869  default:2870    break;2871  case Intrinsic::aarch64_dmb:2872    return instCombineDMB(IC, II);2873  case Intrinsic::aarch64_neon_fmaxnm:2874  case Intrinsic::aarch64_neon_fminnm:2875    return instCombineMaxMinNM(IC, II);2876  case Intrinsic::aarch64_sve_convert_from_svbool:2877    return instCombineConvertFromSVBool(IC, II);2878  case Intrinsic::aarch64_sve_dup:2879    return instCombineSVEDup(IC, II);2880  case Intrinsic::aarch64_sve_dup_x:2881    return instCombineSVEDupX(IC, II);2882  case Intrinsic::aarch64_sve_cmpne:2883  case Intrinsic::aarch64_sve_cmpne_wide:2884    return instCombineSVECmpNE(IC, II);2885  case Intrinsic::aarch64_sve_rdffr:2886    return instCombineRDFFR(IC, II);2887  case Intrinsic::aarch64_sve_lasta:2888  case Intrinsic::aarch64_sve_lastb:2889    return instCombineSVELast(IC, II);2890  case Intrinsic::aarch64_sve_clasta_n:2891  case Intrinsic::aarch64_sve_clastb_n:2892    return instCombineSVECondLast(IC, II);2893  case Intrinsic::aarch64_sve_cntd:2894    return instCombineSVECntElts(IC, II, 2);2895  case Intrinsic::aarch64_sve_cntw:2896    return instCombineSVECntElts(IC, II, 4);2897  case Intrinsic::aarch64_sve_cnth:2898    return instCombineSVECntElts(IC, II, 8);2899  case Intrinsic::aarch64_sve_cntb:2900    return instCombineSVECntElts(IC, II, 16);2901  case Intrinsic::aarch64_sme_cntsd:2902    return instCombineSMECntsd(IC, II, ST);2903  case Intrinsic::aarch64_sve_ptest_any:2904  case Intrinsic::aarch64_sve_ptest_first:2905  case Intrinsic::aarch64_sve_ptest_last:2906    return instCombineSVEPTest(IC, II);2907  case Intrinsic::aarch64_sve_fadd:2908    return instCombineSVEVectorFAdd(IC, II);2909  case Intrinsic::aarch64_sve_fadd_u:2910    return instCombineSVEVectorFAddU(IC, II);2911  case Intrinsic::aarch64_sve_fmul_u:2912    return instCombineSVEVectorBinOp(IC, II);2913  case Intrinsic::aarch64_sve_fsub:2914    return instCombineSVEVectorFSub(IC, II);2915  case Intrinsic::aarch64_sve_fsub_u:2916    return instCombineSVEVectorFSubU(IC, II);2917  case Intrinsic::aarch64_sve_add:2918    return instCombineSVEVectorAdd(IC, II);2919  case Intrinsic::aarch64_sve_add_u:2920    return instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul_u,2921                                             Intrinsic::aarch64_sve_mla_u>(2922        IC, II, true);2923  case Intrinsic::aarch64_sve_sub:2924    return instCombineSVEVectorSub(IC, II);2925  case Intrinsic::aarch64_sve_sub_u:2926    return instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul_u,2927                                             Intrinsic::aarch64_sve_mls_u>(2928        IC, II, true);2929  case Intrinsic::aarch64_sve_tbl:2930    return instCombineSVETBL(IC, II);2931  case Intrinsic::aarch64_sve_uunpkhi:2932  case Intrinsic::aarch64_sve_uunpklo:2933  case Intrinsic::aarch64_sve_sunpkhi:2934  case Intrinsic::aarch64_sve_sunpklo:2935    return instCombineSVEUnpack(IC, II);2936  case Intrinsic::aarch64_sve_uzp1:2937    return instCombineSVEUzp1(IC, II);2938  case Intrinsic::aarch64_sve_zip1:2939  case Intrinsic::aarch64_sve_zip2:2940    return instCombineSVEZip(IC, II);2941  case Intrinsic::aarch64_sve_ld1_gather_index:2942    return instCombineLD1GatherIndex(IC, II);2943  case Intrinsic::aarch64_sve_st1_scatter_index:2944    return instCombineST1ScatterIndex(IC, II);2945  case Intrinsic::aarch64_sve_ld1:2946    return instCombineSVELD1(IC, II, DL);2947  case Intrinsic::aarch64_sve_st1:2948    return instCombineSVEST1(IC, II, DL);2949  case Intrinsic::aarch64_sve_sdiv:2950    return instCombineSVESDIV(IC, II);2951  case Intrinsic::aarch64_sve_sel:2952    return instCombineSVESel(IC, II);2953  case Intrinsic::aarch64_sve_srshl:2954    return instCombineSVESrshl(IC, II);2955  case Intrinsic::aarch64_sve_dupq_lane:2956    return instCombineSVEDupqLane(IC, II);2957  case Intrinsic::aarch64_sve_insr:2958    return instCombineSVEInsr(IC, II);2959  case Intrinsic::aarch64_sve_whilelo:2960    return instCombineWhilelo(IC, II);2961  case Intrinsic::aarch64_sve_ptrue:2962    return instCombinePTrue(IC, II);2963  case Intrinsic::aarch64_sve_uxtb:2964    return instCombineSVEUxt(IC, II, 8);2965  case Intrinsic::aarch64_sve_uxth:2966    return instCombineSVEUxt(IC, II, 16);2967  case Intrinsic::aarch64_sve_uxtw:2968    return instCombineSVEUxt(IC, II, 32);2969  case Intrinsic::aarch64_sme_in_streaming_mode:2970    return instCombineInStreamingMode(IC, II);2971  }2972 2973  return std::nullopt;2974}2975 2976std::optional<Value *> AArch64TTIImpl::simplifyDemandedVectorEltsIntrinsic(2977    InstCombiner &IC, IntrinsicInst &II, APInt OrigDemandedElts,2978    APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3,2979    std::function<void(Instruction *, unsigned, APInt, APInt &)>2980        SimplifyAndSetOp) const {2981  switch (II.getIntrinsicID()) {2982  default:2983    break;2984  case Intrinsic::aarch64_neon_fcvtxn:2985  case Intrinsic::aarch64_neon_rshrn:2986  case Intrinsic::aarch64_neon_sqrshrn:2987  case Intrinsic::aarch64_neon_sqrshrun:2988  case Intrinsic::aarch64_neon_sqshrn:2989  case Intrinsic::aarch64_neon_sqshrun:2990  case Intrinsic::aarch64_neon_sqxtn:2991  case Intrinsic::aarch64_neon_sqxtun:2992  case Intrinsic::aarch64_neon_uqrshrn:2993  case Intrinsic::aarch64_neon_uqshrn:2994  case Intrinsic::aarch64_neon_uqxtn:2995    SimplifyAndSetOp(&II, 0, OrigDemandedElts, UndefElts);2996    break;2997  }2998 2999  return std::nullopt;3000}3001 3002bool AArch64TTIImpl::enableScalableVectorization() const {3003  return ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&3004                                  EnableScalableAutovecInStreamingMode);3005}3006 3007TypeSize3008AArch64TTIImpl::getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const {3009  switch (K) {3010  case TargetTransformInfo::RGK_Scalar:3011    return TypeSize::getFixed(64);3012  case TargetTransformInfo::RGK_FixedWidthVector:3013    if (ST->useSVEForFixedLengthVectors() &&3014        (ST->isSVEAvailable() || EnableFixedwidthAutovecInStreamingMode))3015      return TypeSize::getFixed(3016          std::max(ST->getMinSVEVectorSizeInBits(), 128u));3017    else if (ST->isNeonAvailable())3018      return TypeSize::getFixed(128);3019    else3020      return TypeSize::getFixed(0);3021  case TargetTransformInfo::RGK_ScalableVector:3022    if (ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&3023                                 EnableScalableAutovecInStreamingMode))3024      return TypeSize::getScalable(128);3025    else3026      return TypeSize::getScalable(0);3027  }3028  llvm_unreachable("Unsupported register kind");3029}3030 3031bool AArch64TTIImpl::isSingleExtWideningInstruction(3032    unsigned Opcode, Type *DstTy, ArrayRef<const Value *> Args,3033    Type *SrcOverrideTy) const {3034  // A helper that returns a vector type from the given type. The number of3035  // elements in type Ty determines the vector width.3036  auto toVectorTy = [&](Type *ArgTy) {3037    return VectorType::get(ArgTy->getScalarType(),3038                           cast<VectorType>(DstTy)->getElementCount());3039  };3040 3041  // Exit early if DstTy is not a vector type whose elements are one of [i16,3042  // i32, i64]. SVE doesn't generally have the same set of instructions to3043  // perform an extend with the add/sub/mul. There are SMULLB style3044  // instructions, but they operate on top/bottom, requiring some sort of lane3045  // interleaving to be used with zext/sext.3046  unsigned DstEltSize = DstTy->getScalarSizeInBits();3047  if (!useNeonVector(DstTy) || Args.size() != 2 ||3048      (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))3049    return false;3050 3051  Type *SrcTy = SrcOverrideTy;3052  switch (Opcode) {3053  case Instruction::Add:   // UADDW(2), SADDW(2).3054  case Instruction::Sub: { // USUBW(2), SSUBW(2).3055    // The second operand needs to be an extend3056    if (isa<SExtInst>(Args[1]) || isa<ZExtInst>(Args[1])) {3057      if (!SrcTy)3058        SrcTy =3059            toVectorTy(cast<Instruction>(Args[1])->getOperand(0)->getType());3060      break;3061    }3062 3063    if (Opcode == Instruction::Sub)3064      return false;3065 3066    // UADDW(2), SADDW(2) can be commutted.3067    if (isa<SExtInst>(Args[0]) || isa<ZExtInst>(Args[0])) {3068      if (!SrcTy)3069        SrcTy =3070            toVectorTy(cast<Instruction>(Args[0])->getOperand(0)->getType());3071      break;3072    }3073    return false;3074  }3075  default:3076    return false;3077  }3078 3079  // Legalize the destination type and ensure it can be used in a widening3080  // operation.3081  auto DstTyL = getTypeLegalizationCost(DstTy);3082  if (!DstTyL.second.isVector() || DstEltSize != DstTy->getScalarSizeInBits())3083    return false;3084 3085  // Legalize the source type and ensure it can be used in a widening3086  // operation.3087  assert(SrcTy && "Expected some SrcTy");3088  auto SrcTyL = getTypeLegalizationCost(SrcTy);3089  unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();3090  if (!SrcTyL.second.isVector() || SrcElTySize != SrcTy->getScalarSizeInBits())3091    return false;3092 3093  // Get the total number of vector elements in the legalized types.3094  InstructionCost NumDstEls =3095      DstTyL.first * DstTyL.second.getVectorMinNumElements();3096  InstructionCost NumSrcEls =3097      SrcTyL.first * SrcTyL.second.getVectorMinNumElements();3098 3099  // Return true if the legalized types have the same number of vector elements3100  // and the destination element type size is twice that of the source type.3101  return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;3102}3103 3104Type *AArch64TTIImpl::isBinExtWideningInstruction(unsigned Opcode, Type *DstTy,3105                                                  ArrayRef<const Value *> Args,3106                                                  Type *SrcOverrideTy) const {3107  if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&3108      Opcode != Instruction::Mul)3109    return nullptr;3110 3111  // Exit early if DstTy is not a vector type whose elements are one of [i16,3112  // i32, i64]. SVE doesn't generally have the same set of instructions to3113  // perform an extend with the add/sub/mul. There are SMULLB style3114  // instructions, but they operate on top/bottom, requiring some sort of lane3115  // interleaving to be used with zext/sext.3116  unsigned DstEltSize = DstTy->getScalarSizeInBits();3117  if (!useNeonVector(DstTy) || Args.size() != 2 ||3118      (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))3119    return nullptr;3120 3121  auto getScalarSizeWithOverride = [&](const Value *V) {3122    if (SrcOverrideTy)3123      return SrcOverrideTy->getScalarSizeInBits();3124    return cast<Instruction>(V)3125        ->getOperand(0)3126        ->getType()3127        ->getScalarSizeInBits();3128  };3129 3130  unsigned MaxEltSize = 0;3131  if ((isa<SExtInst>(Args[0]) && isa<SExtInst>(Args[1])) ||3132      (isa<ZExtInst>(Args[0]) && isa<ZExtInst>(Args[1]))) {3133    unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);3134    unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);3135    MaxEltSize = std::max(EltSize0, EltSize1);3136  } else if (isa<SExtInst, ZExtInst>(Args[0]) &&3137             isa<SExtInst, ZExtInst>(Args[1])) {3138    unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);3139    unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);3140    // mul(sext, zext) will become smull(sext, zext) if the extends are large3141    // enough.3142    if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)3143      return nullptr;3144    MaxEltSize = DstEltSize / 2;3145  } else if (Opcode == Instruction::Mul &&3146             (isa<ZExtInst>(Args[0]) || isa<ZExtInst>(Args[1]))) {3147    // If one of the operands is a Zext and the other has enough zero bits3148    // to be treated as unsigned, we can still generate a umull, meaning the3149    // zext is free.3150    KnownBits Known =3151        computeKnownBits(isa<ZExtInst>(Args[0]) ? Args[1] : Args[0], DL);3152    if (Args[0]->getType()->getScalarSizeInBits() -3153            Known.Zero.countLeadingOnes() >3154        DstTy->getScalarSizeInBits() / 2)3155      return nullptr;3156 3157    MaxEltSize =3158        getScalarSizeWithOverride(isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);3159  } else3160    return nullptr;3161 3162  if (MaxEltSize * 2 > DstEltSize)3163    return nullptr;3164 3165  Type *ExtTy = DstTy->getWithNewBitWidth(MaxEltSize * 2);3166  if (ExtTy->getPrimitiveSizeInBits() <= 64)3167    return nullptr;3168  return ExtTy;3169}3170 3171// s/urhadd instructions implement the following pattern, making the3172// extends free:3173//   %x = add ((zext i8 -> i16), 1)3174//   %y = (zext i8 -> i16)3175//   trunc i16 (lshr (add %x, %y), 1) -> i83176//3177bool AArch64TTIImpl::isExtPartOfAvgExpr(const Instruction *ExtUser, Type *Dst,3178                                        Type *Src) const {3179  // The source should be a legal vector type.3180  if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(DL, Src)) ||3181      (Src->isScalableTy() && !ST->hasSVE2()))3182    return false;3183 3184  if (ExtUser->getOpcode() != Instruction::Add || !ExtUser->hasOneUse())3185    return false;3186 3187  // Look for trunc/shl/add before trying to match the pattern.3188  const Instruction *Add = ExtUser;3189  auto *AddUser =3190      dyn_cast_or_null<Instruction>(Add->getUniqueUndroppableUser());3191  if (AddUser && AddUser->getOpcode() == Instruction::Add)3192    Add = AddUser;3193 3194  auto *Shr = dyn_cast_or_null<Instruction>(Add->getUniqueUndroppableUser());3195  if (!Shr || Shr->getOpcode() != Instruction::LShr)3196    return false;3197 3198  auto *Trunc = dyn_cast_or_null<Instruction>(Shr->getUniqueUndroppableUser());3199  if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||3200      Src->getScalarSizeInBits() !=3201          cast<CastInst>(Trunc)->getDestTy()->getScalarSizeInBits())3202    return false;3203 3204  // Try to match the whole pattern. Ext could be either the first or second3205  // m_ZExtOrSExt matched.3206  Instruction *Ex1, *Ex2;3207  if (!(match(Add, m_c_Add(m_Instruction(Ex1),3208                           m_c_Add(m_Instruction(Ex2), m_SpecificInt(1))))))3209    return false;3210 3211  // Ensure both extends are of the same type3212  if (match(Ex1, m_ZExtOrSExt(m_Value())) &&3213      Ex1->getOpcode() == Ex2->getOpcode())3214    return true;3215 3216  return false;3217}3218 3219InstructionCost AArch64TTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst,3220                                                 Type *Src,3221                                                 TTI::CastContextHint CCH,3222                                                 TTI::TargetCostKind CostKind,3223                                                 const Instruction *I) const {3224  int ISD = TLI->InstructionOpcodeToISD(Opcode);3225  assert(ISD && "Invalid opcode");3226  // If the cast is observable, and it is used by a widening instruction (e.g.,3227  // uaddl, saddw, etc.), it may be free.3228  if (I && I->hasOneUser()) {3229    auto *SingleUser = cast<Instruction>(*I->user_begin());3230    SmallVector<const Value *, 4> Operands(SingleUser->operand_values());3231    if (Type *ExtTy = isBinExtWideningInstruction(3232            SingleUser->getOpcode(), Dst, Operands,3233            Src != I->getOperand(0)->getType() ? Src : nullptr)) {3234      // The cost from Src->Src*2 needs to be added if required, the cost from3235      // Src*2->ExtTy is free.3236      if (ExtTy->getScalarSizeInBits() > Src->getScalarSizeInBits() * 2) {3237        Type *DoubleSrcTy =3238            Src->getWithNewBitWidth(Src->getScalarSizeInBits() * 2);3239        return getCastInstrCost(Opcode, DoubleSrcTy, Src,3240                                TTI::CastContextHint::None, CostKind);3241      }3242 3243      return 0;3244    }3245 3246    if (isSingleExtWideningInstruction(3247            SingleUser->getOpcode(), Dst, Operands,3248            Src != I->getOperand(0)->getType() ? Src : nullptr)) {3249      // For adds only count the second operand as free if both operands are3250      // extends but not the same operation. (i.e both operands are not free in3251      // add(sext, zext)).3252      if (SingleUser->getOpcode() == Instruction::Add) {3253        if (I == SingleUser->getOperand(1) ||3254            (isa<CastInst>(SingleUser->getOperand(1)) &&3255             cast<CastInst>(SingleUser->getOperand(1))->getOpcode() == Opcode))3256          return 0;3257      } else {3258        // Others are free so long as isSingleExtWideningInstruction3259        // returned true.3260        return 0;3261      }3262    }3263 3264    // The cast will be free for the s/urhadd instructions3265    if ((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&3266        isExtPartOfAvgExpr(SingleUser, Dst, Src))3267      return 0;3268  }3269 3270  // TODO: Allow non-throughput costs that aren't binary.3271  auto AdjustCost = [&CostKind](InstructionCost Cost) -> InstructionCost {3272    if (CostKind != TTI::TCK_RecipThroughput)3273      return Cost == 0 ? 0 : 1;3274    return Cost;3275  };3276 3277  EVT SrcTy = TLI->getValueType(DL, Src);3278  EVT DstTy = TLI->getValueType(DL, Dst);3279 3280  if (!SrcTy.isSimple() || !DstTy.isSimple())3281    return AdjustCost(3282        BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I));3283 3284  // For the moment we do not have lowering for SVE1-only fptrunc f64->bf16 as3285  // we use fcvtx under SVE2. Give them invalid costs.3286  if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&3287      ISD == ISD::FP_ROUND && SrcTy.isScalableVector() &&3288      DstTy.getScalarType() == MVT::bf16 && SrcTy.getScalarType() == MVT::f64)3289    return InstructionCost::getInvalid();3290 3291  static const TypeConversionCostTblEntry BF16Tbl[] = {3292      {ISD::FP_ROUND, MVT::bf16, MVT::f32, 1},     // bfcvt3293      {ISD::FP_ROUND, MVT::bf16, MVT::f64, 1},     // bfcvt3294      {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f32, 1}, // bfcvtn3295      {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f32, 2}, // bfcvtn+bfcvtn23296      {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f64, 2}, // bfcvtn+fcvtn3297      {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f64, 3}, // fcvtn+fcvtl2+bfcvtn3298      {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f64, 6}, // 2 * fcvtn+fcvtn2+bfcvtn3299      {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f32, 1},  // bfcvt3300      {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f32, 1},  // bfcvt3301      {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f32, 3},  // bfcvt+bfcvt+uzp13302      {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f64, 2},  // fcvtx+bfcvt3303      {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f64, 5},  // 2*fcvtx+2*bfcvt+uzp13304      {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f64, 11}, // 4*fcvt+4*bfcvt+3*uzp3305  };3306 3307  if (ST->hasBF16())3308    if (const auto *Entry = ConvertCostTableLookup(3309            BF16Tbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))3310      return AdjustCost(Entry->Cost);3311 3312  // Symbolic constants for the SVE sitofp/uitofp entries in the table below3313  // The cost of unpacking twice is artificially increased for now in order3314  // to avoid regressions against NEON, which will use tbl instructions directly3315  // instead of multiple layers of [s|u]unpk[lo|hi].3316  // We use the unpacks in cases where the destination type is illegal and3317  // requires splitting of the input, even if the input type itself is legal.3318  const unsigned int SVE_EXT_COST = 1;3319  const unsigned int SVE_FCVT_COST = 1;3320  const unsigned int SVE_UNPACK_ONCE = 4;3321  const unsigned int SVE_UNPACK_TWICE = 16;3322 3323  static const TypeConversionCostTblEntry ConversionTbl[] = {3324      {ISD::TRUNCATE, MVT::v2i8, MVT::v2i64, 1},    // xtn3325      {ISD::TRUNCATE, MVT::v2i16, MVT::v2i64, 1},   // xtn3326      {ISD::TRUNCATE, MVT::v2i32, MVT::v2i64, 1},   // xtn3327      {ISD::TRUNCATE, MVT::v4i8, MVT::v4i32, 1},    // xtn3328      {ISD::TRUNCATE, MVT::v4i8, MVT::v4i64, 3},    // 2 xtn + 1 uzp13329      {ISD::TRUNCATE, MVT::v4i16, MVT::v4i32, 1},   // xtn3330      {ISD::TRUNCATE, MVT::v4i16, MVT::v4i64, 2},   // 1 uzp1 + 1 xtn3331      {ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1},   // 1 uzp13332      {ISD::TRUNCATE, MVT::v8i8, MVT::v8i16, 1},    // 1 xtn3333      {ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, 2},    // 1 uzp1 + 1 xtn3334      {ISD::TRUNCATE, MVT::v8i8, MVT::v8i64, 4},    // 3 x uzp1 + xtn3335      {ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 1},   // 1 uzp13336      {ISD::TRUNCATE, MVT::v8i16, MVT::v8i64, 3},   // 3 x uzp13337      {ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, 2},   // 2 x uzp13338      {ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 1},  // uzp13339      {ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 3},  // (2 + 1) x uzp13340      {ISD::TRUNCATE, MVT::v16i8, MVT::v16i64, 7},  // (4 + 2 + 1) x uzp13341      {ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 2}, // 2 x uzp13342      {ISD::TRUNCATE, MVT::v16i16, MVT::v16i64, 6}, // (4 + 2) x uzp13343      {ISD::TRUNCATE, MVT::v16i32, MVT::v16i64, 4}, // 4 x uzp13344 3345      // Truncations on nxvmiN3346      {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i8, 2},3347      {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i16, 2},3348      {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i32, 2},3349      {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i64, 2},3350      {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i8, 2},3351      {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i16, 2},3352      {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i32, 2},3353      {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i64, 5},3354      {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i8, 2},3355      {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i16, 2},3356      {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i32, 5},3357      {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i64, 11},3358      {ISD::TRUNCATE, MVT::nxv16i1, MVT::nxv16i8, 2},3359      {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i16, 0},3360      {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i32, 0},3361      {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i64, 0},3362      {ISD::TRUNCATE, MVT::nxv2i16, MVT::nxv2i32, 0},3363      {ISD::TRUNCATE, MVT::nxv2i16, MVT::nxv2i64, 0},3364      {ISD::TRUNCATE, MVT::nxv2i32, MVT::nxv2i64, 0},3365      {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i16, 0},3366      {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i32, 0},3367      {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i64, 1},3368      {ISD::TRUNCATE, MVT::nxv4i16, MVT::nxv4i32, 0},3369      {ISD::TRUNCATE, MVT::nxv4i16, MVT::nxv4i64, 1},3370      {ISD::TRUNCATE, MVT::nxv4i32, MVT::nxv4i64, 1},3371      {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i16, 0},3372      {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i32, 1},3373      {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i64, 3},3374      {ISD::TRUNCATE, MVT::nxv8i16, MVT::nxv8i32, 1},3375      {ISD::TRUNCATE, MVT::nxv8i16, MVT::nxv8i64, 3},3376      {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i16, 1},3377      {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i32, 3},3378      {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i64, 7},3379 3380      // The number of shll instructions for the extension.3381      {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i16, 3},3382      {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i16, 3},3383      {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 2},3384      {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 2},3385      {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i8, 3},3386      {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i8, 3},3387      {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 2},3388      {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 2},3389      {ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, 7},3390      {ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, 7},3391      {ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, 6},3392      {ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, 6},3393      {ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 2},3394      {ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 2},3395      {ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, 6},3396      {ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, 6},3397 3398      // FP Ext and trunc3399      {ISD::FP_EXTEND, MVT::f64, MVT::f32, 1},     // fcvt3400      {ISD::FP_EXTEND, MVT::v2f64, MVT::v2f32, 1}, // fcvtl3401      {ISD::FP_EXTEND, MVT::v4f64, MVT::v4f32, 2}, // fcvtl+fcvtl23402      //   FP163403      {ISD::FP_EXTEND, MVT::f32, MVT::f16, 1},     // fcvt3404      {ISD::FP_EXTEND, MVT::f64, MVT::f16, 1},     // fcvt3405      {ISD::FP_EXTEND, MVT::v4f32, MVT::v4f16, 1}, // fcvtl3406      {ISD::FP_EXTEND, MVT::v8f32, MVT::v8f16, 2}, // fcvtl+fcvtl23407      {ISD::FP_EXTEND, MVT::v2f64, MVT::v2f16, 2}, // fcvtl+fcvtl3408      {ISD::FP_EXTEND, MVT::v4f64, MVT::v4f16, 3}, // fcvtl+fcvtl2+fcvtl3409      {ISD::FP_EXTEND, MVT::v8f64, MVT::v8f16, 6}, // 2 * fcvtl+fcvtl2+fcvtl3410      //   BF16 (uses shift)3411      {ISD::FP_EXTEND, MVT::f32, MVT::bf16, 1},     // shl3412      {ISD::FP_EXTEND, MVT::f64, MVT::bf16, 2},     // shl+fcvt3413      {ISD::FP_EXTEND, MVT::v4f32, MVT::v4bf16, 1}, // shll3414      {ISD::FP_EXTEND, MVT::v8f32, MVT::v8bf16, 2}, // shll+shll23415      {ISD::FP_EXTEND, MVT::v2f64, MVT::v2bf16, 2}, // shll+fcvtl3416      {ISD::FP_EXTEND, MVT::v4f64, MVT::v4bf16, 3}, // shll+fcvtl+fcvtl23417      {ISD::FP_EXTEND, MVT::v8f64, MVT::v8bf16, 6}, // 2 * shll+fcvtl+fcvtl23418      // FP Ext and trunc3419      {ISD::FP_ROUND, MVT::f32, MVT::f64, 1},     // fcvt3420      {ISD::FP_ROUND, MVT::v2f32, MVT::v2f64, 1}, // fcvtn3421      {ISD::FP_ROUND, MVT::v4f32, MVT::v4f64, 2}, // fcvtn+fcvtn23422      //   FP163423      {ISD::FP_ROUND, MVT::f16, MVT::f32, 1},     // fcvt3424      {ISD::FP_ROUND, MVT::f16, MVT::f64, 1},     // fcvt3425      {ISD::FP_ROUND, MVT::v4f16, MVT::v4f32, 1}, // fcvtn3426      {ISD::FP_ROUND, MVT::v8f16, MVT::v8f32, 2}, // fcvtn+fcvtn23427      {ISD::FP_ROUND, MVT::v2f16, MVT::v2f64, 2}, // fcvtn+fcvtn3428      {ISD::FP_ROUND, MVT::v4f16, MVT::v4f64, 3}, // fcvtn+fcvtn2+fcvtn3429      {ISD::FP_ROUND, MVT::v8f16, MVT::v8f64, 6}, // 2 * fcvtn+fcvtn2+fcvtn3430      //   BF16 (more complex, with +bf16 is handled above)3431      {ISD::FP_ROUND, MVT::bf16, MVT::f32, 8}, // Expansion is ~8 insns3432      {ISD::FP_ROUND, MVT::bf16, MVT::f64, 9}, // fcvtn + above3433      {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f32, 8},3434      {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f32, 8},3435      {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f32, 15},3436      {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f64, 9},3437      {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f64, 10},3438      {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f64, 19},3439 3440      // LowerVectorINT_TO_FP:3441      {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i32, 1},3442      {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 1},3443      {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 1},3444      {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 1},3445      {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 1},3446      {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 1},3447 3448      // SVE: to nxv2f163449      {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i8,3450       SVE_EXT_COST + SVE_FCVT_COST},3451      {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i16, SVE_FCVT_COST},3452      {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i32, SVE_FCVT_COST},3453      {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i64, SVE_FCVT_COST},3454      {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i8,3455       SVE_EXT_COST + SVE_FCVT_COST},3456      {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i16, SVE_FCVT_COST},3457      {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i32, SVE_FCVT_COST},3458      {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i64, SVE_FCVT_COST},3459 3460      // SVE: to nxv4f163461      {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i8,3462       SVE_EXT_COST + SVE_FCVT_COST},3463      {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i16, SVE_FCVT_COST},3464      {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i32, SVE_FCVT_COST},3465      {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i8,3466       SVE_EXT_COST + SVE_FCVT_COST},3467      {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i16, SVE_FCVT_COST},3468      {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i32, SVE_FCVT_COST},3469 3470      // SVE: to nxv8f163471      {ISD::SINT_TO_FP, MVT::nxv8f16, MVT::nxv8i8,3472       SVE_EXT_COST + SVE_FCVT_COST},3473      {ISD::SINT_TO_FP, MVT::nxv8f16, MVT::nxv8i16, SVE_FCVT_COST},3474      {ISD::UINT_TO_FP, MVT::nxv8f16, MVT::nxv8i8,3475       SVE_EXT_COST + SVE_FCVT_COST},3476      {ISD::UINT_TO_FP, MVT::nxv8f16, MVT::nxv8i16, SVE_FCVT_COST},3477 3478      // SVE: to nxv16f163479      {ISD::SINT_TO_FP, MVT::nxv16f16, MVT::nxv16i8,3480       SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3481      {ISD::UINT_TO_FP, MVT::nxv16f16, MVT::nxv16i8,3482       SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3483 3484      // Complex: to v2f323485      {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i8, 3},3486      {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i16, 3},3487      {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i8, 3},3488      {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i16, 3},3489 3490      // SVE: to nxv2f323491      {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i8,3492       SVE_EXT_COST + SVE_FCVT_COST},3493      {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i16, SVE_FCVT_COST},3494      {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i32, SVE_FCVT_COST},3495      {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i64, SVE_FCVT_COST},3496      {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i8,3497       SVE_EXT_COST + SVE_FCVT_COST},3498      {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i16, SVE_FCVT_COST},3499      {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i32, SVE_FCVT_COST},3500      {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i64, SVE_FCVT_COST},3501 3502      // Complex: to v4f323503      {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i8, 4},3504      {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i16, 2},3505      {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i8, 3},3506      {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i16, 2},3507 3508      // SVE: to nxv4f323509      {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i8,3510       SVE_EXT_COST + SVE_FCVT_COST},3511      {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i16, SVE_FCVT_COST},3512      {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i32, SVE_FCVT_COST},3513      {ISD::UINT_TO_FP, MVT::nxv4f32, MVT::nxv4i8,3514       SVE_EXT_COST + SVE_FCVT_COST},3515      {ISD::UINT_TO_FP, MVT::nxv4f32, MVT::nxv4i16, SVE_FCVT_COST},3516      {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i32, SVE_FCVT_COST},3517 3518      // Complex: to v8f323519      {ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i8, 10},3520      {ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 4},3521      {ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i8, 10},3522      {ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 4},3523 3524      // SVE: to nxv8f323525      {ISD::SINT_TO_FP, MVT::nxv8f32, MVT::nxv8i8,3526       SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3527      {ISD::SINT_TO_FP, MVT::nxv8f32, MVT::nxv8i16,3528       SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3529      {ISD::UINT_TO_FP, MVT::nxv8f32, MVT::nxv8i8,3530       SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3531      {ISD::UINT_TO_FP, MVT::nxv8f32, MVT::nxv8i16,3532       SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3533 3534      // SVE: to nxv16f323535      {ISD::SINT_TO_FP, MVT::nxv16f32, MVT::nxv16i8,3536       SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},3537      {ISD::UINT_TO_FP, MVT::nxv16f32, MVT::nxv16i8,3538       SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},3539 3540      // Complex: to v16f323541      {ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, 21},3542      {ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, 21},3543 3544      // Complex: to v2f643545      {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i8, 4},3546      {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i16, 4},3547      {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i32, 2},3548      {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i8, 4},3549      {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i16, 4},3550      {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 2},3551 3552      // SVE: to nxv2f643553      {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i8,3554       SVE_EXT_COST + SVE_FCVT_COST},3555      {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i16, SVE_FCVT_COST},3556      {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i32, SVE_FCVT_COST},3557      {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i64, SVE_FCVT_COST},3558      {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i8,3559       SVE_EXT_COST + SVE_FCVT_COST},3560      {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i16, SVE_FCVT_COST},3561      {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i32, SVE_FCVT_COST},3562      {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i64, SVE_FCVT_COST},3563 3564      // Complex: to v4f643565      {ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 4},3566      {ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 4},3567 3568      // SVE: to nxv4f643569      {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i8,3570       SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3571      {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i16,3572       SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3573      {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i32,3574       SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3575      {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i8,3576       SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3577      {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i16,3578       SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3579      {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i32,3580       SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},3581 3582      // SVE: to nxv8f643583      {ISD::SINT_TO_FP, MVT::nxv8f64, MVT::nxv8i8,3584       SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},3585      {ISD::SINT_TO_FP, MVT::nxv8f64, MVT::nxv8i16,3586       SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},3587      {ISD::UINT_TO_FP, MVT::nxv8f64, MVT::nxv8i8,3588       SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},3589      {ISD::UINT_TO_FP, MVT::nxv8f64, MVT::nxv8i16,3590       SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},3591 3592      // LowerVectorFP_TO_INT3593      {ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f32, 1},3594      {ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 1},3595      {ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 1},3596      {ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f32, 1},3597      {ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 1},3598      {ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 1},3599 3600      // Complex, from v2f32: legal type is v2i32 (no cost) or v2i64 (1 ext).3601      {ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f32, 2},3602      {ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f32, 1},3603      {ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f32, 1},3604      {ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f32, 2},3605      {ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f32, 1},3606      {ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f32, 1},3607 3608      // Complex, from v4f32: legal type is v4i16, 1 narrowing => ~23609      {ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f32, 2},3610      {ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f32, 2},3611      {ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f32, 2},3612      {ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f32, 2},3613 3614      // Complex, from nxv2f32.3615      {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f32, 1},3616      {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f32, 1},3617      {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f32, 1},3618      {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f32, 1},3619      {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f32, 1},3620      {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f32, 1},3621      {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f32, 1},3622      {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f32, 1},3623 3624      // Complex, from v2f64: legal type is v2i32, 1 narrowing => ~2.3625      {ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f64, 2},3626      {ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f64, 2},3627      {ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f64, 2},3628      {ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f64, 2},3629      {ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f64, 2},3630      {ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f64, 2},3631 3632      // Complex, from nxv2f64.3633      {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f64, 1},3634      {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f64, 1},3635      {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f64, 1},3636      {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f64, 1},3637      {ISD::FP_TO_SINT, MVT::nxv2i1, MVT::nxv2f64, 1},3638      {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f64, 1},3639      {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f64, 1},3640      {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f64, 1},3641      {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f64, 1},3642      {ISD::FP_TO_UINT, MVT::nxv2i1, MVT::nxv2f64, 1},3643 3644      // Complex, from nxv4f32.3645      {ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f32, 4},3646      {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f32, 1},3647      {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f32, 1},3648      {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f32, 1},3649      {ISD::FP_TO_SINT, MVT::nxv4i1, MVT::nxv4f32, 1},3650      {ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f32, 4},3651      {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f32, 1},3652      {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f32, 1},3653      {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f32, 1},3654      {ISD::FP_TO_UINT, MVT::nxv4i1, MVT::nxv4f32, 1},3655 3656      // Complex, from nxv8f64. Illegal -> illegal conversions not required.3657      {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f64, 7},3658      {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f64, 7},3659      {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f64, 7},3660      {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f64, 7},3661 3662      // Complex, from nxv4f64. Illegal -> illegal conversions not required.3663      {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f64, 3},3664      {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f64, 3},3665      {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f64, 3},3666      {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f64, 3},3667      {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f64, 3},3668      {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f64, 3},3669 3670      // Complex, from nxv8f32. Illegal -> illegal conversions not required.3671      {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f32, 3},3672      {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f32, 3},3673      {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f32, 3},3674      {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f32, 3},3675 3676      // Complex, from nxv8f16.3677      {ISD::FP_TO_SINT, MVT::nxv8i64, MVT::nxv8f16, 10},3678      {ISD::FP_TO_SINT, MVT::nxv8i32, MVT::nxv8f16, 4},3679      {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f16, 1},3680      {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f16, 1},3681      {ISD::FP_TO_SINT, MVT::nxv8i1, MVT::nxv8f16, 1},3682      {ISD::FP_TO_UINT, MVT::nxv8i64, MVT::nxv8f16, 10},3683      {ISD::FP_TO_UINT, MVT::nxv8i32, MVT::nxv8f16, 4},3684      {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f16, 1},3685      {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f16, 1},3686      {ISD::FP_TO_UINT, MVT::nxv8i1, MVT::nxv8f16, 1},3687 3688      // Complex, from nxv4f16.3689      {ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f16, 4},3690      {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f16, 1},3691      {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f16, 1},3692      {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f16, 1},3693      {ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f16, 4},3694      {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f16, 1},3695      {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f16, 1},3696      {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f16, 1},3697 3698      // Complex, from nxv2f16.3699      {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f16, 1},3700      {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f16, 1},3701      {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f16, 1},3702      {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f16, 1},3703      {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f16, 1},3704      {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f16, 1},3705      {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f16, 1},3706      {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f16, 1},3707 3708      // Truncate from nxvmf32 to nxvmf16.3709      {ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f32, 1},3710      {ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f32, 1},3711      {ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f32, 3},3712 3713      // Truncate from nxvmf32 to nxvmbf16.3714      {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f32, 8},3715      {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f32, 8},3716      {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f32, 17},3717 3718      // Truncate from nxvmf64 to nxvmf16.3719      {ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f64, 1},3720      {ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f64, 3},3721      {ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f64, 7},3722 3723      // Truncate from nxvmf64 to nxvmbf16.3724      {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f64, 9},3725      {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f64, 19},3726      {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f64, 39},3727 3728      // Truncate from nxvmf64 to nxvmf32.3729      {ISD::FP_ROUND, MVT::nxv2f32, MVT::nxv2f64, 1},3730      {ISD::FP_ROUND, MVT::nxv4f32, MVT::nxv4f64, 3},3731      {ISD::FP_ROUND, MVT::nxv8f32, MVT::nxv8f64, 6},3732 3733      // Extend from nxvmf16 to nxvmf32.3734      {ISD::FP_EXTEND, MVT::nxv2f32, MVT::nxv2f16, 1},3735      {ISD::FP_EXTEND, MVT::nxv4f32, MVT::nxv4f16, 1},3736      {ISD::FP_EXTEND, MVT::nxv8f32, MVT::nxv8f16, 2},3737 3738      // Extend from nxvmbf16 to nxvmf32.3739      {ISD::FP_EXTEND, MVT::nxv2f32, MVT::nxv2bf16, 1}, // lsl3740      {ISD::FP_EXTEND, MVT::nxv4f32, MVT::nxv4bf16, 1}, // lsl3741      {ISD::FP_EXTEND, MVT::nxv8f32, MVT::nxv8bf16, 4}, // unpck+unpck+lsl+lsl3742 3743      // Extend from nxvmf16 to nxvmf64.3744      {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f16, 1},3745      {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f16, 2},3746      {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f16, 4},3747 3748      // Extend from nxvmbf16 to nxvmf64.3749      {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2bf16, 2},  // lsl+fcvt3750      {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4bf16, 6},  // 2*unpck+2*lsl+2*fcvt3751      {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8bf16, 14}, // 6*unpck+4*lsl+4*fcvt3752 3753      // Extend from nxvmf32 to nxvmf64.3754      {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f32, 1},3755      {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f32, 2},3756      {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f32, 6},3757 3758      // Bitcasts from float to integer3759      {ISD::BITCAST, MVT::nxv2f16, MVT::nxv2i16, 0},3760      {ISD::BITCAST, MVT::nxv4f16, MVT::nxv4i16, 0},3761      {ISD::BITCAST, MVT::nxv2f32, MVT::nxv2i32, 0},3762 3763      // Bitcasts from integer to float3764      {ISD::BITCAST, MVT::nxv2i16, MVT::nxv2f16, 0},3765      {ISD::BITCAST, MVT::nxv4i16, MVT::nxv4f16, 0},3766      {ISD::BITCAST, MVT::nxv2i32, MVT::nxv2f32, 0},3767 3768      // Add cost for extending to illegal -too wide- scalable vectors.3769      // zero/sign extend are implemented by multiple unpack operations,3770      // where each operation has a cost of 1.3771      {ISD::ZERO_EXTEND, MVT::nxv16i16, MVT::nxv16i8, 2},3772      {ISD::ZERO_EXTEND, MVT::nxv16i32, MVT::nxv16i8, 6},3773      {ISD::ZERO_EXTEND, MVT::nxv16i64, MVT::nxv16i8, 14},3774      {ISD::ZERO_EXTEND, MVT::nxv8i32, MVT::nxv8i16, 2},3775      {ISD::ZERO_EXTEND, MVT::nxv8i64, MVT::nxv8i16, 6},3776      {ISD::ZERO_EXTEND, MVT::nxv4i64, MVT::nxv4i32, 2},3777 3778      {ISD::SIGN_EXTEND, MVT::nxv16i16, MVT::nxv16i8, 2},3779      {ISD::SIGN_EXTEND, MVT::nxv16i32, MVT::nxv16i8, 6},3780      {ISD::SIGN_EXTEND, MVT::nxv16i64, MVT::nxv16i8, 14},3781      {ISD::SIGN_EXTEND, MVT::nxv8i32, MVT::nxv8i16, 2},3782      {ISD::SIGN_EXTEND, MVT::nxv8i64, MVT::nxv8i16, 6},3783      {ISD::SIGN_EXTEND, MVT::nxv4i64, MVT::nxv4i32, 2},3784  };3785 3786  // We have to estimate a cost of fixed length operation upon3787  // SVE registers(operations) with the number of registers required3788  // for a fixed type to be represented upon SVE registers.3789  EVT WiderTy = SrcTy.bitsGT(DstTy) ? SrcTy : DstTy;3790  if (SrcTy.isFixedLengthVector() && DstTy.isFixedLengthVector() &&3791      SrcTy.getVectorNumElements() == DstTy.getVectorNumElements() &&3792      ST->useSVEForFixedLengthVectors(WiderTy)) {3793    std::pair<InstructionCost, MVT> LT =3794        getTypeLegalizationCost(WiderTy.getTypeForEVT(Dst->getContext()));3795    unsigned NumElements =3796        AArch64::SVEBitsPerBlock / LT.second.getScalarSizeInBits();3797    return AdjustCost(3798        LT.first *3799        getCastInstrCost(3800            Opcode, ScalableVectorType::get(Dst->getScalarType(), NumElements),3801            ScalableVectorType::get(Src->getScalarType(), NumElements), CCH,3802            CostKind, I));3803  }3804 3805  if (const auto *Entry = ConvertCostTableLookup(3806          ConversionTbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))3807    return AdjustCost(Entry->Cost);3808 3809  static const TypeConversionCostTblEntry FP16Tbl[] = {3810      {ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f16, 1}, // fcvtzs3811      {ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f16, 1},3812      {ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f16, 1}, // fcvtzs3813      {ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f16, 1},3814      {ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f16, 2}, // fcvtl+fcvtzs3815      {ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f16, 2},3816      {ISD::FP_TO_SINT, MVT::v8i8, MVT::v8f16, 2}, // fcvtzs+xtn3817      {ISD::FP_TO_UINT, MVT::v8i8, MVT::v8f16, 2},3818      {ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f16, 1}, // fcvtzs3819      {ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f16, 1},3820      {ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f16, 4}, // 2*fcvtl+2*fcvtzs3821      {ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f16, 4},3822      {ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f16, 3}, // 2*fcvtzs+xtn3823      {ISD::FP_TO_UINT, MVT::v16i8, MVT::v16f16, 3},3824      {ISD::FP_TO_SINT, MVT::v16i16, MVT::v16f16, 2}, // 2*fcvtzs3825      {ISD::FP_TO_UINT, MVT::v16i16, MVT::v16f16, 2},3826      {ISD::FP_TO_SINT, MVT::v16i32, MVT::v16f16, 8}, // 4*fcvtl+4*fcvtzs3827      {ISD::FP_TO_UINT, MVT::v16i32, MVT::v16f16, 8},3828      {ISD::UINT_TO_FP, MVT::v8f16, MVT::v8i8, 2},   // ushll + ucvtf3829      {ISD::SINT_TO_FP, MVT::v8f16, MVT::v8i8, 2},   // sshll + scvtf3830      {ISD::UINT_TO_FP, MVT::v16f16, MVT::v16i8, 4}, // 2 * ushl(2) + 2 * ucvtf3831      {ISD::SINT_TO_FP, MVT::v16f16, MVT::v16i8, 4}, // 2 * sshl(2) + 2 * scvtf3832  };3833 3834  if (ST->hasFullFP16())3835    if (const auto *Entry = ConvertCostTableLookup(3836            FP16Tbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))3837      return AdjustCost(Entry->Cost);3838 3839  // INT_TO_FP of i64->f32 will scalarize, which is required to avoid3840  // double-rounding issues.3841  if ((ISD == ISD::SINT_TO_FP || ISD == ISD::UINT_TO_FP) &&3842      DstTy.getScalarType() == MVT::f32 && SrcTy.getScalarSizeInBits() > 32 &&3843      isa<FixedVectorType>(Dst) && isa<FixedVectorType>(Src))3844    return AdjustCost(3845        cast<FixedVectorType>(Dst)->getNumElements() *3846            getCastInstrCost(Opcode, Dst->getScalarType(), Src->getScalarType(),3847                             CCH, CostKind) +3848        BaseT::getScalarizationOverhead(cast<FixedVectorType>(Src), false, true,3849                                        CostKind) +3850        BaseT::getScalarizationOverhead(cast<FixedVectorType>(Dst), true, false,3851                                        CostKind));3852 3853  if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&3854      CCH == TTI::CastContextHint::Masked &&3855      ST->isSVEorStreamingSVEAvailable() &&3856      TLI->getTypeAction(Src->getContext(), SrcTy) ==3857          TargetLowering::TypePromoteInteger &&3858      TLI->getTypeAction(Dst->getContext(), DstTy) ==3859          TargetLowering::TypeSplitVector) {3860    // The standard behaviour in the backend for these cases is to split the3861    // extend up into two parts:3862    //  1. Perform an extending load or masked load up to the legal type.3863    //  2. Extend the loaded data to the final type.3864    std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(Src);3865    Type *LegalTy = EVT(SrcLT.second).getTypeForEVT(Src->getContext());3866    InstructionCost Part1 = AArch64TTIImpl::getCastInstrCost(3867        Opcode, LegalTy, Src, CCH, CostKind, I);3868    InstructionCost Part2 = AArch64TTIImpl::getCastInstrCost(3869        Opcode, Dst, LegalTy, TTI::CastContextHint::None, CostKind, I);3870    return Part1 + Part2;3871  }3872 3873  // The BasicTTIImpl version only deals with CCH==TTI::CastContextHint::Normal,3874  // but we also want to include the TTI::CastContextHint::Masked case too.3875  if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&3876      CCH == TTI::CastContextHint::Masked &&3877      ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))3878    CCH = TTI::CastContextHint::Normal;3879 3880  return AdjustCost(3881      BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I));3882}3883 3884InstructionCost3885AArch64TTIImpl::getExtractWithExtendCost(unsigned Opcode, Type *Dst,3886                                         VectorType *VecTy, unsigned Index,3887                                         TTI::TargetCostKind CostKind) const {3888 3889  // Make sure we were given a valid extend opcode.3890  assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&3891         "Invalid opcode");3892 3893  // We are extending an element we extract from a vector, so the source type3894  // of the extend is the element type of the vector.3895  auto *Src = VecTy->getElementType();3896 3897  // Sign- and zero-extends are for integer types only.3898  assert(isa<IntegerType>(Dst) && isa<IntegerType>(Src) && "Invalid type");3899 3900  // Get the cost for the extract. We compute the cost (if any) for the extend3901  // below.3902  InstructionCost Cost = getVectorInstrCost(Instruction::ExtractElement, VecTy,3903                                            CostKind, Index, nullptr, nullptr);3904 3905  // Legalize the types.3906  auto VecLT = getTypeLegalizationCost(VecTy);3907  auto DstVT = TLI->getValueType(DL, Dst);3908  auto SrcVT = TLI->getValueType(DL, Src);3909 3910  // If the resulting type is still a vector and the destination type is legal,3911  // we may get the extension for free. If not, get the default cost for the3912  // extend.3913  if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))3914    return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,3915                                   CostKind);3916 3917  // The destination type should be larger than the element type. If not, get3918  // the default cost for the extend.3919  if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())3920    return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,3921                                   CostKind);3922 3923  switch (Opcode) {3924  default:3925    llvm_unreachable("Opcode should be either SExt or ZExt");3926 3927  // For sign-extends, we only need a smov, which performs the extension3928  // automatically.3929  case Instruction::SExt:3930    return Cost;3931 3932  // For zero-extends, the extend is performed automatically by a umov unless3933  // the destination type is i64 and the element type is i8 or i16.3934  case Instruction::ZExt:3935    if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)3936      return Cost;3937  }3938 3939  // If we are unable to perform the extend for free, get the default cost.3940  return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,3941                                 CostKind);3942}3943 3944InstructionCost AArch64TTIImpl::getCFInstrCost(unsigned Opcode,3945                                               TTI::TargetCostKind CostKind,3946                                               const Instruction *I) const {3947  if (CostKind != TTI::TCK_RecipThroughput)3948    return Opcode == Instruction::PHI ? 0 : 1;3949  assert(CostKind == TTI::TCK_RecipThroughput && "unexpected CostKind");3950  // Branches are assumed to be predicted.3951  return 0;3952}3953 3954InstructionCost AArch64TTIImpl::getVectorInstrCostHelper(3955    unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,3956    const Instruction *I, Value *Scalar,3957    ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx) const {3958  assert(Val->isVectorTy() && "This must be a vector type");3959 3960  if (Index != -1U) {3961    // Legalize the type.3962    std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Val);3963 3964    // This type is legalized to a scalar type.3965    if (!LT.second.isVector())3966      return 0;3967 3968    // The type may be split. For fixed-width vectors we can normalize the3969    // index to the new type.3970    if (LT.second.isFixedLengthVector()) {3971      unsigned Width = LT.second.getVectorNumElements();3972      Index = Index % Width;3973    }3974 3975    // The element at index zero is already inside the vector.3976    // - For a insert-element or extract-element3977    // instruction that extracts integers, an explicit FPR -> GPR move is3978    // needed. So it has non-zero cost.3979    if (Index == 0 && !Val->getScalarType()->isIntegerTy())3980      return 0;3981 3982    // This is recognising a LD1 single-element structure to one lane of one3983    // register instruction. I.e., if this is an `insertelement` instruction,3984    // and its second operand is a load, then we will generate a LD1, which3985    // are expensive instructions.3986    if (I && dyn_cast<LoadInst>(I->getOperand(1)))3987      return CostKind == TTI::TCK_CodeSize3988                 ? 03989                 : ST->getVectorInsertExtractBaseCost() + 1;3990 3991    // i1 inserts and extract will include an extra cset or cmp of the vector3992    // value. Increase the cost by 1 to account.3993    if (Val->getScalarSizeInBits() == 1)3994      return CostKind == TTI::TCK_CodeSize3995                 ? 23996                 : ST->getVectorInsertExtractBaseCost() + 1;3997 3998    // FIXME:3999    // If the extract-element and insert-element instructions could be4000    // simplified away (e.g., could be combined into users by looking at use-def4001    // context), they have no cost. This is not done in the first place for4002    // compile-time considerations.4003  }4004 4005  // In case of Neon, if there exists extractelement from lane != 0 such that4006  // 1. extractelement does not necessitate a move from vector_reg -> GPR.4007  // 2. extractelement result feeds into fmul.4008  // 3. Other operand of fmul is an extractelement from lane 0 or lane4009  // equivalent to 0.4010  // then the extractelement can be merged with fmul in the backend and it4011  // incurs no cost.4012  // e.g.4013  // define double @foo(<2 x double> %a) {4014  //   %1 = extractelement <2 x double> %a, i32 04015  //   %2 = extractelement <2 x double> %a, i32 14016  //   %res = fmul double %1, %24017  //   ret double %res4018  // }4019  // %2 and %res can be merged in the backend to generate fmul d0, d0, v1.d[1]4020  auto ExtractCanFuseWithFmul = [&]() {4021    // We bail out if the extract is from lane 0.4022    if (Index == 0)4023      return false;4024 4025    // Check if the scalar element type of the vector operand of ExtractElement4026    // instruction is one of the allowed types.4027    auto IsAllowedScalarTy = [&](const Type *T) {4028      return T->isFloatTy() || T->isDoubleTy() ||4029             (T->isHalfTy() && ST->hasFullFP16());4030    };4031 4032    // Check if the extractelement user is scalar fmul.4033    auto IsUserFMulScalarTy = [](const Value *EEUser) {4034      // Check if the user is scalar fmul.4035      const auto *BO = dyn_cast<BinaryOperator>(EEUser);4036      return BO && BO->getOpcode() == BinaryOperator::FMul &&4037             !BO->getType()->isVectorTy();4038    };4039 4040    // Check if the extract index is from lane 0 or lane equivalent to 0 for a4041    // certain scalar type and a certain vector register width.4042    auto IsExtractLaneEquivalentToZero = [&](unsigned Idx, unsigned EltSz) {4043      auto RegWidth =4044          getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)4045              .getFixedValue();4046      return Idx == 0 || (RegWidth != 0 && (Idx * EltSz) % RegWidth == 0);4047    };4048 4049    // Check if the type constraints on input vector type and result scalar type4050    // of extractelement instruction are satisfied.4051    if (!isa<FixedVectorType>(Val) || !IsAllowedScalarTy(Val->getScalarType()))4052      return false;4053 4054    if (Scalar) {4055      DenseMap<User *, unsigned> UserToExtractIdx;4056      for (auto *U : Scalar->users()) {4057        if (!IsUserFMulScalarTy(U))4058          return false;4059        // Recording entry for the user is important. Index value is not4060        // important.4061        UserToExtractIdx[U];4062      }4063      if (UserToExtractIdx.empty())4064        return false;4065      for (auto &[S, U, L] : ScalarUserAndIdx) {4066        for (auto *U : S->users()) {4067          if (UserToExtractIdx.contains(U)) {4068            auto *FMul = cast<BinaryOperator>(U);4069            auto *Op0 = FMul->getOperand(0);4070            auto *Op1 = FMul->getOperand(1);4071            if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {4072              UserToExtractIdx[U] = L;4073              break;4074            }4075          }4076        }4077      }4078      for (auto &[U, L] : UserToExtractIdx) {4079        if (!IsExtractLaneEquivalentToZero(Index, Val->getScalarSizeInBits()) &&4080            !IsExtractLaneEquivalentToZero(L, Val->getScalarSizeInBits()))4081          return false;4082      }4083    } else {4084      const auto *EE = cast<ExtractElementInst>(I);4085 4086      const auto *IdxOp = dyn_cast<ConstantInt>(EE->getIndexOperand());4087      if (!IdxOp)4088        return false;4089 4090      return !EE->users().empty() && all_of(EE->users(), [&](const User *U) {4091        if (!IsUserFMulScalarTy(U))4092          return false;4093 4094        // Check if the other operand of extractelement is also extractelement4095        // from lane equivalent to 0.4096        const auto *BO = cast<BinaryOperator>(U);4097        const auto *OtherEE = dyn_cast<ExtractElementInst>(4098            BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));4099        if (OtherEE) {4100          const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());4101          if (!IdxOp)4102            return false;4103          return IsExtractLaneEquivalentToZero(4104              cast<ConstantInt>(OtherEE->getIndexOperand())4105                  ->getValue()4106                  .getZExtValue(),4107              OtherEE->getType()->getScalarSizeInBits());4108        }4109        return true;4110      });4111    }4112    return true;4113  };4114 4115  if (Opcode == Instruction::ExtractElement && (I || Scalar) &&4116      ExtractCanFuseWithFmul())4117    return 0;4118 4119  // All other insert/extracts cost this much.4120  return CostKind == TTI::TCK_CodeSize ? 14121                                       : ST->getVectorInsertExtractBaseCost();4122}4123 4124InstructionCost AArch64TTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val,4125                                                   TTI::TargetCostKind CostKind,4126                                                   unsigned Index,4127                                                   const Value *Op0,4128                                                   const Value *Op1) const {4129  // Treat insert at lane 0 into a poison vector as having zero cost. This4130  // ensures vector broadcasts via an insert + shuffle (and will be lowered to a4131  // single dup) are treated as cheap.4132  if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&4133      isa<PoisonValue>(Op0))4134    return 0;4135  return getVectorInstrCostHelper(Opcode, Val, CostKind, Index);4136}4137 4138InstructionCost AArch64TTIImpl::getVectorInstrCost(4139    unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,4140    Value *Scalar,4141    ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx) const {4142  return getVectorInstrCostHelper(Opcode, Val, CostKind, Index, nullptr, Scalar,4143                                  ScalarUserAndIdx);4144}4145 4146InstructionCost AArch64TTIImpl::getVectorInstrCost(const Instruction &I,4147                                                   Type *Val,4148                                                   TTI::TargetCostKind CostKind,4149                                                   unsigned Index) const {4150  return getVectorInstrCostHelper(I.getOpcode(), Val, CostKind, Index, &I);4151}4152 4153InstructionCost4154AArch64TTIImpl::getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val,4155                                                 TTI::TargetCostKind CostKind,4156                                                 unsigned Index) const {4157  if (isa<FixedVectorType>(Val))4158    return BaseT::getIndexedVectorInstrCostFromEnd(Opcode, Val, CostKind,4159                                                   Index);4160 4161  // This typically requires both while and lastb instructions in order4162  // to extract the last element. If this is in a loop the while4163  // instruction can at least be hoisted out, although it will consume a4164  // predicate register. The cost should be more expensive than the base4165  // extract cost, which is 2 for most CPUs.4166  return CostKind == TTI::TCK_CodeSize4167             ? 24168             : ST->getVectorInsertExtractBaseCost() + 1;4169}4170 4171InstructionCost AArch64TTIImpl::getScalarizationOverhead(4172    VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,4173    TTI::TargetCostKind CostKind, bool ForPoisonSrc,4174    ArrayRef<Value *> VL) const {4175  if (isa<ScalableVectorType>(Ty))4176    return InstructionCost::getInvalid();4177  if (Ty->getElementType()->isFloatingPointTy())4178    return BaseT::getScalarizationOverhead(Ty, DemandedElts, Insert, Extract,4179                                           CostKind);4180  unsigned VecInstCost =4181      CostKind == TTI::TCK_CodeSize ? 1 : ST->getVectorInsertExtractBaseCost();4182  return DemandedElts.popcount() * (Insert + Extract) * VecInstCost;4183}4184 4185std::optional<InstructionCost> AArch64TTIImpl::getFP16BF16PromoteCost(4186    Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info,4187    TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE,4188    std::function<InstructionCost(Type *)> InstCost) const {4189  if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())4190    return std::nullopt;4191  if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())4192    return std::nullopt;4193  if (CanUseSVE && Ty->isScalableTy() && ST->hasSVEB16B16() &&4194      ST->isNonStreamingSVEorSME2Available())4195    return std::nullopt;4196 4197  Type *PromotedTy = Ty->getWithNewType(Type::getFloatTy(Ty->getContext()));4198  InstructionCost Cost = getCastInstrCost(Instruction::FPExt, PromotedTy, Ty,4199                                          TTI::CastContextHint::None, CostKind);4200  if (!Op1Info.isConstant() && !Op2Info.isConstant())4201    Cost *= 2;4202  Cost += InstCost(PromotedTy);4203  if (IncludeTrunc)4204    Cost += getCastInstrCost(Instruction::FPTrunc, Ty, PromotedTy,4205                             TTI::CastContextHint::None, CostKind);4206  return Cost;4207}4208 4209InstructionCost AArch64TTIImpl::getArithmeticInstrCost(4210    unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,4211    TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info,4212    ArrayRef<const Value *> Args, const Instruction *CxtI) const {4213 4214  // The code-generator is currently not able to handle scalable vectors4215  // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting4216  // it. This change will be removed when code-generation for these types is4217  // sufficiently reliable.4218  if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))4219    if (VTy->getElementCount() == ElementCount::getScalable(1))4220      return InstructionCost::getInvalid();4221 4222  // TODO: Handle more cost kinds.4223  if (CostKind != TTI::TCK_RecipThroughput)4224    return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,4225                                         Op2Info, Args, CxtI);4226 4227  // Legalize the type.4228  std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);4229  int ISD = TLI->InstructionOpcodeToISD(Opcode);4230 4231  // Increase the cost for half and bfloat types if not architecturally4232  // supported.4233  if (ISD == ISD::FADD || ISD == ISD::FSUB || ISD == ISD::FMUL ||4234      ISD == ISD::FDIV || ISD == ISD::FREM)4235    if (auto PromotedCost = getFP16BF16PromoteCost(4236            Ty, CostKind, Op1Info, Op2Info, /*IncludeTrunc=*/true,4237            // There is not native support for fdiv/frem even with +sve-b16b16.4238            /*CanUseSVE=*/ISD != ISD::FDIV && ISD != ISD::FREM,4239            [&](Type *PromotedTy) {4240              return getArithmeticInstrCost(Opcode, PromotedTy, CostKind,4241                                            Op1Info, Op2Info);4242            }))4243      return *PromotedCost;4244 4245  // If the operation is a widening instruction (smull or umull) and both4246  // operands are extends the cost can be cheaper by considering that the4247  // operation will operate on the narrowest type size possible (double the4248  // largest input size) and a further extend.4249  if (Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {4250    if (ExtTy != Ty)4251      return getArithmeticInstrCost(Opcode, ExtTy, CostKind) +4252             getCastInstrCost(Instruction::ZExt, Ty, ExtTy,4253                              TTI::CastContextHint::None, CostKind);4254    return LT.first;4255  }4256 4257  switch (ISD) {4258  default:4259    return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,4260                                         Op2Info);4261  case ISD::SREM:4262  case ISD::SDIV:4263    /*4264    Notes for sdiv/srem specific costs:4265    1. This only considers the cases where the divisor is constant, uniform and4266    (pow-of-2/non-pow-of-2). Other cases are not important since they either4267    result in some form of (ldr + adrp), corresponding to constant vectors, or4268    scalarization of the division operation.4269    2. Constant divisors, either negative in whole or partially, don't result in4270    significantly different codegen as compared to positive constant divisors.4271    So, we don't consider negative divisors separately.4272    3. If the codegen is significantly different with SVE, it has been indicated4273    using comments at appropriate places.4274 4275    sdiv specific cases:4276    -----------------------------------------------------------------------4277    codegen                       | pow-of-2               | Type4278    -----------------------------------------------------------------------4279    add + cmp + csel + asr        | Y                      | i644280    add + cmp + csel + asr        | Y                      | i324281    -----------------------------------------------------------------------4282 4283    srem specific cases:4284    -----------------------------------------------------------------------4285    codegen                       | pow-of-2               | Type4286    -----------------------------------------------------------------------4287    negs + and + and + csneg      | Y                      | i644288    negs + and + and + csneg      | Y                      | i324289    -----------------------------------------------------------------------4290 4291    other sdiv/srem cases:4292    -------------------------------------------------------------------------4293    common codegen            | + srem     | + sdiv     | pow-of-2  | Type4294    -------------------------------------------------------------------------4295    smulh + asr + add + add   | -          | -          | N         | i644296    smull + lsr + add + add   | -          | -          | N         | i324297    usra                      | and + sub  | sshr       | Y         | <2 x i64>4298    2 * (scalar code)         | -          | -          | N         | <2 x i64>4299    usra                      | bic + sub  | sshr + neg | Y         | <4 x i32>4300    smull2 + smull + uzp2     | mls        | -          | N         | <4 x i32>4301           + sshr  + usra     |            |            |           |4302    -------------------------------------------------------------------------4303    */4304    if (Op2Info.isConstant() && Op2Info.isUniform()) {4305      InstructionCost AddCost =4306          getArithmeticInstrCost(Instruction::Add, Ty, CostKind,4307                                 Op1Info.getNoProps(), Op2Info.getNoProps());4308      InstructionCost AsrCost =4309          getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,4310                                 Op1Info.getNoProps(), Op2Info.getNoProps());4311      InstructionCost MulCost =4312          getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,4313                                 Op1Info.getNoProps(), Op2Info.getNoProps());4314      // add/cmp/csel/csneg should have similar cost while asr/negs/and should4315      // have similar cost.4316      auto VT = TLI->getValueType(DL, Ty);4317      if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {4318        if (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2()) {4319          // Neg can be folded into the asr instruction.4320          return ISD == ISD::SDIV ? (3 * AddCost + AsrCost)4321                                  : (3 * AsrCost + AddCost);4322        } else {4323          return MulCost + AsrCost + 2 * AddCost;4324        }4325      } else if (VT.isVector()) {4326        InstructionCost UsraCost = 2 * AsrCost;4327        if (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2()) {4328          // Division with scalable types corresponds to native 'asrd'4329          // instruction when SVE is available.4330          // e.g. %1 = sdiv <vscale x 4 x i32> %a, splat (i32 8)4331 4332          // One more for the negation in SDIV4333          InstructionCost Cost =4334              (Op2Info.isNegatedPowerOf2() && ISD == ISD::SDIV) ? AsrCost : 0;4335          if (Ty->isScalableTy() && ST->hasSVE())4336            Cost += 2 * AsrCost;4337          else {4338            Cost +=4339                UsraCost +4340                (ISD == ISD::SDIV4341                     ? (LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost4342                     : 2 * AddCost);4343          }4344          return Cost;4345        } else if (LT.second == MVT::v2i64) {4346          return VT.getVectorNumElements() *4347                 getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind,4348                                        Op1Info.getNoProps(),4349                                        Op2Info.getNoProps());4350        } else {4351          // When SVE is available, we get:4352          // smulh + lsr + add/sub + asr + add/sub.4353          if (Ty->isScalableTy() && ST->hasSVE())4354            return MulCost /*smulh cost*/ + 2 * AddCost + 2 * AsrCost;4355          return 2 * MulCost + AddCost /*uzp2 cost*/ + AsrCost + UsraCost;4356        }4357      }4358    }4359    if (Op2Info.isConstant() && !Op2Info.isUniform() &&4360        LT.second.isFixedLengthVector()) {4361      // FIXME: When the constant vector is non-uniform, this may result in4362      // loading the vector from constant pool or in some cases, may also result4363      // in scalarization. For now, we are approximating this with the4364      // scalarization cost.4365      auto ExtractCost = 2 * getVectorInstrCost(Instruction::ExtractElement, Ty,4366                                                CostKind, -1, nullptr, nullptr);4367      auto InsertCost = getVectorInstrCost(Instruction::InsertElement, Ty,4368                                           CostKind, -1, nullptr, nullptr);4369      unsigned NElts = cast<FixedVectorType>(Ty)->getNumElements();4370      return ExtractCost + InsertCost +4371             NElts * getArithmeticInstrCost(Opcode, Ty->getScalarType(),4372                                            CostKind, Op1Info.getNoProps(),4373                                            Op2Info.getNoProps());4374    }4375    [[fallthrough]];4376  case ISD::UDIV:4377  case ISD::UREM: {4378    auto VT = TLI->getValueType(DL, Ty);4379    if (Op2Info.isConstant()) {4380      // If the operand is a power of 2 we can use the shift or and cost.4381      if (ISD == ISD::UDIV && Op2Info.isPowerOf2())4382        return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,4383                                      Op1Info.getNoProps(),4384                                      Op2Info.getNoProps());4385      if (ISD == ISD::UREM && Op2Info.isPowerOf2())4386        return getArithmeticInstrCost(Instruction::And, Ty, CostKind,4387                                      Op1Info.getNoProps(),4388                                      Op2Info.getNoProps());4389 4390      if (ISD == ISD::UDIV || ISD == ISD::UREM) {4391        // Divides by a constant are expanded to MULHU + SUB + SRL + ADD + SRL.4392        // The MULHU will be expanded to UMULL for the types not listed below,4393        // and will become a pair of UMULL+MULL2 for 128bit vectors.4394        bool HasMULH = VT == MVT::i64 || LT.second == MVT::nxv2i64 ||4395                       LT.second == MVT::nxv4i32 || LT.second == MVT::nxv8i16 ||4396                       LT.second == MVT::nxv16i8;4397        bool Is128bit = LT.second.is128BitVector();4398 4399        InstructionCost MulCost =4400            getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,4401                                   Op1Info.getNoProps(), Op2Info.getNoProps());4402        InstructionCost AddCost =4403            getArithmeticInstrCost(Instruction::Add, Ty, CostKind,4404                                   Op1Info.getNoProps(), Op2Info.getNoProps());4405        InstructionCost ShrCost =4406            getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,4407                                   Op1Info.getNoProps(), Op2Info.getNoProps());4408        InstructionCost DivCost = MulCost * (Is128bit ? 2 : 1) + // UMULL/UMULH4409                                  (HasMULH ? 0 : ShrCost) +      // UMULL shift4410                                  AddCost * 2 + ShrCost;4411        return DivCost + (ISD == ISD::UREM ? MulCost + AddCost : 0);4412      }4413    }4414 4415    // div i128's are lowered as libcalls.  Pass nullptr as (u)divti3 calls are4416    // emitted by the backend even when those functions are not declared in the4417    // module.4418    if (!VT.isVector() && VT.getSizeInBits() > 64)4419      return getCallInstrCost(/*Function*/ nullptr, Ty, {Ty, Ty}, CostKind);4420 4421    InstructionCost Cost = BaseT::getArithmeticInstrCost(4422        Opcode, Ty, CostKind, Op1Info, Op2Info);4423    if (Ty->isVectorTy() && (ISD == ISD::SDIV || ISD == ISD::UDIV)) {4424      if (TLI->isOperationLegalOrCustom(ISD, LT.second) && ST->hasSVE()) {4425        // SDIV/UDIV operations are lowered using SVE, then we can have less4426        // costs.4427        if (VT.isSimple() && isa<FixedVectorType>(Ty) &&4428            Ty->getPrimitiveSizeInBits().getFixedValue() < 128) {4429          static const CostTblEntry DivTbl[]{4430              {ISD::SDIV, MVT::v2i8, 5},  {ISD::SDIV, MVT::v4i8, 8},4431              {ISD::SDIV, MVT::v8i8, 8},  {ISD::SDIV, MVT::v2i16, 5},4432              {ISD::SDIV, MVT::v4i16, 5}, {ISD::SDIV, MVT::v2i32, 1},4433              {ISD::UDIV, MVT::v2i8, 5},  {ISD::UDIV, MVT::v4i8, 8},4434              {ISD::UDIV, MVT::v8i8, 8},  {ISD::UDIV, MVT::v2i16, 5},4435              {ISD::UDIV, MVT::v4i16, 5}, {ISD::UDIV, MVT::v2i32, 1}};4436 4437          const auto *Entry = CostTableLookup(DivTbl, ISD, VT.getSimpleVT());4438          if (nullptr != Entry)4439            return Entry->Cost;4440        }4441        // For 8/16-bit elements, the cost is higher because the type4442        // requires promotion and possibly splitting:4443        if (LT.second.getScalarType() == MVT::i8)4444          Cost *= 8;4445        else if (LT.second.getScalarType() == MVT::i16)4446          Cost *= 4;4447        return Cost;4448      } else {4449        // If one of the operands is a uniform constant then the cost for each4450        // element is Cost for insertion, extraction and division.4451        // Insertion cost = 2, Extraction Cost = 2, Division = cost for the4452        // operation with scalar type4453        if ((Op1Info.isConstant() && Op1Info.isUniform()) ||4454            (Op2Info.isConstant() && Op2Info.isUniform())) {4455          if (auto *VTy = dyn_cast<FixedVectorType>(Ty)) {4456            InstructionCost DivCost = BaseT::getArithmeticInstrCost(4457                Opcode, Ty->getScalarType(), CostKind, Op1Info, Op2Info);4458            return (4 + DivCost) * VTy->getNumElements();4459          }4460        }4461        // On AArch64, without SVE, vector divisions are expanded4462        // into scalar divisions of each pair of elements.4463        Cost += getVectorInstrCost(Instruction::ExtractElement, Ty, CostKind,4464                                   -1, nullptr, nullptr);4465        Cost += getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, -1,4466                                   nullptr, nullptr);4467      }4468 4469      // TODO: if one of the arguments is scalar, then it's not necessary to4470      // double the cost of handling the vector elements.4471      Cost += Cost;4472    }4473    return Cost;4474  }4475  case ISD::MUL:4476    // When SVE is available, then we can lower the v2i64 operation using4477    // the SVE mul instruction, which has a lower cost.4478    if (LT.second == MVT::v2i64 && ST->hasSVE())4479      return LT.first;4480 4481    // When SVE is not available, there is no MUL.2d instruction,4482    // which means mul <2 x i64> is expensive as elements are extracted4483    // from the vectors and the muls scalarized.4484    // As getScalarizationOverhead is a bit too pessimistic, we4485    // estimate the cost for a i64 vector directly here, which is:4486    // - four 2-cost i64 extracts,4487    // - two 2-cost i64 inserts, and4488    // - two 1-cost muls.4489    // So, for a v2i64 with LT.First = 1 the cost is 14, and for a v4i64 with4490    // LT.first = 2 the cost is 28.4491    if (LT.second != MVT::v2i64)4492      return LT.first;4493    return cast<VectorType>(Ty)->getElementCount().getKnownMinValue() *4494           (getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind) +4495            getVectorInstrCost(Instruction::ExtractElement, Ty, CostKind, -1,4496                               nullptr, nullptr) *4497                2 +4498            getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, -1,4499                               nullptr, nullptr));4500  case ISD::ADD:4501  case ISD::XOR:4502  case ISD::OR:4503  case ISD::AND:4504  case ISD::SRL:4505  case ISD::SRA:4506  case ISD::SHL:4507    // These nodes are marked as 'custom' for combining purposes only.4508    // We know that they are legal. See LowerAdd in ISelLowering.4509    return LT.first;4510 4511  case ISD::FNEG:4512    // Scalar fmul(fneg) or fneg(fmul) can be converted to fnmul4513    if ((Ty->isFloatTy() || Ty->isDoubleTy() ||4514         (Ty->isHalfTy() && ST->hasFullFP16())) &&4515        CxtI &&4516        ((CxtI->hasOneUse() &&4517          match(*CxtI->user_begin(), m_FMul(m_Value(), m_Value()))) ||4518         match(CxtI->getOperand(0), m_FMul(m_Value(), m_Value()))))4519      return 0;4520    [[fallthrough]];4521  case ISD::FADD:4522  case ISD::FSUB:4523    if (!Ty->getScalarType()->isFP128Ty())4524      return LT.first;4525    [[fallthrough]];4526  case ISD::FMUL:4527  case ISD::FDIV:4528    // These nodes are marked as 'custom' just to lower them to SVE.4529    // We know said lowering will incur no additional cost.4530    if (!Ty->getScalarType()->isFP128Ty())4531      return 2 * LT.first;4532 4533    return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,4534                                         Op2Info);4535  case ISD::FREM:4536    // Pass nullptr as fmod/fmodf calls are emitted by the backend even when4537    // those functions are not declared in the module.4538    if (!Ty->isVectorTy())4539      return getCallInstrCost(/*Function*/ nullptr, Ty, {Ty, Ty}, CostKind);4540    return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,4541                                         Op2Info);4542  }4543}4544 4545InstructionCost4546AArch64TTIImpl::getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE,4547                                          const SCEV *Ptr,4548                                          TTI::TargetCostKind CostKind) const {4549  // Address computations in vectorized code with non-consecutive addresses will4550  // likely result in more instructions compared to scalar code where the4551  // computation can more often be merged into the index mode. The resulting4552  // extra micro-ops can significantly decrease throughput.4553  unsigned NumVectorInstToHideOverhead = NeonNonConstStrideOverhead;4554  int MaxMergeDistance = 64;4555 4556  if (PtrTy->isVectorTy() && SE &&4557      !BaseT::isConstantStridedAccessLessThan(SE, Ptr, MaxMergeDistance + 1))4558    return NumVectorInstToHideOverhead;4559 4560  // In many cases the address computation is not merged into the instruction4561  // addressing mode.4562  return 1;4563}4564 4565/// Check whether Opcode1 has less throughput according to the scheduling4566/// model than Opcode2.4567bool AArch64TTIImpl::hasKnownLowerThroughputFromSchedulingModel(4568    unsigned Opcode1, unsigned Opcode2) const {4569  const MCSchedModel &Sched = ST->getSchedModel();4570  const TargetInstrInfo *TII = ST->getInstrInfo();4571  if (!Sched.hasInstrSchedModel())4572    return false;4573 4574  const MCSchedClassDesc *SCD1 =4575      Sched.getSchedClassDesc(TII->get(Opcode1).getSchedClass());4576  const MCSchedClassDesc *SCD2 =4577      Sched.getSchedClassDesc(TII->get(Opcode2).getSchedClass());4578  // We cannot handle variant scheduling classes without an MI. If we need to4579  // support them for any of the instructions we query the information of we4580  // might need to add a way to resolve them without a MI or not use the4581  // scheduling info.4582  assert(!SCD1->isVariant() && !SCD2->isVariant() &&4583         "Cannot handle variant scheduling classes without an MI");4584  if (!SCD1->isValid() || !SCD2->isValid())4585    return false;4586 4587  return MCSchedModel::getReciprocalThroughput(*ST, *SCD1) >4588         MCSchedModel::getReciprocalThroughput(*ST, *SCD2);4589}4590 4591InstructionCost AArch64TTIImpl::getCmpSelInstrCost(4592    unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,4593    TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info,4594    TTI::OperandValueInfo Op2Info, const Instruction *I) const {4595  // We don't lower some vector selects well that are wider than the register4596  // width. TODO: Improve this with different cost kinds.4597  if (isa<FixedVectorType>(ValTy) && Opcode == Instruction::Select) {4598    // We would need this many instructions to hide the scalarization happening.4599    const int AmortizationCost = 20;4600 4601    // If VecPred is not set, check if we can get a predicate from the context4602    // instruction, if its type matches the requested ValTy.4603    if (VecPred == CmpInst::BAD_ICMP_PREDICATE && I && I->getType() == ValTy) {4604      CmpPredicate CurrentPred;4605      if (match(I, m_Select(m_Cmp(CurrentPred, m_Value(), m_Value()), m_Value(),4606                            m_Value())))4607        VecPred = CurrentPred;4608    }4609    // Check if we have a compare/select chain that can be lowered using4610    // a (F)CMxx & BFI pair.4611    if (CmpInst::isIntPredicate(VecPred) || VecPred == CmpInst::FCMP_OLE ||4612        VecPred == CmpInst::FCMP_OLT || VecPred == CmpInst::FCMP_OGT ||4613        VecPred == CmpInst::FCMP_OGE || VecPred == CmpInst::FCMP_OEQ ||4614        VecPred == CmpInst::FCMP_UNE) {4615      static const auto ValidMinMaxTys = {4616          MVT::v8i8,  MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,4617          MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};4618      static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};4619 4620      auto LT = getTypeLegalizationCost(ValTy);4621      if (any_of(ValidMinMaxTys, [&LT](MVT M) { return M == LT.second; }) ||4622          (ST->hasFullFP16() &&4623           any_of(ValidFP16MinMaxTys, [&LT](MVT M) { return M == LT.second; })))4624        return LT.first;4625    }4626 4627    static const TypeConversionCostTblEntry VectorSelectTbl[] = {4628        {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},4629        {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},4630        {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},4631        {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},4632        {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},4633        {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},4634        {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},4635        {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},4636        {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},4637        {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},4638        {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};4639 4640    EVT SelCondTy = TLI->getValueType(DL, CondTy);4641    EVT SelValTy = TLI->getValueType(DL, ValTy);4642    if (SelCondTy.isSimple() && SelValTy.isSimple()) {4643      if (const auto *Entry = ConvertCostTableLookup(VectorSelectTbl, Opcode,4644                                                     SelCondTy.getSimpleVT(),4645                                                     SelValTy.getSimpleVT()))4646        return Entry->Cost;4647    }4648  }4649 4650  if (Opcode == Instruction::FCmp) {4651    if (auto PromotedCost = getFP16BF16PromoteCost(4652            ValTy, CostKind, Op1Info, Op2Info, /*IncludeTrunc=*/false,4653            // TODO: Consider costing SVE FCMPs.4654            /*CanUseSVE=*/false, [&](Type *PromotedTy) {4655              InstructionCost Cost =4656                  getCmpSelInstrCost(Opcode, PromotedTy, CondTy, VecPred,4657                                     CostKind, Op1Info, Op2Info);4658              if (isa<VectorType>(PromotedTy))4659                Cost += getCastInstrCost(4660                    Instruction::Trunc,4661                    VectorType::getInteger(cast<VectorType>(ValTy)),4662                    VectorType::getInteger(cast<VectorType>(PromotedTy)),4663                    TTI::CastContextHint::None, CostKind);4664              return Cost;4665            }))4666      return *PromotedCost;4667 4668    auto LT = getTypeLegalizationCost(ValTy);4669    // Model unknown fp compares as a libcall.4670    if (LT.second.getScalarType() != MVT::f64 &&4671        LT.second.getScalarType() != MVT::f32 &&4672        LT.second.getScalarType() != MVT::f16)4673      return LT.first * getCallInstrCost(/*Function*/ nullptr, ValTy,4674                                         {ValTy, ValTy}, CostKind);4675 4676    // Some comparison operators require expanding to multiple compares + or.4677    unsigned Factor = 1;4678    if (!CondTy->isVectorTy() &&4679        (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ))4680      Factor = 2; // fcmp with 2 selects4681    else if (isa<FixedVectorType>(ValTy) &&4682             (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ ||4683              VecPred == FCmpInst::FCMP_ORD || VecPred == FCmpInst::FCMP_UNO))4684      Factor = 3; // fcmxx+fcmyy+or4685    else if (isa<ScalableVectorType>(ValTy) &&4686             (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ))4687      Factor = 3; // fcmxx+fcmyy+or4688 4689    if (isa<ScalableVectorType>(ValTy) &&4690        CostKind == TTI::TCK_RecipThroughput &&4691        hasKnownLowerThroughputFromSchedulingModel(AArch64::FCMEQ_PPzZZ_S,4692                                                   AArch64::FCMEQv4f32))4693      Factor *= 2;4694 4695    return Factor * (CostKind == TTI::TCK_Latency ? 2 : LT.first);4696  }4697 4698  // Treat the icmp in icmp(and, 0) or icmp(and, -1/1) when it can be folded to4699  // icmp(and, 0) as free, as we can make use of ands, but only if the4700  // comparison is not unsigned. FIXME: Enable for non-throughput cost kinds4701  // providing it will not cause performance regressions.4702  if (CostKind == TTI::TCK_RecipThroughput && ValTy->isIntegerTy() &&4703      Opcode == Instruction::ICmp && I && !CmpInst::isUnsigned(VecPred) &&4704      TLI->isTypeLegal(TLI->getValueType(DL, ValTy)) &&4705      match(I->getOperand(0), m_And(m_Value(), m_Value()))) {4706    if (match(I->getOperand(1), m_Zero()))4707      return 0;4708 4709    // x >= 1 / x < 1 -> x > 0 / x <= 04710    if (match(I->getOperand(1), m_One()) &&4711        (VecPred == CmpInst::ICMP_SLT || VecPred == CmpInst::ICMP_SGE))4712      return 0;4713 4714    // x <= -1 / x > -1 -> x > 0 / x <= 04715    if (match(I->getOperand(1), m_AllOnes()) &&4716        (VecPred == CmpInst::ICMP_SLE || VecPred == CmpInst::ICMP_SGT))4717      return 0;4718  }4719 4720  // The base case handles scalable vectors fine for now, since it treats the4721  // cost as 1 * legalization cost.4722  return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,4723                                   Op1Info, Op2Info, I);4724}4725 4726AArch64TTIImpl::TTI::MemCmpExpansionOptions4727AArch64TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {4728  TTI::MemCmpExpansionOptions Options;4729  if (ST->requiresStrictAlign()) {4730    // TODO: Add cost modeling for strict align. Misaligned loads expand to4731    // a bunch of instructions when strict align is enabled.4732    return Options;4733  }4734  Options.AllowOverlappingLoads = true;4735  Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);4736  Options.NumLoadsPerBlock = Options.MaxNumLoads;4737  // TODO: Though vector loads usually perform well on AArch64, in some targets4738  // they may wake up the FP unit, which raises the power consumption.  Perhaps4739  // they could be used with no holds barred (-O3).4740  Options.LoadSizes = {8, 4, 2, 1};4741  Options.AllowedTailExpansions = {3, 5, 6};4742  return Options;4743}4744 4745bool AArch64TTIImpl::prefersVectorizedAddressing() const {4746  return ST->hasSVE();4747}4748 4749InstructionCost4750AArch64TTIImpl::getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA,4751                                      TTI::TargetCostKind CostKind) const {4752  Type *Src = MICA.getDataType();4753 4754  if (useNeonVector(Src))4755    return BaseT::getMaskedMemoryOpCost(MICA, CostKind);4756  auto LT = getTypeLegalizationCost(Src);4757  if (!LT.first.isValid())4758    return InstructionCost::getInvalid();4759 4760  // Return an invalid cost for element types that we are unable to lower.4761  auto *VT = cast<VectorType>(Src);4762  if (VT->getElementType()->isIntegerTy(1))4763    return InstructionCost::getInvalid();4764 4765  // The code-generator is currently not able to handle scalable vectors4766  // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting4767  // it. This change will be removed when code-generation for these types is4768  // sufficiently reliable.4769  if (VT->getElementCount() == ElementCount::getScalable(1))4770    return InstructionCost::getInvalid();4771 4772  return LT.first;4773}4774 4775// This function returns gather/scatter overhead either from4776// user-provided value or specialized values per-target from \p ST.4777static unsigned getSVEGatherScatterOverhead(unsigned Opcode,4778                                            const AArch64Subtarget *ST) {4779  assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&4780         "Should be called on only load or stores.");4781  switch (Opcode) {4782  case Instruction::Load:4783    if (SVEGatherOverhead.getNumOccurrences() > 0)4784      return SVEGatherOverhead;4785    return ST->getGatherOverhead();4786    break;4787  case Instruction::Store:4788    if (SVEScatterOverhead.getNumOccurrences() > 0)4789      return SVEScatterOverhead;4790    return ST->getScatterOverhead();4791    break;4792  default:4793    llvm_unreachable("Shouldn't have reached here");4794  }4795}4796 4797InstructionCost AArch64TTIImpl::getGatherScatterOpCost(4798    unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask,4799    Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) const {4800  if (useNeonVector(DataTy) || !isLegalMaskedGatherScatter(DataTy))4801    return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask,4802                                         Alignment, CostKind, I);4803  auto *VT = cast<VectorType>(DataTy);4804  auto LT = getTypeLegalizationCost(DataTy);4805  if (!LT.first.isValid())4806    return InstructionCost::getInvalid();4807 4808  // Return an invalid cost for element types that we are unable to lower.4809  if (!LT.second.isVector() ||4810      !isElementTypeLegalForScalableVector(VT->getElementType()) ||4811      VT->getElementType()->isIntegerTy(1))4812    return InstructionCost::getInvalid();4813 4814  // The code-generator is currently not able to handle scalable vectors4815  // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting4816  // it. This change will be removed when code-generation for these types is4817  // sufficiently reliable.4818  if (VT->getElementCount() == ElementCount::getScalable(1))4819    return InstructionCost::getInvalid();4820 4821  ElementCount LegalVF = LT.second.getVectorElementCount();4822  InstructionCost MemOpCost =4823      getMemoryOpCost(Opcode, VT->getElementType(), Alignment, 0, CostKind,4824                      {TTI::OK_AnyValue, TTI::OP_None}, I);4825  // Add on an overhead cost for using gathers/scatters.4826  MemOpCost *= getSVEGatherScatterOverhead(Opcode, ST);4827  return LT.first * MemOpCost * getMaxNumElements(LegalVF);4828}4829 4830bool AArch64TTIImpl::useNeonVector(const Type *Ty) const {4831  return isa<FixedVectorType>(Ty) && !ST->useSVEForFixedLengthVectors();4832}4833 4834InstructionCost AArch64TTIImpl::getMemoryOpCost(unsigned Opcode, Type *Ty,4835                                                Align Alignment,4836                                                unsigned AddressSpace,4837                                                TTI::TargetCostKind CostKind,4838                                                TTI::OperandValueInfo OpInfo,4839                                                const Instruction *I) const {4840  EVT VT = TLI->getValueType(DL, Ty, true);4841  // Type legalization can't handle structs4842  if (VT == MVT::Other)4843    return BaseT::getMemoryOpCost(Opcode, Ty, Alignment, AddressSpace,4844                                  CostKind);4845 4846  auto LT = getTypeLegalizationCost(Ty);4847  if (!LT.first.isValid())4848    return InstructionCost::getInvalid();4849 4850  // The code-generator is currently not able to handle scalable vectors4851  // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting4852  // it. This change will be removed when code-generation for these types is4853  // sufficiently reliable.4854  // We also only support full register predicate loads and stores.4855  if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))4856    if (VTy->getElementCount() == ElementCount::getScalable(1) ||4857        (VTy->getElementType()->isIntegerTy(1) &&4858         !VTy->getElementCount().isKnownMultipleOf(4859             ElementCount::getScalable(16))))4860      return InstructionCost::getInvalid();4861 4862  // TODO: consider latency as well for TCK_SizeAndLatency.4863  if (CostKind == TTI::TCK_CodeSize || CostKind == TTI::TCK_SizeAndLatency)4864    return LT.first;4865 4866  if (CostKind != TTI::TCK_RecipThroughput)4867    return 1;4868 4869  if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&4870      LT.second.is128BitVector() && Alignment < Align(16)) {4871    // Unaligned stores are extremely inefficient. We don't split all4872    // unaligned 128-bit stores because the negative impact that has shown in4873    // practice on inlined block copy code.4874    // We make such stores expensive so that we will only vectorize if there4875    // are 6 other instructions getting vectorized.4876    const int AmortizationCost = 6;4877 4878    return LT.first * 2 * AmortizationCost;4879  }4880 4881  // Opaque ptr or ptr vector types are i64s and can be lowered to STP/LDPs.4882  if (Ty->isPtrOrPtrVectorTy())4883    return LT.first;4884 4885  if (useNeonVector(Ty)) {4886    // Check truncating stores and extending loads.4887    if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {4888      // v4i8 types are lowered to scalar a load/store and sshll/xtn.4889      if (VT == MVT::v4i8)4890        return 2;4891      // Otherwise we need to scalarize.4892      return cast<FixedVectorType>(Ty)->getNumElements() * 2;4893    }4894    EVT EltVT = VT.getVectorElementType();4895    unsigned EltSize = EltVT.getScalarSizeInBits();4896    if (!isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||4897        VT.getVectorNumElements() >= (128 / EltSize) || Alignment != Align(1))4898      return LT.first;4899    // FIXME: v3i8 lowering currently is very inefficient, due to automatic4900    // widening to v4i8, which produces suboptimal results.4901    if (VT.getVectorNumElements() == 3 && EltVT == MVT::i8)4902      return LT.first;4903 4904    // Check non-power-of-2 loads/stores for legal vector element types with4905    // NEON. Non-power-of-2 memory ops will get broken down to a set of4906    // operations on smaller power-of-2 ops, including ld1/st1.4907    LLVMContext &C = Ty->getContext();4908    InstructionCost Cost(0);4909    SmallVector<EVT> TypeWorklist;4910    TypeWorklist.push_back(VT);4911    while (!TypeWorklist.empty()) {4912      EVT CurrVT = TypeWorklist.pop_back_val();4913      unsigned CurrNumElements = CurrVT.getVectorNumElements();4914      if (isPowerOf2_32(CurrNumElements)) {4915        Cost += 1;4916        continue;4917      }4918 4919      unsigned PrevPow2 = NextPowerOf2(CurrNumElements) / 2;4920      TypeWorklist.push_back(EVT::getVectorVT(C, EltVT, PrevPow2));4921      TypeWorklist.push_back(4922          EVT::getVectorVT(C, EltVT, CurrNumElements - PrevPow2));4923    }4924    return Cost;4925  }4926 4927  return LT.first;4928}4929 4930InstructionCost AArch64TTIImpl::getInterleavedMemoryOpCost(4931    unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,4932    Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,4933    bool UseMaskForCond, bool UseMaskForGaps) const {4934  assert(Factor >= 2 && "Invalid interleave factor");4935  auto *VecVTy = cast<VectorType>(VecTy);4936 4937  if (VecTy->isScalableTy() && !ST->hasSVE())4938    return InstructionCost::getInvalid();4939 4940  // Scalable VFs will emit vector.[de]interleave intrinsics, and currently we4941  // only have lowering for power-of-2 factors.4942  // TODO: Add lowering for vector.[de]interleave3 intrinsics and support in4943  // InterleavedAccessPass for ld3/st34944  if (VecTy->isScalableTy() && !isPowerOf2_32(Factor))4945    return InstructionCost::getInvalid();4946 4947  // Vectorization for masked interleaved accesses is only enabled for scalable4948  // VF.4949  if (!VecTy->isScalableTy() && (UseMaskForCond || UseMaskForGaps))4950    return InstructionCost::getInvalid();4951 4952  if (!UseMaskForGaps && Factor <= TLI->getMaxSupportedInterleaveFactor()) {4953    unsigned MinElts = VecVTy->getElementCount().getKnownMinValue();4954    auto *SubVecTy =4955        VectorType::get(VecVTy->getElementType(),4956                        VecVTy->getElementCount().divideCoefficientBy(Factor));4957 4958    // ldN/stN only support legal vector types of size 64 or 128 in bits.4959    // Accesses having vector types that are a multiple of 128 bits can be4960    // matched to more than one ldN/stN instruction.4961    bool UseScalable;4962    if (MinElts % Factor == 0 &&4963        TLI->isLegalInterleavedAccessType(SubVecTy, DL, UseScalable))4964      return Factor * TLI->getNumInterleavedAccesses(SubVecTy, DL, UseScalable);4965  }4966 4967  return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,4968                                           Alignment, AddressSpace, CostKind,4969                                           UseMaskForCond, UseMaskForGaps);4970}4971 4972InstructionCost4973AArch64TTIImpl::getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const {4974  InstructionCost Cost = 0;4975  TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;4976  for (auto *I : Tys) {4977    if (!I->isVectorTy())4978      continue;4979    if (I->getScalarSizeInBits() * cast<FixedVectorType>(I)->getNumElements() ==4980        128)4981      Cost += getMemoryOpCost(Instruction::Store, I, Align(128), 0, CostKind) +4982              getMemoryOpCost(Instruction::Load, I, Align(128), 0, CostKind);4983  }4984  return Cost;4985}4986 4987unsigned AArch64TTIImpl::getMaxInterleaveFactor(ElementCount VF) const {4988  return ST->getMaxInterleaveFactor();4989}4990 4991// For Falkor, we want to avoid having too many strided loads in a loop since4992// that can exhaust the HW prefetcher resources.  We adjust the unroller4993// MaxCount preference below to attempt to ensure unrolling doesn't create too4994// many strided loads.4995static void4996getFalkorUnrollingPreferences(Loop *L, ScalarEvolution &SE,4997                              TargetTransformInfo::UnrollingPreferences &UP) {4998  enum { MaxStridedLoads = 7 };4999  auto countStridedLoads = [](Loop *L, ScalarEvolution &SE) {5000    int StridedLoads = 0;5001    // FIXME? We could make this more precise by looking at the CFG and5002    // e.g. not counting loads in each side of an if-then-else diamond.5003    for (const auto BB : L->blocks()) {5004      for (auto &I : *BB) {5005        LoadInst *LMemI = dyn_cast<LoadInst>(&I);5006        if (!LMemI)5007          continue;5008 5009        Value *PtrValue = LMemI->getPointerOperand();5010        if (L->isLoopInvariant(PtrValue))5011          continue;5012 5013        const SCEV *LSCEV = SE.getSCEV(PtrValue);5014        const SCEVAddRecExpr *LSCEVAddRec = dyn_cast<SCEVAddRecExpr>(LSCEV);5015        if (!LSCEVAddRec || !LSCEVAddRec->isAffine())5016          continue;5017 5018        // FIXME? We could take pairing of unrolled load copies into account5019        // by looking at the AddRec, but we would probably have to limit this5020        // to loops with no stores or other memory optimization barriers.5021        ++StridedLoads;5022        // We've seen enough strided loads that seeing more won't make a5023        // difference.5024        if (StridedLoads > MaxStridedLoads / 2)5025          return StridedLoads;5026      }5027    }5028    return StridedLoads;5029  };5030 5031  int StridedLoads = countStridedLoads(L, SE);5032  LLVM_DEBUG(dbgs() << "falkor-hwpf: detected " << StridedLoads5033                    << " strided loads\n");5034  // Pick the largest power of 2 unroll count that won't result in too many5035  // strided loads.5036  if (StridedLoads) {5037    UP.MaxCount = 1 << Log2_32(MaxStridedLoads / StridedLoads);5038    LLVM_DEBUG(dbgs() << "falkor-hwpf: setting unroll MaxCount to "5039                      << UP.MaxCount << '\n');5040  }5041}5042 5043// This function returns true if the loop:5044//  1. Has a valid cost, and5045//  2. Has a cost within the supplied budget.5046// Otherwise it returns false.5047static bool isLoopSizeWithinBudget(Loop *L, const AArch64TTIImpl &TTI,5048                                   InstructionCost Budget,5049                                   unsigned *FinalSize) {5050  // Estimate the size of the loop.5051  InstructionCost LoopCost = 0;5052 5053  for (auto *BB : L->getBlocks()) {5054    for (auto &I : *BB) {5055      SmallVector<const Value *, 4> Operands(I.operand_values());5056      InstructionCost Cost =5057          TTI.getInstructionCost(&I, Operands, TTI::TCK_CodeSize);5058      // This can happen with intrinsics that don't currently have a cost model5059      // or for some operations that require SVE.5060      if (!Cost.isValid())5061        return false;5062 5063      LoopCost += Cost;5064      if (LoopCost > Budget)5065        return false;5066    }5067  }5068 5069  if (FinalSize)5070    *FinalSize = LoopCost.getValue();5071  return true;5072}5073 5074static bool shouldUnrollMultiExitLoop(Loop *L, ScalarEvolution &SE,5075                                      const AArch64TTIImpl &TTI) {5076  // Only consider loops with unknown trip counts for which we can determine5077  // a symbolic expression. Multi-exit loops with small known trip counts will5078  // likely be unrolled anyway.5079  const SCEV *BTC = SE.getSymbolicMaxBackedgeTakenCount(L);5080  if (isa<SCEVConstant>(BTC) || isa<SCEVCouldNotCompute>(BTC))5081    return false;5082 5083  // It might not be worth unrolling loops with low max trip counts. Restrict5084  // this to max trip counts > 32 for now.5085  unsigned MaxTC = SE.getSmallConstantMaxTripCount(L);5086  if (MaxTC > 0 && MaxTC <= 32)5087    return false;5088 5089  // Make sure the loop size is <= 5.5090  if (!isLoopSizeWithinBudget(L, TTI, 5, nullptr))5091    return false;5092 5093  // Small search loops with multiple exits can be highly beneficial to unroll.5094  // We only care about loops with exactly two exiting blocks, although each5095  // block could jump to the same exit block.5096  ArrayRef<BasicBlock *> Blocks = L->getBlocks();5097  if (Blocks.size() != 2)5098    return false;5099 5100  if (any_of(Blocks, [](BasicBlock *BB) {5101        return !isa<BranchInst>(BB->getTerminator());5102      }))5103    return false;5104 5105  return true;5106}5107 5108/// For Apple CPUs, we want to runtime-unroll loops to make better use if the5109/// OOO engine's wide instruction window and various predictors.5110static void5111getAppleRuntimeUnrollPreferences(Loop *L, ScalarEvolution &SE,5112                                 TargetTransformInfo::UnrollingPreferences &UP,5113                                 const AArch64TTIImpl &TTI) {5114  // Limit loops with structure that is highly likely to benefit from runtime5115  // unrolling; that is we exclude outer loops and loops with many blocks (i.e.5116  // likely with complex control flow). Note that the heuristics here may be5117  // overly conservative and we err on the side of avoiding runtime unrolling5118  // rather than unroll excessively. They are all subject to further refinement.5119  if (!L->isInnermost() || L->getNumBlocks() > 8)5120    return;5121 5122  // Loops with multiple exits are handled by common code.5123  if (!L->getExitBlock())5124    return;5125 5126  // Check if the loop contains any reductions that could be parallelized when5127  // unrolling. If so, enable partial unrolling, if the trip count is know to be5128  // a multiple of 2.5129  bool HasParellelizableReductions =5130      L->getNumBlocks() == 1 &&5131      any_of(L->getHeader()->phis(),5132             [&SE, L](PHINode &Phi) {5133               return canParallelizeReductionWhenUnrolling(Phi, L, &SE);5134             }) &&5135      isLoopSizeWithinBudget(L, TTI, 12, nullptr);5136  if (HasParellelizableReductions &&5137      SE.getSmallConstantTripMultiple(L, L->getExitingBlock()) % 2 == 0) {5138    UP.Partial = true;5139    UP.MaxCount = 4;5140    UP.AddAdditionalAccumulators = true;5141  }5142 5143  const SCEV *BTC = SE.getSymbolicMaxBackedgeTakenCount(L);5144  if (isa<SCEVConstant>(BTC) || isa<SCEVCouldNotCompute>(BTC) ||5145      (SE.getSmallConstantMaxTripCount(L) > 0 &&5146       SE.getSmallConstantMaxTripCount(L) <= 32))5147    return;5148 5149  if (findStringMetadataForLoop(L, "llvm.loop.isvectorized"))5150    return;5151 5152  if (SE.getSymbolicMaxBackedgeTakenCount(L) != SE.getBackedgeTakenCount(L))5153    return;5154 5155  // Limit to loops with trip counts that are cheap to expand.5156  UP.SCEVExpansionBudget = 1;5157 5158  if (HasParellelizableReductions) {5159    UP.Runtime = true;5160    UP.DefaultUnrollRuntimeCount = 4;5161    UP.AddAdditionalAccumulators = true;5162  }5163 5164  // Try to unroll small loops, of few-blocks with low budget, if they have5165  // load/store dependencies, to expose more parallel memory access streams,5166  // or if they do little work inside a block (i.e. load -> X -> store pattern).5167  BasicBlock *Header = L->getHeader();5168  BasicBlock *Latch = L->getLoopLatch();5169  if (Header == Latch) {5170    // Estimate the size of the loop.5171    unsigned Size;5172    unsigned Width = 10;5173    if (!isLoopSizeWithinBudget(L, TTI, Width, &Size))5174      return;5175 5176    // Try to find an unroll count that maximizes the use of the instruction5177    // window, i.e. trying to fetch as many instructions per cycle as possible.5178    unsigned MaxInstsPerLine = 16;5179    unsigned UC = 1;5180    unsigned BestUC = 1;5181    unsigned SizeWithBestUC = BestUC * Size;5182    while (UC <= 8) {5183      unsigned SizeWithUC = UC * Size;5184      if (SizeWithUC > 48)5185        break;5186      if ((SizeWithUC % MaxInstsPerLine) == 0 ||5187          (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {5188        BestUC = UC;5189        SizeWithBestUC = BestUC * Size;5190      }5191      UC++;5192    }5193 5194    if (BestUC == 1)5195      return;5196 5197    SmallPtrSet<Value *, 8> LoadedValuesPlus;5198    SmallVector<StoreInst *> Stores;5199    for (auto *BB : L->blocks()) {5200      for (auto &I : *BB) {5201        Value *Ptr = getLoadStorePointerOperand(&I);5202        if (!Ptr)5203          continue;5204        const SCEV *PtrSCEV = SE.getSCEV(Ptr);5205        if (SE.isLoopInvariant(PtrSCEV, L))5206          continue;5207        if (isa<LoadInst>(&I)) {5208          LoadedValuesPlus.insert(&I);5209          // Include in-loop 1st users of loaded values.5210          for (auto *U : I.users())5211            if (L->contains(cast<Instruction>(U)))5212              LoadedValuesPlus.insert(U);5213        } else5214          Stores.push_back(cast<StoreInst>(&I));5215      }5216    }5217 5218    if (none_of(Stores, [&LoadedValuesPlus](StoreInst *SI) {5219          return LoadedValuesPlus.contains(SI->getOperand(0));5220        }))5221      return;5222 5223    UP.Runtime = true;5224    UP.DefaultUnrollRuntimeCount = BestUC;5225    return;5226  }5227 5228  // Try to runtime-unroll loops with early-continues depending on loop-varying5229  // loads; this helps with branch-prediction for the early-continues.5230  auto *Term = dyn_cast<BranchInst>(Header->getTerminator());5231  SmallVector<BasicBlock *> Preds(predecessors(Latch));5232  if (!Term || !Term->isConditional() || Preds.size() == 1 ||5233      !llvm::is_contained(Preds, Header) ||5234      none_of(Preds, [L](BasicBlock *Pred) { return L->contains(Pred); }))5235    return;5236 5237  std::function<bool(Instruction *, unsigned)> DependsOnLoopLoad =5238      [&](Instruction *I, unsigned Depth) -> bool {5239    if (isa<PHINode>(I) || L->isLoopInvariant(I) || Depth > 8)5240      return false;5241 5242    if (isa<LoadInst>(I))5243      return true;5244 5245    return any_of(I->operands(), [&](Value *V) {5246      auto *I = dyn_cast<Instruction>(V);5247      return I && DependsOnLoopLoad(I, Depth + 1);5248    });5249  };5250  CmpPredicate Pred;5251  Instruction *I;5252  if (match(Term, m_Br(m_ICmp(Pred, m_Instruction(I), m_Value()), m_Value(),5253                       m_Value())) &&5254      DependsOnLoopLoad(I, 0)) {5255    UP.Runtime = true;5256  }5257}5258 5259void AArch64TTIImpl::getUnrollingPreferences(5260    Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP,5261    OptimizationRemarkEmitter *ORE) const {5262  // Enable partial unrolling and runtime unrolling.5263  BaseT::getUnrollingPreferences(L, SE, UP, ORE);5264 5265  UP.UpperBound = true;5266 5267  // For inner loop, it is more likely to be a hot one, and the runtime check5268  // can be promoted out from LICM pass, so the overhead is less, let's try5269  // a larger threshold to unroll more loops.5270  if (L->getLoopDepth() > 1)5271    UP.PartialThreshold *= 2;5272 5273  // Disable partial & runtime unrolling on -Os.5274  UP.PartialOptSizeThreshold = 0;5275 5276  // Scan the loop: don't unroll loops with calls as this could prevent5277  // inlining. Don't unroll auto-vectorized loops either, though do allow5278  // unrolling of the scalar remainder.5279  bool IsVectorized = getBooleanLoopAttribute(L, "llvm.loop.isvectorized");5280  InstructionCost Cost = 0;5281  for (auto *BB : L->getBlocks()) {5282    for (auto &I : *BB) {5283      // Both auto-vectorized loops and the scalar remainder have the5284      // isvectorized attribute, so differentiate between them by the presence5285      // of vector instructions.5286      if (IsVectorized && I.getType()->isVectorTy())5287        return;5288      if (isa<CallBase>(I)) {5289        if (isa<CallInst>(I) || isa<InvokeInst>(I))5290          if (const Function *F = cast<CallBase>(I).getCalledFunction())5291            if (!isLoweredToCall(F))5292              continue;5293        return;5294      }5295 5296      SmallVector<const Value *, 4> Operands(I.operand_values());5297      Cost += getInstructionCost(&I, Operands,5298                                 TargetTransformInfo::TCK_SizeAndLatency);5299    }5300  }5301 5302  // Apply subtarget-specific unrolling preferences.5303  switch (ST->getProcFamily()) {5304  case AArch64Subtarget::AppleA14:5305  case AArch64Subtarget::AppleA15:5306  case AArch64Subtarget::AppleA16:5307  case AArch64Subtarget::AppleM4:5308    getAppleRuntimeUnrollPreferences(L, SE, UP, *this);5309    break;5310  case AArch64Subtarget::Falkor:5311    if (EnableFalkorHWPFUnrollFix)5312      getFalkorUnrollingPreferences(L, SE, UP);5313    break;5314  default:5315    break;5316  }5317 5318  // If this is a small, multi-exit loop similar to something like std::find,5319  // then there is typically a performance improvement achieved by unrolling.5320  if (!L->getExitBlock() && shouldUnrollMultiExitLoop(L, SE, *this)) {5321    UP.RuntimeUnrollMultiExit = true;5322    UP.Runtime = true;5323    // Limit unroll count.5324    UP.DefaultUnrollRuntimeCount = 4;5325    // Allow slightly more costly trip-count expansion to catch search loops5326    // with pointer inductions.5327    UP.SCEVExpansionBudget = 5;5328    return;5329  }5330 5331  // Enable runtime unrolling for in-order models5332  // If mcpu is omitted, getProcFamily() returns AArch64Subtarget::Others, so by5333  // checking for that case, we can ensure that the default behaviour is5334  // unchanged5335  if (ST->getProcFamily() != AArch64Subtarget::Generic &&5336      !ST->getSchedModel().isOutOfOrder()) {5337    UP.Runtime = true;5338    UP.Partial = true;5339    UP.UnrollRemainder = true;5340    UP.DefaultUnrollRuntimeCount = 4;5341 5342    UP.UnrollAndJam = true;5343    UP.UnrollAndJamInnerLoopThreshold = 60;5344  }5345 5346  // Force unrolling small loops can be very useful because of the branch5347  // taken cost of the backedge.5348  if (Cost < Aarch64ForceUnrollThreshold)5349    UP.Force = true;5350}5351 5352void AArch64TTIImpl::getPeelingPreferences(Loop *L, ScalarEvolution &SE,5353                                           TTI::PeelingPreferences &PP) const {5354  BaseT::getPeelingPreferences(L, SE, PP);5355}5356 5357Value *AArch64TTIImpl::getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,5358                                                         Type *ExpectedType,5359                                                         bool CanCreate) const {5360  switch (Inst->getIntrinsicID()) {5361  default:5362    return nullptr;5363  case Intrinsic::aarch64_neon_st2:5364  case Intrinsic::aarch64_neon_st3:5365  case Intrinsic::aarch64_neon_st4: {5366    // Create a struct type5367    StructType *ST = dyn_cast<StructType>(ExpectedType);5368    if (!CanCreate || !ST)5369      return nullptr;5370    unsigned NumElts = Inst->arg_size() - 1;5371    if (ST->getNumElements() != NumElts)5372      return nullptr;5373    for (unsigned i = 0, e = NumElts; i != e; ++i) {5374      if (Inst->getArgOperand(i)->getType() != ST->getElementType(i))5375        return nullptr;5376    }5377    Value *Res = PoisonValue::get(ExpectedType);5378    IRBuilder<> Builder(Inst);5379    for (unsigned i = 0, e = NumElts; i != e; ++i) {5380      Value *L = Inst->getArgOperand(i);5381      Res = Builder.CreateInsertValue(Res, L, i);5382    }5383    return Res;5384  }5385  case Intrinsic::aarch64_neon_ld2:5386  case Intrinsic::aarch64_neon_ld3:5387  case Intrinsic::aarch64_neon_ld4:5388    if (Inst->getType() == ExpectedType)5389      return Inst;5390    return nullptr;5391  }5392}5393 5394bool AArch64TTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,5395                                        MemIntrinsicInfo &Info) const {5396  switch (Inst->getIntrinsicID()) {5397  default:5398    break;5399  case Intrinsic::aarch64_neon_ld2:5400  case Intrinsic::aarch64_neon_ld3:5401  case Intrinsic::aarch64_neon_ld4:5402    Info.ReadMem = true;5403    Info.WriteMem = false;5404    Info.PtrVal = Inst->getArgOperand(0);5405    break;5406  case Intrinsic::aarch64_neon_st2:5407  case Intrinsic::aarch64_neon_st3:5408  case Intrinsic::aarch64_neon_st4:5409    Info.ReadMem = false;5410    Info.WriteMem = true;5411    Info.PtrVal = Inst->getArgOperand(Inst->arg_size() - 1);5412    break;5413  }5414 5415  switch (Inst->getIntrinsicID()) {5416  default:5417    return false;5418  case Intrinsic::aarch64_neon_ld2:5419  case Intrinsic::aarch64_neon_st2:5420    Info.MatchingId = VECTOR_LDST_TWO_ELEMENTS;5421    break;5422  case Intrinsic::aarch64_neon_ld3:5423  case Intrinsic::aarch64_neon_st3:5424    Info.MatchingId = VECTOR_LDST_THREE_ELEMENTS;5425    break;5426  case Intrinsic::aarch64_neon_ld4:5427  case Intrinsic::aarch64_neon_st4:5428    Info.MatchingId = VECTOR_LDST_FOUR_ELEMENTS;5429    break;5430  }5431  return true;5432}5433 5434/// See if \p I should be considered for address type promotion. We check if \p5435/// I is a sext with right type and used in memory accesses. If it used in a5436/// "complex" getelementptr, we allow it to be promoted without finding other5437/// sext instructions that sign extended the same initial value. A getelementptr5438/// is considered as "complex" if it has more than 2 operands.5439bool AArch64TTIImpl::shouldConsiderAddressTypePromotion(5440    const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const {5441  bool Considerable = false;5442  AllowPromotionWithoutCommonHeader = false;5443  if (!isa<SExtInst>(&I))5444    return false;5445  Type *ConsideredSExtType =5446      Type::getInt64Ty(I.getParent()->getParent()->getContext());5447  if (I.getType() != ConsideredSExtType)5448    return false;5449  // See if the sext is the one with the right type and used in at least one5450  // GetElementPtrInst.5451  for (const User *U : I.users()) {5452    if (const GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(U)) {5453      Considerable = true;5454      // A getelementptr is considered as "complex" if it has more than 25455      // operands. We will promote a SExt used in such complex GEP as we5456      // expect some computation to be merged if they are done on 64 bits.5457      if (GEPInst->getNumOperands() > 2) {5458        AllowPromotionWithoutCommonHeader = true;5459        break;5460      }5461    }5462  }5463  return Considerable;5464}5465 5466bool AArch64TTIImpl::isLegalToVectorizeReduction(5467    const RecurrenceDescriptor &RdxDesc, ElementCount VF) const {5468  if (!VF.isScalable())5469    return true;5470 5471  Type *Ty = RdxDesc.getRecurrenceType();5472  if (Ty->isBFloatTy() || !isElementTypeLegalForScalableVector(Ty))5473    return false;5474 5475  switch (RdxDesc.getRecurrenceKind()) {5476  case RecurKind::Sub:5477  case RecurKind::AddChainWithSubs:5478  case RecurKind::Add:5479  case RecurKind::FAdd:5480  case RecurKind::And:5481  case RecurKind::Or:5482  case RecurKind::Xor:5483  case RecurKind::SMin:5484  case RecurKind::SMax:5485  case RecurKind::UMin:5486  case RecurKind::UMax:5487  case RecurKind::FMin:5488  case RecurKind::FMax:5489  case RecurKind::FMulAdd:5490  case RecurKind::AnyOf:5491    return true;5492  default:5493    return false;5494  }5495}5496 5497InstructionCost5498AArch64TTIImpl::getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty,5499                                       FastMathFlags FMF,5500                                       TTI::TargetCostKind CostKind) const {5501  // The code-generator is currently not able to handle scalable vectors5502  // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting5503  // it. This change will be removed when code-generation for these types is5504  // sufficiently reliable.5505  if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))5506    if (VTy->getElementCount() == ElementCount::getScalable(1))5507      return InstructionCost::getInvalid();5508 5509  std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);5510 5511  if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())5512    return BaseT::getMinMaxReductionCost(IID, Ty, FMF, CostKind);5513 5514  InstructionCost LegalizationCost = 0;5515  if (LT.first > 1) {5516    Type *LegalVTy = EVT(LT.second).getTypeForEVT(Ty->getContext());5517    IntrinsicCostAttributes Attrs(IID, LegalVTy, {LegalVTy, LegalVTy}, FMF);5518    LegalizationCost = getIntrinsicInstrCost(Attrs, CostKind) * (LT.first - 1);5519  }5520 5521  return LegalizationCost + /*Cost of horizontal reduction*/ 2;5522}5523 5524InstructionCost AArch64TTIImpl::getArithmeticReductionCostSVE(5525    unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const {5526  std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);5527  InstructionCost LegalizationCost = 0;5528  if (LT.first > 1) {5529    Type *LegalVTy = EVT(LT.second).getTypeForEVT(ValTy->getContext());5530    LegalizationCost = getArithmeticInstrCost(Opcode, LegalVTy, CostKind);5531    LegalizationCost *= LT.first - 1;5532  }5533 5534  int ISD = TLI->InstructionOpcodeToISD(Opcode);5535  assert(ISD && "Invalid opcode");5536  // Add the final reduction cost for the legal horizontal reduction5537  switch (ISD) {5538  case ISD::ADD:5539  case ISD::AND:5540  case ISD::OR:5541  case ISD::XOR:5542  case ISD::FADD:5543    return LegalizationCost + 2;5544  default:5545    return InstructionCost::getInvalid();5546  }5547}5548 5549InstructionCost5550AArch64TTIImpl::getArithmeticReductionCost(unsigned Opcode, VectorType *ValTy,5551                                           std::optional<FastMathFlags> FMF,5552                                           TTI::TargetCostKind CostKind) const {5553  // The code-generator is currently not able to handle scalable vectors5554  // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting5555  // it. This change will be removed when code-generation for these types is5556  // sufficiently reliable.5557  if (auto *VTy = dyn_cast<ScalableVectorType>(ValTy))5558    if (VTy->getElementCount() == ElementCount::getScalable(1))5559      return InstructionCost::getInvalid();5560 5561  if (TTI::requiresOrderedReduction(FMF)) {5562    if (auto *FixedVTy = dyn_cast<FixedVectorType>(ValTy)) {5563      InstructionCost BaseCost =5564          BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);5565      // Add on extra cost to reflect the extra overhead on some CPUs. We still5566      // end up vectorizing for more computationally intensive loops.5567      return BaseCost + FixedVTy->getNumElements();5568    }5569 5570    if (Opcode != Instruction::FAdd)5571      return InstructionCost::getInvalid();5572 5573    auto *VTy = cast<ScalableVectorType>(ValTy);5574    InstructionCost Cost =5575        getArithmeticInstrCost(Opcode, VTy->getScalarType(), CostKind);5576    Cost *= getMaxNumElements(VTy->getElementCount());5577    return Cost;5578  }5579 5580  if (isa<ScalableVectorType>(ValTy))5581    return getArithmeticReductionCostSVE(Opcode, ValTy, CostKind);5582 5583  std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);5584  MVT MTy = LT.second;5585  int ISD = TLI->InstructionOpcodeToISD(Opcode);5586  assert(ISD && "Invalid opcode");5587 5588  // Horizontal adds can use the 'addv' instruction. We model the cost of these5589  // instructions as twice a normal vector add, plus 1 for each legalization5590  // step (LT.first). This is the only arithmetic vector reduction operation for5591  // which we have an instruction.5592  // OR, XOR and AND costs should match the codegen from:5593  // OR: llvm/test/CodeGen/AArch64/reduce-or.ll5594  // XOR: llvm/test/CodeGen/AArch64/reduce-xor.ll5595  // AND: llvm/test/CodeGen/AArch64/reduce-and.ll5596  static const CostTblEntry CostTblNoPairwise[]{5597      {ISD::ADD, MVT::v8i8, 2},5598      {ISD::ADD, MVT::v16i8, 2},5599      {ISD::ADD, MVT::v4i16, 2},5600      {ISD::ADD, MVT::v8i16, 2},5601      {ISD::ADD, MVT::v2i32, 2},5602      {ISD::ADD, MVT::v4i32, 2},5603      {ISD::ADD, MVT::v2i64, 2},5604      {ISD::OR, MVT::v8i8, 5},  // fmov + orr_lsr + orr_lsr + lsr + orr5605      {ISD::OR, MVT::v16i8, 7}, // ext + orr + same as v8i85606      {ISD::OR, MVT::v4i16, 4}, // fmov + orr_lsr + lsr + orr5607      {ISD::OR, MVT::v8i16, 6}, // ext + orr + same as v4i165608      {ISD::OR, MVT::v2i32, 3}, // fmov + lsr + orr5609      {ISD::OR, MVT::v4i32, 5}, // ext + orr + same as v2i325610      {ISD::OR, MVT::v2i64, 3}, // ext + orr + fmov5611      {ISD::XOR, MVT::v8i8, 5}, // Same as above for or...5612      {ISD::XOR, MVT::v16i8, 7},5613      {ISD::XOR, MVT::v4i16, 4},5614      {ISD::XOR, MVT::v8i16, 6},5615      {ISD::XOR, MVT::v2i32, 3},5616      {ISD::XOR, MVT::v4i32, 5},5617      {ISD::XOR, MVT::v2i64, 3},5618      {ISD::AND, MVT::v8i8, 5}, // Same as above for or...5619      {ISD::AND, MVT::v16i8, 7},5620      {ISD::AND, MVT::v4i16, 4},5621      {ISD::AND, MVT::v8i16, 6},5622      {ISD::AND, MVT::v2i32, 3},5623      {ISD::AND, MVT::v4i32, 5},5624      {ISD::AND, MVT::v2i64, 3},5625  };5626  switch (ISD) {5627  default:5628    break;5629  case ISD::FADD:5630    if (Type *EltTy = ValTy->getScalarType();5631        // FIXME: For half types without fullfp16 support, this could extend and5632        // use a fp32 faddp reduction but current codegen unrolls.5633        MTy.isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||5634                           (EltTy->isHalfTy() && ST->hasFullFP16()))) {5635      const unsigned NElts = MTy.getVectorNumElements();5636      if (ValTy->getElementCount().getFixedValue() >= 2 && NElts >= 2 &&5637          isPowerOf2_32(NElts))5638        // Reduction corresponding to series of fadd instructions is lowered to5639        // series of faddp instructions. faddp has latency/throughput that5640        // matches fadd instruction and hence, every faddp instruction can be5641        // considered to have a relative cost = 1 with5642        // CostKind = TCK_RecipThroughput.5643        // An faddp will pairwise add vector elements, so the size of input5644        // vector reduces by half every time, requiring5645        // #(faddp instructions) = log2_32(NElts).5646        return (LT.first - 1) + /*No of faddp instructions*/ Log2_32(NElts);5647    }5648    break;5649  case ISD::ADD:5650    if (const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy))5651      return (LT.first - 1) + Entry->Cost;5652    break;5653  case ISD::XOR:5654  case ISD::AND:5655  case ISD::OR:5656    const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy);5657    if (!Entry)5658      break;5659    auto *ValVTy = cast<FixedVectorType>(ValTy);5660    if (MTy.getVectorNumElements() <= ValVTy->getNumElements() &&5661        isPowerOf2_32(ValVTy->getNumElements())) {5662      InstructionCost ExtraCost = 0;5663      if (LT.first != 1) {5664        // Type needs to be split, so there is an extra cost of LT.first - 15665        // arithmetic ops.5666        auto *Ty = FixedVectorType::get(ValTy->getElementType(),5667                                        MTy.getVectorNumElements());5668        ExtraCost = getArithmeticInstrCost(Opcode, Ty, CostKind);5669        ExtraCost *= LT.first - 1;5670      }5671      // All and/or/xor of i1 will be lowered with maxv/minv/addv + fmov5672      auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;5673      return Cost + ExtraCost;5674    }5675    break;5676  }5677  return BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);5678}5679 5680InstructionCost AArch64TTIImpl::getExtendedReductionCost(5681    unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *VecTy,5682    std::optional<FastMathFlags> FMF, TTI::TargetCostKind CostKind) const {5683  EVT VecVT = TLI->getValueType(DL, VecTy);5684  EVT ResVT = TLI->getValueType(DL, ResTy);5685 5686  if (Opcode == Instruction::Add && VecVT.isSimple() && ResVT.isSimple() &&5687      VecVT.getSizeInBits() >= 64) {5688    std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(VecTy);5689 5690    // The legal cases are:5691    //   UADDLV 8/16/32->325692    //   UADDLP 32->645693    unsigned RevVTSize = ResVT.getSizeInBits();5694    if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&5695         RevVTSize <= 32) ||5696        ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&5697         RevVTSize <= 32) ||5698        ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&5699         RevVTSize <= 64))5700      return (LT.first - 1) * 2 + 2;5701  }5702 5703  return BaseT::getExtendedReductionCost(Opcode, IsUnsigned, ResTy, VecTy, FMF,5704                                         CostKind);5705}5706 5707InstructionCost5708AArch64TTIImpl::getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode,5709                                       Type *ResTy, VectorType *VecTy,5710                                       TTI::TargetCostKind CostKind) const {5711  EVT VecVT = TLI->getValueType(DL, VecTy);5712  EVT ResVT = TLI->getValueType(DL, ResTy);5713 5714  if (ST->hasDotProd() && VecVT.isSimple() && ResVT.isSimple() &&5715      RedOpcode == Instruction::Add) {5716    std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(VecTy);5717 5718    // The legal cases with dotprod are5719    //   UDOT 8->325720    // Which requires an additional uaddv to sum the i32 values.5721    if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&5722         ResVT == MVT::i32)5723      return LT.first + 2;5724  }5725 5726  return BaseT::getMulAccReductionCost(IsUnsigned, RedOpcode, ResTy, VecTy,5727                                       CostKind);5728}5729 5730InstructionCost5731AArch64TTIImpl::getSpliceCost(VectorType *Tp, int Index,5732                              TTI::TargetCostKind CostKind) const {5733  static const CostTblEntry ShuffleTbl[] = {5734      { TTI::SK_Splice, MVT::nxv16i8,  1 },5735      { TTI::SK_Splice, MVT::nxv8i16,  1 },5736      { TTI::SK_Splice, MVT::nxv4i32,  1 },5737      { TTI::SK_Splice, MVT::nxv2i64,  1 },5738      { TTI::SK_Splice, MVT::nxv2f16,  1 },5739      { TTI::SK_Splice, MVT::nxv4f16,  1 },5740      { TTI::SK_Splice, MVT::nxv8f16,  1 },5741      { TTI::SK_Splice, MVT::nxv2bf16, 1 },5742      { TTI::SK_Splice, MVT::nxv4bf16, 1 },5743      { TTI::SK_Splice, MVT::nxv8bf16, 1 },5744      { TTI::SK_Splice, MVT::nxv2f32,  1 },5745      { TTI::SK_Splice, MVT::nxv4f32,  1 },5746      { TTI::SK_Splice, MVT::nxv2f64,  1 },5747  };5748 5749  // The code-generator is currently not able to handle scalable vectors5750  // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting5751  // it. This change will be removed when code-generation for these types is5752  // sufficiently reliable.5753  if (Tp->getElementCount() == ElementCount::getScalable(1))5754    return InstructionCost::getInvalid();5755 5756  std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Tp);5757  Type *LegalVTy = EVT(LT.second).getTypeForEVT(Tp->getContext());5758  EVT PromotedVT = LT.second.getScalarType() == MVT::i15759                       ? TLI->getPromotedVTForPredicate(EVT(LT.second))5760                       : LT.second;5761  Type *PromotedVTy = EVT(PromotedVT).getTypeForEVT(Tp->getContext());5762  InstructionCost LegalizationCost = 0;5763  if (Index < 0) {5764    LegalizationCost =5765        getCmpSelInstrCost(Instruction::ICmp, PromotedVTy, PromotedVTy,5766                           CmpInst::BAD_ICMP_PREDICATE, CostKind) +5767        getCmpSelInstrCost(Instruction::Select, PromotedVTy, LegalVTy,5768                           CmpInst::BAD_ICMP_PREDICATE, CostKind);5769  }5770 5771  // Predicated splice are promoted when lowering. See AArch64ISelLowering.cpp5772  // Cost performed on a promoted type.5773  if (LT.second.getScalarType() == MVT::i1) {5774    LegalizationCost +=5775        getCastInstrCost(Instruction::ZExt, PromotedVTy, LegalVTy,5776                         TTI::CastContextHint::None, CostKind) +5777        getCastInstrCost(Instruction::Trunc, LegalVTy, PromotedVTy,5778                         TTI::CastContextHint::None, CostKind);5779  }5780  const auto *Entry =5781      CostTableLookup(ShuffleTbl, TTI::SK_Splice, PromotedVT.getSimpleVT());5782  assert(Entry && "Illegal Type for Splice");5783  LegalizationCost += Entry->Cost;5784  return LegalizationCost * LT.first;5785}5786 5787InstructionCost AArch64TTIImpl::getPartialReductionCost(5788    unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,5789    ElementCount VF, TTI::PartialReductionExtendKind OpAExtend,5790    TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,5791    TTI::TargetCostKind CostKind) const {5792  InstructionCost Invalid = InstructionCost::getInvalid();5793 5794  if (CostKind != TTI::TCK_RecipThroughput)5795    return Invalid;5796 5797  if (VF.isFixed() && !ST->isSVEorStreamingSVEAvailable() &&5798      (!ST->isNeonAvailable() || !ST->hasDotProd()))5799    return Invalid;5800 5801  if ((Opcode != Instruction::Add && Opcode != Instruction::Sub) ||5802      OpAExtend == TTI::PR_None)5803    return Invalid;5804 5805  assert((BinOp || (OpBExtend == TTI::PR_None && !InputTypeB)) &&5806         (!BinOp || (OpBExtend != TTI::PR_None && InputTypeB)) &&5807         "Unexpected values for OpBExtend or InputTypeB");5808 5809  // We only support multiply binary operations for now, and for muls we5810  // require the types being extended to be the same.5811  if (BinOp && (*BinOp != Instruction::Mul || InputTypeA != InputTypeB))5812    return Invalid;5813 5814  bool IsUSDot = OpBExtend != TTI::PR_None && OpAExtend != OpBExtend;5815  if (IsUSDot && !ST->hasMatMulInt8())5816    return Invalid;5817 5818  unsigned Ratio =5819      AccumType->getScalarSizeInBits() / InputTypeA->getScalarSizeInBits();5820  if (VF.getKnownMinValue() <= Ratio)5821    return Invalid;5822 5823  VectorType *InputVectorType = VectorType::get(InputTypeA, VF);5824  VectorType *AccumVectorType =5825      VectorType::get(AccumType, VF.divideCoefficientBy(Ratio));5826  // We don't yet support all kinds of legalization.5827  auto TC = TLI->getTypeConversion(AccumVectorType->getContext(),5828                                   EVT::getEVT(AccumVectorType));5829  switch (TC.first) {5830  default:5831    return Invalid;5832  case TargetLowering::TypeLegal:5833  case TargetLowering::TypePromoteInteger:5834  case TargetLowering::TypeSplitVector:5835    // The legalised type (e.g. after splitting) must be legal too.5836    if (TLI->getTypeAction(AccumVectorType->getContext(), TC.second) !=5837        TargetLowering::TypeLegal)5838      return Invalid;5839    break;5840  }5841 5842  std::pair<InstructionCost, MVT> AccumLT =5843      getTypeLegalizationCost(AccumVectorType);5844  std::pair<InstructionCost, MVT> InputLT =5845      getTypeLegalizationCost(InputVectorType);5846 5847  InstructionCost Cost = InputLT.first * TTI::TCC_Basic;5848 5849  // Prefer using full types by costing half-full input types as more expensive.5850  if (TypeSize::isKnownLT(InputVectorType->getPrimitiveSizeInBits(),5851                          TypeSize::getScalable(128)))5852    // FIXME: This can be removed after the cost of the extends are folded into5853    // the dot-product expression in VPlan, after landing:5854    //  https://github.com/llvm/llvm-project/pull/1473025855    Cost *= 2;5856 5857  if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {5858    // i16 -> i64 is natively supported for udot/sdot5859    if (AccumLT.second.getScalarType() == MVT::i64 &&5860        InputLT.second.getScalarType() == MVT::i16)5861      return Cost;5862    // i8 -> i64 is supported with an extra level of extends5863    if (AccumLT.second.getScalarType() == MVT::i64 &&5864        InputLT.second.getScalarType() == MVT::i8)5865      // FIXME: This cost should probably be a little higher, e.g. Cost + 25866      // because it requires two extra extends on the inputs. But if we'd change5867      // that now, a regular reduction would be cheaper because the costs of5868      // the extends in the IR are still counted. This can be fixed5869      // after https://github.com/llvm/llvm-project/pull/147302 has landed.5870      return Cost;5871  }5872 5873  // i8 -> i32 is natively supported for udot/sdot/usdot, both for NEON and SVE.5874  if (ST->isSVEorStreamingSVEAvailable() ||5875      (AccumLT.second.isFixedLengthVector() && ST->isNeonAvailable() &&5876       ST->hasDotProd())) {5877    if (AccumLT.second.getScalarType() == MVT::i32 &&5878        InputLT.second.getScalarType() == MVT::i8)5879      return Cost;5880  }5881 5882  // Add additional cost for the extends that would need to be inserted.5883  return Cost + 2;5884}5885 5886InstructionCost5887AArch64TTIImpl::getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy,5888                               VectorType *SrcTy, ArrayRef<int> Mask,5889                               TTI::TargetCostKind CostKind, int Index,5890                               VectorType *SubTp, ArrayRef<const Value *> Args,5891                               const Instruction *CxtI) const {5892  assert((Mask.empty() || DstTy->isScalableTy() ||5893          Mask.size() == DstTy->getElementCount().getKnownMinValue()) &&5894         "Expected the Mask to match the return size if given");5895  assert(SrcTy->getScalarType() == DstTy->getScalarType() &&5896         "Expected the same scalar types");5897  std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(SrcTy);5898 5899  // If we have a Mask, and the LT is being legalized somehow, split the Mask5900  // into smaller vectors and sum the cost of each shuffle.5901  if (!Mask.empty() && isa<FixedVectorType>(SrcTy) && LT.second.isVector() &&5902      LT.second.getScalarSizeInBits() * Mask.size() > 128 &&5903      SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&5904      Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {5905    // Check for LD3/LD4 instructions, which are represented in llvm IR as5906    // deinterleaving-shuffle(load). The shuffle cost could potentially be free,5907    // but we model it with a cost of LT.first so that LD3/LD4 have a higher5908    // cost than just the load.5909    if (Args.size() >= 1 && isa<LoadInst>(Args[0]) &&5910        (ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, 3) ||5911         ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, 4)))5912      return std::max<InstructionCost>(1, LT.first / 4);5913 5914    // Check for ST3/ST4 instructions, which are represented in llvm IR as5915    // store(interleaving-shuffle). The shuffle cost could potentially be free,5916    // but we model it with a cost of LT.first so that ST3/ST4 have a higher5917    // cost than just the store.5918    if (CxtI && CxtI->hasOneUse() && isa<StoreInst>(*CxtI->user_begin()) &&5919        (ShuffleVectorInst::isInterleaveMask(5920             Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||5921         ShuffleVectorInst::isInterleaveMask(5922             Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))5923      return LT.first;5924 5925    unsigned TpNumElts = Mask.size();5926    unsigned LTNumElts = LT.second.getVectorNumElements();5927    unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;5928    VectorType *NTp = VectorType::get(SrcTy->getScalarType(),5929                                      LT.second.getVectorElementCount());5930    InstructionCost Cost;5931    std::map<std::tuple<unsigned, unsigned, SmallVector<int>>, InstructionCost>5932        PreviousCosts;5933    for (unsigned N = 0; N < NumVecs; N++) {5934      SmallVector<int> NMask;5935      // Split the existing mask into chunks of size LTNumElts. Track the source5936      // sub-vectors to ensure the result has at most 2 inputs.5937      unsigned Source1 = -1U, Source2 = -1U;5938      unsigned NumSources = 0;5939      for (unsigned E = 0; E < LTNumElts; E++) {5940        int MaskElt = (N * LTNumElts + E < TpNumElts) ? Mask[N * LTNumElts + E]5941                                                      : PoisonMaskElem;5942        if (MaskElt < 0) {5943          NMask.push_back(PoisonMaskElem);5944          continue;5945        }5946 5947        // Calculate which source from the input this comes from and whether it5948        // is new to us.5949        unsigned Source = MaskElt / LTNumElts;5950        if (NumSources == 0) {5951          Source1 = Source;5952          NumSources = 1;5953        } else if (NumSources == 1 && Source != Source1) {5954          Source2 = Source;5955          NumSources = 2;5956        } else if (NumSources >= 2 && Source != Source1 && Source != Source2) {5957          NumSources++;5958        }5959 5960        // Add to the new mask. For the NumSources>2 case these are not correct,5961        // but are only used for the modular lane number.5962        if (Source == Source1)5963          NMask.push_back(MaskElt % LTNumElts);5964        else if (Source == Source2)5965          NMask.push_back(MaskElt % LTNumElts + LTNumElts);5966        else5967          NMask.push_back(MaskElt % LTNumElts);5968      }5969      // Check if we have already generated this sub-shuffle, which means we5970      // will have already generated the output. For example a <16 x i32> splat5971      // will be the same sub-splat 4 times, which only needs to be generated5972      // once and reused.5973      auto Result =5974          PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});5975      // Check if it was already in the map (already costed).5976      if (!Result.second)5977        continue;5978      // If the sub-mask has at most 2 input sub-vectors then re-cost it using5979      // getShuffleCost. If not then cost it using the worst case as the number5980      // of element moves into a new vector.5981      InstructionCost NCost =5982          NumSources <= 25983              ? getShuffleCost(NumSources <= 1 ? TTI::SK_PermuteSingleSrc5984                                               : TTI::SK_PermuteTwoSrc,5985                               NTp, NTp, NMask, CostKind, 0, nullptr, Args,5986                               CxtI)5987              : LTNumElts;5988      Result.first->second = NCost;5989      Cost += NCost;5990    }5991    return Cost;5992  }5993 5994  Kind = improveShuffleKindFromMask(Kind, Mask, SrcTy, Index, SubTp);5995  bool IsExtractSubvector = Kind == TTI::SK_ExtractSubvector;5996  // A subvector extract can be implemented with a NEON/SVE ext (or trivial5997  // extract, if from lane 0) for 128-bit NEON vectors or legal SVE vectors.5998  // This currently only handles low or high extracts to prevent SLP vectorizer5999  // regressions.6000  // Note that SVE's ext instruction is destructive, but it can be fused with6001  // a movprfx to act like a constructive instruction.6002  if (IsExtractSubvector && LT.second.isFixedLengthVector()) {6003    if (LT.second.getFixedSizeInBits() >= 128 &&6004        cast<FixedVectorType>(SubTp)->getNumElements() ==6005            LT.second.getVectorNumElements() / 2) {6006      if (Index == 0)6007        return 0;6008      if (Index == (int)LT.second.getVectorNumElements() / 2)6009        return 1;6010    }6011    Kind = TTI::SK_PermuteSingleSrc;6012  }6013  // FIXME: This was added to keep the costs equal when adding DstTys. Update6014  // the code to handle length-changing shuffles.6015  if (Kind == TTI::SK_InsertSubvector) {6016    LT = getTypeLegalizationCost(DstTy);6017    SrcTy = DstTy;6018  }6019 6020  // Check for identity masks, which we can treat as free for both fixed and6021  // scalable vector paths.6022  if (!Mask.empty() && LT.second.isFixedLengthVector() &&6023      (Kind == TTI::SK_PermuteTwoSrc || Kind == TTI::SK_PermuteSingleSrc) &&6024      all_of(enumerate(Mask), [](const auto &M) {6025        return M.value() < 0 || M.value() == (int)M.index();6026      }))6027    return 0;6028 6029  // Segmented shuffle matching.6030  if (Kind == TTI::SK_PermuteSingleSrc && isa<FixedVectorType>(SrcTy) &&6031      !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&6032      SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(6033          AArch64::SVEBitsPerBlock)) {6034 6035    FixedVectorType *VTy = cast<FixedVectorType>(SrcTy);6036    unsigned Segments =6037        VTy->getPrimitiveSizeInBits() / AArch64::SVEBitsPerBlock;6038    unsigned SegmentElts = VTy->getNumElements() / Segments;6039 6040    // dupq zd.t, zn.t[idx]6041    if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&6042        ST->isSVEorStreamingSVEAvailable() &&6043        isDUPQMask(Mask, Segments, SegmentElts))6044      return LT.first;6045 6046    // mov zd.q, vn6047    if (ST->isSVEorStreamingSVEAvailable() &&6048        isDUPFirstSegmentMask(Mask, Segments, SegmentElts))6049      return LT.first;6050  }6051 6052  // Check for broadcast loads, which are supported by the LD1R instruction.6053  // In terms of code-size, the shuffle vector is free when a load + dup get6054  // folded into a LD1R. That's what we check and return here. For performance6055  // and reciprocal throughput, a LD1R is not completely free. In this case, we6056  // return the cost for the broadcast below (i.e. 1 for most/all types), so6057  // that we model the load + dup sequence slightly higher because LD1R is a6058  // high latency instruction.6059  if (CostKind == TTI::TCK_CodeSize && Kind == TTI::SK_Broadcast) {6060    bool IsLoad = !Args.empty() && isa<LoadInst>(Args[0]);6061    if (IsLoad && LT.second.isVector() &&6062        isLegalBroadcastLoad(SrcTy->getElementType(),6063                             LT.second.getVectorElementCount()))6064      return 0;6065  }6066 6067  // If we have 4 elements for the shuffle and a Mask, get the cost straight6068  // from the perfect shuffle tables.6069  if (Mask.size() == 4 &&6070      SrcTy->getElementCount() == ElementCount::getFixed(4) &&6071      (SrcTy->getScalarSizeInBits() == 16 ||6072       SrcTy->getScalarSizeInBits() == 32) &&6073      all_of(Mask, [](int E) { return E < 8; }))6074    return getPerfectShuffleCost(Mask);6075 6076  // Check for other shuffles that are not SK_ kinds but we have native6077  // instructions for, for example ZIP and UZP.6078  unsigned Unused;6079  if (LT.second.isFixedLengthVector() &&6080      LT.second.getVectorNumElements() == Mask.size() &&6081      (Kind == TTI::SK_PermuteTwoSrc || Kind == TTI::SK_PermuteSingleSrc) &&6082      (isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||6083       isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||6084       isREVMask(Mask, LT.second.getScalarSizeInBits(),6085                 LT.second.getVectorNumElements(), 16) ||6086       isREVMask(Mask, LT.second.getScalarSizeInBits(),6087                 LT.second.getVectorNumElements(), 32) ||6088       isREVMask(Mask, LT.second.getScalarSizeInBits(),6089                 LT.second.getVectorNumElements(), 64) ||6090       // Check for non-zero lane splats6091       all_of(drop_begin(Mask),6092              [&Mask](int M) { return M < 0 || M == Mask[0]; })))6093    return 1;6094 6095  if (Kind == TTI::SK_Broadcast || Kind == TTI::SK_Transpose ||6096      Kind == TTI::SK_Select || Kind == TTI::SK_PermuteSingleSrc ||6097      Kind == TTI::SK_Reverse || Kind == TTI::SK_Splice) {6098    static const CostTblEntry ShuffleTbl[] = {6099        // Broadcast shuffle kinds can be performed with 'dup'.6100        {TTI::SK_Broadcast, MVT::v8i8, 1},6101        {TTI::SK_Broadcast, MVT::v16i8, 1},6102        {TTI::SK_Broadcast, MVT::v4i16, 1},6103        {TTI::SK_Broadcast, MVT::v8i16, 1},6104        {TTI::SK_Broadcast, MVT::v2i32, 1},6105        {TTI::SK_Broadcast, MVT::v4i32, 1},6106        {TTI::SK_Broadcast, MVT::v2i64, 1},6107        {TTI::SK_Broadcast, MVT::v4f16, 1},6108        {TTI::SK_Broadcast, MVT::v8f16, 1},6109        {TTI::SK_Broadcast, MVT::v4bf16, 1},6110        {TTI::SK_Broadcast, MVT::v8bf16, 1},6111        {TTI::SK_Broadcast, MVT::v2f32, 1},6112        {TTI::SK_Broadcast, MVT::v4f32, 1},6113        {TTI::SK_Broadcast, MVT::v2f64, 1},6114        // Transpose shuffle kinds can be performed with 'trn1/trn2' and6115        // 'zip1/zip2' instructions.6116        {TTI::SK_Transpose, MVT::v8i8, 1},6117        {TTI::SK_Transpose, MVT::v16i8, 1},6118        {TTI::SK_Transpose, MVT::v4i16, 1},6119        {TTI::SK_Transpose, MVT::v8i16, 1},6120        {TTI::SK_Transpose, MVT::v2i32, 1},6121        {TTI::SK_Transpose, MVT::v4i32, 1},6122        {TTI::SK_Transpose, MVT::v2i64, 1},6123        {TTI::SK_Transpose, MVT::v4f16, 1},6124        {TTI::SK_Transpose, MVT::v8f16, 1},6125        {TTI::SK_Transpose, MVT::v4bf16, 1},6126        {TTI::SK_Transpose, MVT::v8bf16, 1},6127        {TTI::SK_Transpose, MVT::v2f32, 1},6128        {TTI::SK_Transpose, MVT::v4f32, 1},6129        {TTI::SK_Transpose, MVT::v2f64, 1},6130        // Select shuffle kinds.6131        // TODO: handle vXi8/vXi16.6132        {TTI::SK_Select, MVT::v2i32, 1}, // mov.6133        {TTI::SK_Select, MVT::v4i32, 2}, // rev+trn (or similar).6134        {TTI::SK_Select, MVT::v2i64, 1}, // mov.6135        {TTI::SK_Select, MVT::v2f32, 1}, // mov.6136        {TTI::SK_Select, MVT::v4f32, 2}, // rev+trn (or similar).6137        {TTI::SK_Select, MVT::v2f64, 1}, // mov.6138        // PermuteSingleSrc shuffle kinds.6139        {TTI::SK_PermuteSingleSrc, MVT::v2i32, 1}, // mov.6140        {TTI::SK_PermuteSingleSrc, MVT::v4i32, 3}, // perfectshuffle worst case.6141        {TTI::SK_PermuteSingleSrc, MVT::v2i64, 1}, // mov.6142        {TTI::SK_PermuteSingleSrc, MVT::v2f32, 1}, // mov.6143        {TTI::SK_PermuteSingleSrc, MVT::v4f32, 3}, // perfectshuffle worst case.6144        {TTI::SK_PermuteSingleSrc, MVT::v2f64, 1}, // mov.6145        {TTI::SK_PermuteSingleSrc, MVT::v4i16, 3}, // perfectshuffle worst case.6146        {TTI::SK_PermuteSingleSrc, MVT::v4f16, 3}, // perfectshuffle worst case.6147        {TTI::SK_PermuteSingleSrc, MVT::v4bf16, 3}, // same6148        {TTI::SK_PermuteSingleSrc, MVT::v8i16, 8},  // constpool + load + tbl6149        {TTI::SK_PermuteSingleSrc, MVT::v8f16, 8},  // constpool + load + tbl6150        {TTI::SK_PermuteSingleSrc, MVT::v8bf16, 8}, // constpool + load + tbl6151        {TTI::SK_PermuteSingleSrc, MVT::v8i8, 8},   // constpool + load + tbl6152        {TTI::SK_PermuteSingleSrc, MVT::v16i8, 8},  // constpool + load + tbl6153        // Reverse can be lowered with `rev`.6154        {TTI::SK_Reverse, MVT::v2i32, 1}, // REV646155        {TTI::SK_Reverse, MVT::v4i32, 2}, // REV64; EXT6156        {TTI::SK_Reverse, MVT::v2i64, 1}, // EXT6157        {TTI::SK_Reverse, MVT::v2f32, 1}, // REV646158        {TTI::SK_Reverse, MVT::v4f32, 2}, // REV64; EXT6159        {TTI::SK_Reverse, MVT::v2f64, 1}, // EXT6160        {TTI::SK_Reverse, MVT::v8f16, 2}, // REV64; EXT6161        {TTI::SK_Reverse, MVT::v8bf16, 2}, // REV64; EXT6162        {TTI::SK_Reverse, MVT::v8i16, 2}, // REV64; EXT6163        {TTI::SK_Reverse, MVT::v16i8, 2}, // REV64; EXT6164        {TTI::SK_Reverse, MVT::v4f16, 1}, // REV646165        {TTI::SK_Reverse, MVT::v4bf16, 1}, // REV646166        {TTI::SK_Reverse, MVT::v4i16, 1}, // REV646167        {TTI::SK_Reverse, MVT::v8i8, 1},  // REV646168        // Splice can all be lowered as `ext`.6169        {TTI::SK_Splice, MVT::v2i32, 1},6170        {TTI::SK_Splice, MVT::v4i32, 1},6171        {TTI::SK_Splice, MVT::v2i64, 1},6172        {TTI::SK_Splice, MVT::v2f32, 1},6173        {TTI::SK_Splice, MVT::v4f32, 1},6174        {TTI::SK_Splice, MVT::v2f64, 1},6175        {TTI::SK_Splice, MVT::v8f16, 1},6176        {TTI::SK_Splice, MVT::v8bf16, 1},6177        {TTI::SK_Splice, MVT::v8i16, 1},6178        {TTI::SK_Splice, MVT::v16i8, 1},6179        {TTI::SK_Splice, MVT::v4f16, 1},6180        {TTI::SK_Splice, MVT::v4bf16, 1},6181        {TTI::SK_Splice, MVT::v4i16, 1},6182        {TTI::SK_Splice, MVT::v8i8, 1},6183        // Broadcast shuffle kinds for scalable vectors6184        {TTI::SK_Broadcast, MVT::nxv16i8, 1},6185        {TTI::SK_Broadcast, MVT::nxv8i16, 1},6186        {TTI::SK_Broadcast, MVT::nxv4i32, 1},6187        {TTI::SK_Broadcast, MVT::nxv2i64, 1},6188        {TTI::SK_Broadcast, MVT::nxv2f16, 1},6189        {TTI::SK_Broadcast, MVT::nxv4f16, 1},6190        {TTI::SK_Broadcast, MVT::nxv8f16, 1},6191        {TTI::SK_Broadcast, MVT::nxv2bf16, 1},6192        {TTI::SK_Broadcast, MVT::nxv4bf16, 1},6193        {TTI::SK_Broadcast, MVT::nxv8bf16, 1},6194        {TTI::SK_Broadcast, MVT::nxv2f32, 1},6195        {TTI::SK_Broadcast, MVT::nxv4f32, 1},6196        {TTI::SK_Broadcast, MVT::nxv2f64, 1},6197        {TTI::SK_Broadcast, MVT::nxv16i1, 1},6198        {TTI::SK_Broadcast, MVT::nxv8i1, 1},6199        {TTI::SK_Broadcast, MVT::nxv4i1, 1},6200        {TTI::SK_Broadcast, MVT::nxv2i1, 1},6201        // Handle the cases for vector.reverse with scalable vectors6202        {TTI::SK_Reverse, MVT::nxv16i8, 1},6203        {TTI::SK_Reverse, MVT::nxv8i16, 1},6204        {TTI::SK_Reverse, MVT::nxv4i32, 1},6205        {TTI::SK_Reverse, MVT::nxv2i64, 1},6206        {TTI::SK_Reverse, MVT::nxv2f16, 1},6207        {TTI::SK_Reverse, MVT::nxv4f16, 1},6208        {TTI::SK_Reverse, MVT::nxv8f16, 1},6209        {TTI::SK_Reverse, MVT::nxv2bf16, 1},6210        {TTI::SK_Reverse, MVT::nxv4bf16, 1},6211        {TTI::SK_Reverse, MVT::nxv8bf16, 1},6212        {TTI::SK_Reverse, MVT::nxv2f32, 1},6213        {TTI::SK_Reverse, MVT::nxv4f32, 1},6214        {TTI::SK_Reverse, MVT::nxv2f64, 1},6215        {TTI::SK_Reverse, MVT::nxv16i1, 1},6216        {TTI::SK_Reverse, MVT::nxv8i1, 1},6217        {TTI::SK_Reverse, MVT::nxv4i1, 1},6218        {TTI::SK_Reverse, MVT::nxv2i1, 1},6219    };6220    if (const auto *Entry = CostTableLookup(ShuffleTbl, Kind, LT.second))6221      return LT.first * Entry->Cost;6222  }6223 6224  if (Kind == TTI::SK_Splice && isa<ScalableVectorType>(SrcTy))6225    return getSpliceCost(SrcTy, Index, CostKind);6226 6227  // Inserting a subvector can often be done with either a D, S or H register6228  // move, so long as the inserted vector is "aligned".6229  if (Kind == TTI::SK_InsertSubvector && LT.second.isFixedLengthVector() &&6230      LT.second.getSizeInBits() <= 128 && SubTp) {6231    std::pair<InstructionCost, MVT> SubLT = getTypeLegalizationCost(SubTp);6232    if (SubLT.second.isVector()) {6233      int NumElts = LT.second.getVectorNumElements();6234      int NumSubElts = SubLT.second.getVectorNumElements();6235      if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)6236        return SubLT.first;6237    }6238  }6239 6240  // Restore optimal kind.6241  if (IsExtractSubvector)6242    Kind = TTI::SK_ExtractSubvector;6243  return BaseT::getShuffleCost(Kind, DstTy, SrcTy, Mask, CostKind, Index, SubTp,6244                               Args, CxtI);6245}6246 6247static bool containsDecreasingPointers(Loop *TheLoop,6248                                       PredicatedScalarEvolution *PSE,6249                                       const DominatorTree &DT) {6250  const auto &Strides = DenseMap<Value *, const SCEV *>();6251  for (BasicBlock *BB : TheLoop->blocks()) {6252    // Scan the instructions in the block and look for addresses that are6253    // consecutive and decreasing.6254    for (Instruction &I : *BB) {6255      if (isa<LoadInst>(&I) || isa<StoreInst>(&I)) {6256        Value *Ptr = getLoadStorePointerOperand(&I);6257        Type *AccessTy = getLoadStoreType(&I);6258        if (getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,6259                         /*Assume=*/true, /*ShouldCheckWrap=*/false)6260                .value_or(0) < 0)6261          return true;6262      }6263    }6264  }6265  return false;6266}6267 6268bool AArch64TTIImpl::preferFixedOverScalableIfEqualCost(bool IsEpilogue) const {6269  if (SVEPreferFixedOverScalableIfEqualCost.getNumOccurrences())6270    return SVEPreferFixedOverScalableIfEqualCost;6271  // For cases like post-LTO vectorization, when we eventually know the trip6272  // count, epilogue with fixed-width vectorization can be deleted if the trip6273  // count is less than the epilogue iterations. That's why we prefer6274  // fixed-width vectorization in epilogue in case of equal costs.6275  if (IsEpilogue)6276    return true;6277  return ST->useFixedOverScalableIfEqualCost();6278}6279 6280unsigned AArch64TTIImpl::getEpilogueVectorizationMinVF() const {6281  return ST->getEpilogueVectorizationMinVF();6282}6283 6284bool AArch64TTIImpl::preferPredicateOverEpilogue(TailFoldingInfo *TFI) const {6285  if (!ST->hasSVE())6286    return false;6287 6288  // We don't currently support vectorisation with interleaving for SVE - with6289  // such loops we're better off not using tail-folding. This gives us a chance6290  // to fall back on fixed-width vectorisation using NEON's ld2/st2/etc.6291  if (TFI->IAI->hasGroups())6292    return false;6293 6294  TailFoldingOpts Required = TailFoldingOpts::Disabled;6295  if (TFI->LVL->getReductionVars().size())6296    Required |= TailFoldingOpts::Reductions;6297  if (TFI->LVL->getFixedOrderRecurrences().size())6298    Required |= TailFoldingOpts::Recurrences;6299 6300  // We call this to discover whether any load/store pointers in the loop have6301  // negative strides. This will require extra work to reverse the loop6302  // predicate, which may be expensive.6303  if (containsDecreasingPointers(TFI->LVL->getLoop(),6304                                 TFI->LVL->getPredicatedScalarEvolution(),6305                                 *TFI->LVL->getDominatorTree()))6306    Required |= TailFoldingOpts::Reverse;6307  if (Required == TailFoldingOpts::Disabled)6308    Required |= TailFoldingOpts::Simple;6309 6310  if (!TailFoldingOptionLoc.satisfies(ST->getSVETailFoldingDefaultOpts(),6311                                      Required))6312    return false;6313 6314  // Don't tail-fold for tight loops where we would be better off interleaving6315  // with an unpredicated loop.6316  unsigned NumInsns = 0;6317  for (BasicBlock *BB : TFI->LVL->getLoop()->blocks()) {6318    NumInsns += BB->sizeWithoutDebug();6319  }6320 6321  // We expect 4 of these to be a IV PHI, IV add, IV compare and branch.6322  return NumInsns >= SVETailFoldInsnThreshold;6323}6324 6325InstructionCost6326AArch64TTIImpl::getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,6327                                     StackOffset BaseOffset, bool HasBaseReg,6328                                     int64_t Scale, unsigned AddrSpace) const {6329  // Scaling factors are not free at all.6330  // Operands                     | Rt Latency6331  // -------------------------------------------6332  // Rt, [Xn, Xm]                 | 46333  // -------------------------------------------6334  // Rt, [Xn, Xm, lsl #imm]       | Rn: 4 Rm: 56335  // Rt, [Xn, Wm, <extend> #imm]  |6336  TargetLoweringBase::AddrMode AM;6337  AM.BaseGV = BaseGV;6338  AM.BaseOffs = BaseOffset.getFixed();6339  AM.HasBaseReg = HasBaseReg;6340  AM.Scale = Scale;6341  AM.ScalableOffset = BaseOffset.getScalable();6342  if (getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace))6343    // Scale represents reg2 * scale, thus account for 1 if6344    // it is not equal to 0 or 1.6345    return AM.Scale != 0 && AM.Scale != 1;6346  return InstructionCost::getInvalid();6347}6348 6349bool AArch64TTIImpl::shouldTreatInstructionLikeSelect(6350    const Instruction *I) const {6351  if (EnableOrLikeSelectOpt) {6352    // For the binary operators (e.g. or) we need to be more careful than6353    // selects, here we only transform them if they are already at a natural6354    // break point in the code - the end of a block with an unconditional6355    // terminator.6356    if (I->getOpcode() == Instruction::Or &&6357        isa<BranchInst>(I->getNextNode()) &&6358        cast<BranchInst>(I->getNextNode())->isUnconditional())6359      return true;6360 6361    if (I->getOpcode() == Instruction::Add ||6362        I->getOpcode() == Instruction::Sub)6363      return true;6364  }6365  return BaseT::shouldTreatInstructionLikeSelect(I);6366}6367 6368bool AArch64TTIImpl::isLSRCostLess(6369    const TargetTransformInfo::LSRCost &C1,6370    const TargetTransformInfo::LSRCost &C2) const {6371  // AArch64 specific here is adding the number of instructions to the6372  // comparison (though not as the first consideration, as some targets do)6373  // along with changing the priority of the base additions.6374  // TODO: Maybe a more nuanced tradeoff between instruction count6375  // and number of registers? To be investigated at a later date.6376  if (EnableLSRCostOpt)6377    return std::tie(C1.NumRegs, C1.Insns, C1.NumBaseAdds, C1.AddRecCost,6378                    C1.NumIVMuls, C1.ScaleCost, C1.ImmCost, C1.SetupCost) <6379           std::tie(C2.NumRegs, C2.Insns, C2.NumBaseAdds, C2.AddRecCost,6380                    C2.NumIVMuls, C2.ScaleCost, C2.ImmCost, C2.SetupCost);6381 6382  return TargetTransformInfoImplBase::isLSRCostLess(C1, C2);6383}6384 6385static bool isSplatShuffle(Value *V) {6386  if (auto *Shuf = dyn_cast<ShuffleVectorInst>(V))6387    return all_equal(Shuf->getShuffleMask());6388  return false;6389}6390 6391/// Check if both Op1 and Op2 are shufflevector extracts of either the lower6392/// or upper half of the vector elements.6393static bool areExtractShuffleVectors(Value *Op1, Value *Op2,6394                                     bool AllowSplat = false) {6395  // Scalable types can't be extract shuffle vectors.6396  if (Op1->getType()->isScalableTy() || Op2->getType()->isScalableTy())6397    return false;6398 6399  auto areTypesHalfed = [](Value *FullV, Value *HalfV) {6400    auto *FullTy = FullV->getType();6401    auto *HalfTy = HalfV->getType();6402    return FullTy->getPrimitiveSizeInBits().getFixedValue() ==6403           2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();6404  };6405 6406  auto extractHalf = [](Value *FullV, Value *HalfV) {6407    auto *FullVT = cast<FixedVectorType>(FullV->getType());6408    auto *HalfVT = cast<FixedVectorType>(HalfV->getType());6409    return FullVT->getNumElements() == 2 * HalfVT->getNumElements();6410  };6411 6412  ArrayRef<int> M1, M2;6413  Value *S1Op1 = nullptr, *S2Op1 = nullptr;6414  if (!match(Op1, m_Shuffle(m_Value(S1Op1), m_Undef(), m_Mask(M1))) ||6415      !match(Op2, m_Shuffle(m_Value(S2Op1), m_Undef(), m_Mask(M2))))6416    return false;6417 6418  // If we allow splats, set S1Op1/S2Op1 to nullptr for the relevant arg so that6419  // it is not checked as an extract below.6420  if (AllowSplat && isSplatShuffle(Op1))6421    S1Op1 = nullptr;6422  if (AllowSplat && isSplatShuffle(Op2))6423    S2Op1 = nullptr;6424 6425  // Check that the operands are half as wide as the result and we extract6426  // half of the elements of the input vectors.6427  if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||6428      (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))6429    return false;6430 6431  // Check the mask extracts either the lower or upper half of vector6432  // elements.6433  int M1Start = 0;6434  int M2Start = 0;6435  int NumElements = cast<FixedVectorType>(Op1->getType())->getNumElements() * 2;6436  if ((S1Op1 &&6437       !ShuffleVectorInst::isExtractSubvectorMask(M1, NumElements, M1Start)) ||6438      (S2Op1 &&6439       !ShuffleVectorInst::isExtractSubvectorMask(M2, NumElements, M2Start)))6440    return false;6441 6442  if ((M1Start != 0 && M1Start != (NumElements / 2)) ||6443      (M2Start != 0 && M2Start != (NumElements / 2)))6444    return false;6445  if (S1Op1 && S2Op1 && M1Start != M2Start)6446    return false;6447 6448  return true;6449}6450 6451/// Check if Ext1 and Ext2 are extends of the same type, doubling the bitwidth6452/// of the vector elements.6453static bool areExtractExts(Value *Ext1, Value *Ext2) {6454  auto areExtDoubled = [](Instruction *Ext) {6455    return Ext->getType()->getScalarSizeInBits() ==6456           2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();6457  };6458 6459  if (!match(Ext1, m_ZExtOrSExt(m_Value())) ||6460      !match(Ext2, m_ZExtOrSExt(m_Value())) ||6461      !areExtDoubled(cast<Instruction>(Ext1)) ||6462      !areExtDoubled(cast<Instruction>(Ext2)))6463    return false;6464 6465  return true;6466}6467 6468/// Check if Op could be used with vmull_high_p64 intrinsic.6469static bool isOperandOfVmullHighP64(Value *Op) {6470  Value *VectorOperand = nullptr;6471  ConstantInt *ElementIndex = nullptr;6472  return match(Op, m_ExtractElt(m_Value(VectorOperand),6473                                m_ConstantInt(ElementIndex))) &&6474         ElementIndex->getValue() == 1 &&6475         isa<FixedVectorType>(VectorOperand->getType()) &&6476         cast<FixedVectorType>(VectorOperand->getType())->getNumElements() == 2;6477}6478 6479/// Check if Op1 and Op2 could be used with vmull_high_p64 intrinsic.6480static bool areOperandsOfVmullHighP64(Value *Op1, Value *Op2) {6481  return isOperandOfVmullHighP64(Op1) && isOperandOfVmullHighP64(Op2);6482}6483 6484static bool shouldSinkVectorOfPtrs(Value *Ptrs, SmallVectorImpl<Use *> &Ops) {6485  // Restrict ourselves to the form CodeGenPrepare typically constructs.6486  auto *GEP = dyn_cast<GetElementPtrInst>(Ptrs);6487  if (!GEP || GEP->getNumOperands() != 2)6488    return false;6489 6490  Value *Base = GEP->getOperand(0);6491  Value *Offsets = GEP->getOperand(1);6492 6493  // We only care about scalar_base+vector_offsets.6494  if (Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())6495    return false;6496 6497  // Sink extends that would allow us to use 32-bit offset vectors.6498  if (isa<SExtInst>(Offsets) || isa<ZExtInst>(Offsets)) {6499    auto *OffsetsInst = cast<Instruction>(Offsets);6500    if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&6501        OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)6502      Ops.push_back(&GEP->getOperandUse(1));6503  }6504 6505  // Sink the GEP.6506  return true;6507}6508 6509/// We want to sink following cases:6510/// (add|sub|gep) A, ((mul|shl) vscale, imm); (add|sub|gep) A, vscale;6511/// (add|sub|gep) A, ((mul|shl) zext(vscale), imm);6512static bool shouldSinkVScale(Value *Op, SmallVectorImpl<Use *> &Ops) {6513  if (match(Op, m_VScale()))6514    return true;6515  if (match(Op, m_Shl(m_VScale(), m_ConstantInt())) ||6516      match(Op, m_Mul(m_VScale(), m_ConstantInt()))) {6517    Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));6518    return true;6519  }6520  if (match(Op, m_Shl(m_ZExt(m_VScale()), m_ConstantInt())) ||6521      match(Op, m_Mul(m_ZExt(m_VScale()), m_ConstantInt()))) {6522    Value *ZExtOp = cast<Instruction>(Op)->getOperand(0);6523    Ops.push_back(&cast<Instruction>(ZExtOp)->getOperandUse(0));6524    Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));6525    return true;6526  }6527  return false;6528}6529 6530/// Check if sinking \p I's operands to I's basic block is profitable, because6531/// the operands can be folded into a target instruction, e.g.6532/// shufflevectors extracts and/or sext/zext can be folded into (u,s)subl(2).6533bool AArch64TTIImpl::isProfitableToSinkOperands(6534    Instruction *I, SmallVectorImpl<Use *> &Ops) const {6535  if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {6536    switch (II->getIntrinsicID()) {6537    case Intrinsic::aarch64_neon_smull:6538    case Intrinsic::aarch64_neon_umull:6539      if (areExtractShuffleVectors(II->getOperand(0), II->getOperand(1),6540                                   /*AllowSplat=*/true)) {6541        Ops.push_back(&II->getOperandUse(0));6542        Ops.push_back(&II->getOperandUse(1));6543        return true;6544      }6545      [[fallthrough]];6546 6547    case Intrinsic::fma:6548    case Intrinsic::fmuladd:6549      if (isa<VectorType>(I->getType()) &&6550          cast<VectorType>(I->getType())->getElementType()->isHalfTy() &&6551          !ST->hasFullFP16())6552        return false;6553      [[fallthrough]];6554    case Intrinsic::aarch64_neon_sqdmull:6555    case Intrinsic::aarch64_neon_sqdmulh:6556    case Intrinsic::aarch64_neon_sqrdmulh:6557      // Sink splats for index lane variants6558      if (isSplatShuffle(II->getOperand(0)))6559        Ops.push_back(&II->getOperandUse(0));6560      if (isSplatShuffle(II->getOperand(1)))6561        Ops.push_back(&II->getOperandUse(1));6562      return !Ops.empty();6563    case Intrinsic::aarch64_neon_fmlal:6564    case Intrinsic::aarch64_neon_fmlal2:6565    case Intrinsic::aarch64_neon_fmlsl:6566    case Intrinsic::aarch64_neon_fmlsl2:6567      // Sink splats for index lane variants6568      if (isSplatShuffle(II->getOperand(1)))6569        Ops.push_back(&II->getOperandUse(1));6570      if (isSplatShuffle(II->getOperand(2)))6571        Ops.push_back(&II->getOperandUse(2));6572      return !Ops.empty();6573    case Intrinsic::aarch64_sve_ptest_first:6574    case Intrinsic::aarch64_sve_ptest_last:6575      if (auto *IIOp = dyn_cast<IntrinsicInst>(II->getOperand(0)))6576        if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)6577          Ops.push_back(&II->getOperandUse(0));6578      return !Ops.empty();6579    case Intrinsic::aarch64_sme_write_horiz:6580    case Intrinsic::aarch64_sme_write_vert:6581    case Intrinsic::aarch64_sme_writeq_horiz:6582    case Intrinsic::aarch64_sme_writeq_vert: {6583      auto *Idx = dyn_cast<Instruction>(II->getOperand(1));6584      if (!Idx || Idx->getOpcode() != Instruction::Add)6585        return false;6586      Ops.push_back(&II->getOperandUse(1));6587      return true;6588    }6589    case Intrinsic::aarch64_sme_read_horiz:6590    case Intrinsic::aarch64_sme_read_vert:6591    case Intrinsic::aarch64_sme_readq_horiz:6592    case Intrinsic::aarch64_sme_readq_vert:6593    case Intrinsic::aarch64_sme_ld1b_vert:6594    case Intrinsic::aarch64_sme_ld1h_vert:6595    case Intrinsic::aarch64_sme_ld1w_vert:6596    case Intrinsic::aarch64_sme_ld1d_vert:6597    case Intrinsic::aarch64_sme_ld1q_vert:6598    case Intrinsic::aarch64_sme_st1b_vert:6599    case Intrinsic::aarch64_sme_st1h_vert:6600    case Intrinsic::aarch64_sme_st1w_vert:6601    case Intrinsic::aarch64_sme_st1d_vert:6602    case Intrinsic::aarch64_sme_st1q_vert:6603    case Intrinsic::aarch64_sme_ld1b_horiz:6604    case Intrinsic::aarch64_sme_ld1h_horiz:6605    case Intrinsic::aarch64_sme_ld1w_horiz:6606    case Intrinsic::aarch64_sme_ld1d_horiz:6607    case Intrinsic::aarch64_sme_ld1q_horiz:6608    case Intrinsic::aarch64_sme_st1b_horiz:6609    case Intrinsic::aarch64_sme_st1h_horiz:6610    case Intrinsic::aarch64_sme_st1w_horiz:6611    case Intrinsic::aarch64_sme_st1d_horiz:6612    case Intrinsic::aarch64_sme_st1q_horiz: {6613      auto *Idx = dyn_cast<Instruction>(II->getOperand(3));6614      if (!Idx || Idx->getOpcode() != Instruction::Add)6615        return false;6616      Ops.push_back(&II->getOperandUse(3));6617      return true;6618    }6619    case Intrinsic::aarch64_neon_pmull:6620      if (!areExtractShuffleVectors(II->getOperand(0), II->getOperand(1)))6621        return false;6622      Ops.push_back(&II->getOperandUse(0));6623      Ops.push_back(&II->getOperandUse(1));6624      return true;6625    case Intrinsic::aarch64_neon_pmull64:6626      if (!areOperandsOfVmullHighP64(II->getArgOperand(0),6627                                     II->getArgOperand(1)))6628        return false;6629      Ops.push_back(&II->getArgOperandUse(0));6630      Ops.push_back(&II->getArgOperandUse(1));6631      return true;6632    case Intrinsic::masked_gather:6633      if (!shouldSinkVectorOfPtrs(II->getArgOperand(0), Ops))6634        return false;6635      Ops.push_back(&II->getArgOperandUse(0));6636      return true;6637    case Intrinsic::masked_scatter:6638      if (!shouldSinkVectorOfPtrs(II->getArgOperand(1), Ops))6639        return false;6640      Ops.push_back(&II->getArgOperandUse(1));6641      return true;6642    default:6643      return false;6644    }6645  }6646 6647  auto ShouldSinkCondition = [](Value *Cond,6648                                SmallVectorImpl<Use *> &Ops) -> bool {6649    if (!isa<IntrinsicInst>(Cond))6650      return false;6651    auto *II = dyn_cast<IntrinsicInst>(Cond);6652    if (II->getIntrinsicID() != Intrinsic::vector_reduce_or ||6653        !isa<ScalableVectorType>(II->getOperand(0)->getType()))6654      return false;6655    if (isa<CmpInst>(II->getOperand(0)))6656      Ops.push_back(&II->getOperandUse(0));6657    return true;6658  };6659 6660  switch (I->getOpcode()) {6661  case Instruction::GetElementPtr:6662  case Instruction::Add:6663  case Instruction::Sub:6664    // Sink vscales closer to uses for better isel6665    for (unsigned Op = 0; Op < I->getNumOperands(); ++Op) {6666      if (shouldSinkVScale(I->getOperand(Op), Ops)) {6667        Ops.push_back(&I->getOperandUse(Op));6668        return true;6669      }6670    }6671    break;6672  case Instruction::Select: {6673    if (!ShouldSinkCondition(I->getOperand(0), Ops))6674      return false;6675 6676    Ops.push_back(&I->getOperandUse(0));6677    return true;6678  }6679  case Instruction::Br: {6680    if (cast<BranchInst>(I)->isUnconditional())6681      return false;6682 6683    if (!ShouldSinkCondition(cast<BranchInst>(I)->getCondition(), Ops))6684      return false;6685 6686    Ops.push_back(&I->getOperandUse(0));6687    return true;6688  }6689  default:6690    break;6691  }6692 6693  if (!I->getType()->isVectorTy())6694    return false;6695 6696  switch (I->getOpcode()) {6697  case Instruction::Sub:6698  case Instruction::Add: {6699    if (!areExtractExts(I->getOperand(0), I->getOperand(1)))6700      return false;6701 6702    // If the exts' operands extract either the lower or upper elements, we6703    // can sink them too.6704    auto Ext1 = cast<Instruction>(I->getOperand(0));6705    auto Ext2 = cast<Instruction>(I->getOperand(1));6706    if (areExtractShuffleVectors(Ext1->getOperand(0), Ext2->getOperand(0))) {6707      Ops.push_back(&Ext1->getOperandUse(0));6708      Ops.push_back(&Ext2->getOperandUse(0));6709    }6710 6711    Ops.push_back(&I->getOperandUse(0));6712    Ops.push_back(&I->getOperandUse(1));6713 6714    return true;6715  }6716  case Instruction::Or: {6717    // Pattern: Or(And(MaskValue, A), And(Not(MaskValue), B)) ->6718    // bitselect(MaskValue, A, B) where Not(MaskValue) = Xor(MaskValue, -1)6719    if (ST->hasNEON()) {6720      Instruction *OtherAnd, *IA, *IB;6721      Value *MaskValue;6722      // MainAnd refers to And instruction that has 'Not' as one of its operands6723      if (match(I, m_c_Or(m_OneUse(m_Instruction(OtherAnd)),6724                          m_OneUse(m_c_And(m_OneUse(m_Not(m_Value(MaskValue))),6725                                           m_Instruction(IA)))))) {6726        if (match(OtherAnd,6727                  m_c_And(m_Specific(MaskValue), m_Instruction(IB)))) {6728          Instruction *MainAnd = I->getOperand(0) == OtherAnd6729                                     ? cast<Instruction>(I->getOperand(1))6730                                     : cast<Instruction>(I->getOperand(0));6731 6732          // Both Ands should be in same basic block as Or6733          if (I->getParent() != MainAnd->getParent() ||6734              I->getParent() != OtherAnd->getParent())6735            return false;6736 6737          // Non-mask operands of both Ands should also be in same basic block6738          if (I->getParent() != IA->getParent() ||6739              I->getParent() != IB->getParent())6740            return false;6741 6742          Ops.push_back(6743              &MainAnd->getOperandUse(MainAnd->getOperand(0) == IA ? 1 : 0));6744          Ops.push_back(&I->getOperandUse(0));6745          Ops.push_back(&I->getOperandUse(1));6746 6747          return true;6748        }6749      }6750    }6751 6752    return false;6753  }6754  case Instruction::Mul: {6755    auto ShouldSinkSplatForIndexedVariant = [](Value *V) {6756      auto *Ty = cast<VectorType>(V->getType());6757      // For SVE the lane-indexing is within 128-bits, so we can't fold splats.6758      if (Ty->isScalableTy())6759        return false;6760 6761      // Indexed variants of Mul exist for i16 and i32 element types only.6762      return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;6763    };6764 6765    int NumZExts = 0, NumSExts = 0;6766    for (auto &Op : I->operands()) {6767      // Make sure we are not already sinking this operand6768      if (any_of(Ops, [&](Use *U) { return U->get() == Op; }))6769        continue;6770 6771      if (match(&Op, m_ZExtOrSExt(m_Value()))) {6772        auto *Ext = cast<Instruction>(Op);6773        auto *ExtOp = Ext->getOperand(0);6774        if (isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))6775          Ops.push_back(&Ext->getOperandUse(0));6776        Ops.push_back(&Op);6777 6778        if (isa<SExtInst>(Ext)) {6779          NumSExts++;6780        } else {6781          NumZExts++;6782          // A zext(a) is also a sext(zext(a)), if we take more than 2 steps.6783          if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <6784              I->getType()->getScalarSizeInBits())6785            NumSExts++;6786        }6787 6788        continue;6789      }6790 6791      ShuffleVectorInst *Shuffle = dyn_cast<ShuffleVectorInst>(Op);6792      if (!Shuffle)6793        continue;6794 6795      // If the Shuffle is a splat and the operand is a zext/sext, sinking the6796      // operand and the s/zext can help create indexed s/umull. This is6797      // especially useful to prevent i64 mul being scalarized.6798      if (isSplatShuffle(Shuffle) &&6799          match(Shuffle->getOperand(0), m_ZExtOrSExt(m_Value()))) {6800        Ops.push_back(&Shuffle->getOperandUse(0));6801        Ops.push_back(&Op);6802        if (match(Shuffle->getOperand(0), m_SExt(m_Value())))6803          NumSExts++;6804        else6805          NumZExts++;6806        continue;6807      }6808 6809      Value *ShuffleOperand = Shuffle->getOperand(0);6810      InsertElementInst *Insert = dyn_cast<InsertElementInst>(ShuffleOperand);6811      if (!Insert)6812        continue;6813 6814      Instruction *OperandInstr = dyn_cast<Instruction>(Insert->getOperand(1));6815      if (!OperandInstr)6816        continue;6817 6818      ConstantInt *ElementConstant =6819          dyn_cast<ConstantInt>(Insert->getOperand(2));6820      // Check that the insertelement is inserting into element 06821      if (!ElementConstant || !ElementConstant->isZero())6822        continue;6823 6824      unsigned Opcode = OperandInstr->getOpcode();6825      if (Opcode == Instruction::SExt)6826        NumSExts++;6827      else if (Opcode == Instruction::ZExt)6828        NumZExts++;6829      else {6830        // If we find that the top bits are known 0, then we can sink and allow6831        // the backend to generate a umull.6832        unsigned Bitwidth = I->getType()->getScalarSizeInBits();6833        APInt UpperMask = APInt::getHighBitsSet(Bitwidth, Bitwidth / 2);6834        if (!MaskedValueIsZero(OperandInstr, UpperMask, DL))6835          continue;6836        NumZExts++;6837      }6838 6839      // And(Load) is excluded to prevent CGP getting stuck in a loop of sinking6840      // the And, just to hoist it again back to the load.6841      if (!match(OperandInstr, m_And(m_Load(m_Value()), m_Value())))6842        Ops.push_back(&Insert->getOperandUse(1));6843      Ops.push_back(&Shuffle->getOperandUse(0));6844      Ops.push_back(&Op);6845    }6846 6847    // It is profitable to sink if we found two of the same type of extends.6848    if (!Ops.empty() && (NumSExts == 2 || NumZExts == 2))6849      return true;6850 6851    // Otherwise, see if we should sink splats for indexed variants.6852    if (!ShouldSinkSplatForIndexedVariant(I))6853      return false;6854 6855    Ops.clear();6856    if (isSplatShuffle(I->getOperand(0)))6857      Ops.push_back(&I->getOperandUse(0));6858    if (isSplatShuffle(I->getOperand(1)))6859      Ops.push_back(&I->getOperandUse(1));6860 6861    return !Ops.empty();6862  }6863  case Instruction::FMul: {6864    // For SVE the lane-indexing is within 128-bits, so we can't fold splats.6865    if (I->getType()->isScalableTy())6866      return false;6867 6868    if (cast<VectorType>(I->getType())->getElementType()->isHalfTy() &&6869        !ST->hasFullFP16())6870      return false;6871 6872    // Sink splats for index lane variants6873    if (isSplatShuffle(I->getOperand(0)))6874      Ops.push_back(&I->getOperandUse(0));6875    if (isSplatShuffle(I->getOperand(1)))6876      Ops.push_back(&I->getOperandUse(1));6877    return !Ops.empty();6878  }6879  default:6880    return false;6881  }6882  return false;6883}6884