10b57cec5SDimitry Andric //===- AArch64TargetTransformInfo.h - AArch64 specific TTI ------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// This file a TargetTransformInfo::Concept conforming object specific to the 100b57cec5SDimitry Andric /// AArch64 target machine. It uses the target's detailed information to 110b57cec5SDimitry Andric /// provide more precise answers to certain TTI queries, while letting the 120b57cec5SDimitry Andric /// target independent and default TTI implementations handle the rest. 130b57cec5SDimitry Andric /// 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64TARGETTRANSFORMINFO_H 170b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AARCH64_AARCH64TARGETTRANSFORMINFO_H 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "AArch64.h" 200b57cec5SDimitry Andric #include "AArch64Subtarget.h" 210b57cec5SDimitry Andric #include "AArch64TargetMachine.h" 220b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 230b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/BasicTTIImpl.h" 250b57cec5SDimitry Andric #include "llvm/IR/Function.h" 260b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 270b57cec5SDimitry Andric #include <cstdint> 28bdd1243dSDimitry Andric #include <optional> 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace llvm { 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric class APInt; 330b57cec5SDimitry Andric class Instruction; 340b57cec5SDimitry Andric class IntrinsicInst; 350b57cec5SDimitry Andric class Loop; 360b57cec5SDimitry Andric class SCEV; 370b57cec5SDimitry Andric class ScalarEvolution; 380b57cec5SDimitry Andric class Type; 390b57cec5SDimitry Andric class Value; 400b57cec5SDimitry Andric class VectorType; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric class AArch64TTIImpl : public BasicTTIImplBase<AArch64TTIImpl> { 430b57cec5SDimitry Andric using BaseT = BasicTTIImplBase<AArch64TTIImpl>; 440b57cec5SDimitry Andric using TTI = TargetTransformInfo; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric friend BaseT; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric const AArch64Subtarget *ST; 490b57cec5SDimitry Andric const AArch64TargetLowering *TLI; 500b57cec5SDimitry Andric getST()510b57cec5SDimitry Andric const AArch64Subtarget *getST() const { return ST; } getTLI()520b57cec5SDimitry Andric const AArch64TargetLowering *getTLI() const { return TLI; } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric enum MemIntrinsicType { 550b57cec5SDimitry Andric VECTOR_LDST_TWO_ELEMENTS, 560b57cec5SDimitry Andric VECTOR_LDST_THREE_ELEMENTS, 570b57cec5SDimitry Andric VECTOR_LDST_FOUR_ELEMENTS 580b57cec5SDimitry Andric }; 590b57cec5SDimitry Andric 6006c3fb27SDimitry Andric bool isWideningInstruction(Type *DstTy, unsigned Opcode, 6106c3fb27SDimitry Andric ArrayRef<const Value *> Args, 6206c3fb27SDimitry Andric Type *SrcOverrideTy = nullptr); 630b57cec5SDimitry Andric 64bdd1243dSDimitry Andric // A helper function called by 'getVectorInstrCost'. 65bdd1243dSDimitry Andric // 66bdd1243dSDimitry Andric // 'Val' and 'Index' are forwarded from 'getVectorInstrCost'; 'HasRealUse' 67bdd1243dSDimitry Andric // indicates whether the vector instruction is available in the input IR or 68bdd1243dSDimitry Andric // just imaginary in vectorizer passes. 6906c3fb27SDimitry Andric InstructionCost getVectorInstrCostHelper(const Instruction *I, Type *Val, 7006c3fb27SDimitry Andric unsigned Index, bool HasRealUse); 71bdd1243dSDimitry Andric 720b57cec5SDimitry Andric public: AArch64TTIImpl(const AArch64TargetMachine * TM,const Function & F)730b57cec5SDimitry Andric explicit AArch64TTIImpl(const AArch64TargetMachine *TM, const Function &F) 740fca6ea1SDimitry Andric : BaseT(TM, F.getDataLayout()), ST(TM->getSubtargetImpl(F)), 750b57cec5SDimitry Andric TLI(ST->getTargetLowering()) {} 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric bool areInlineCompatible(const Function *Caller, 780b57cec5SDimitry Andric const Function *Callee) const; 790b57cec5SDimitry Andric 80b121cb00SDimitry Andric bool areTypesABICompatible(const Function *Caller, const Function *Callee, 81b121cb00SDimitry Andric const ArrayRef<Type *> &Types) const; 82b121cb00SDimitry Andric 835f757f3fSDimitry Andric unsigned getInlineCallPenalty(const Function *F, const CallBase &Call, 845f757f3fSDimitry Andric unsigned DefaultCallPenalty) const; 855f757f3fSDimitry Andric 860b57cec5SDimitry Andric /// \name Scalar TTI Implementations 870b57cec5SDimitry Andric /// @{ 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric using BaseT::getIntImmCost; 90fe6060f1SDimitry Andric InstructionCost getIntImmCost(int64_t Val); 91fe6060f1SDimitry Andric InstructionCost getIntImmCost(const APInt &Imm, Type *Ty, 92fe6060f1SDimitry Andric TTI::TargetCostKind CostKind); 93fe6060f1SDimitry Andric InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, 94fe6060f1SDimitry Andric const APInt &Imm, Type *Ty, 95fe6060f1SDimitry Andric TTI::TargetCostKind CostKind, 96e8d8bef9SDimitry Andric Instruction *Inst = nullptr); 97fe6060f1SDimitry Andric InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, 98fe6060f1SDimitry Andric const APInt &Imm, Type *Ty, 99fe6060f1SDimitry Andric TTI::TargetCostKind CostKind); 1000b57cec5SDimitry Andric TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric /// @} 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// \name Vector TTI Implementations 1050b57cec5SDimitry Andric /// @{ 1060b57cec5SDimitry Andric enableInterleavedAccessVectorization()1070b57cec5SDimitry Andric bool enableInterleavedAccessVectorization() { return true; } 1080b57cec5SDimitry Andric enableMaskedInterleavedAccessVectorization()10906c3fb27SDimitry Andric bool enableMaskedInterleavedAccessVectorization() { return ST->hasSVE(); } 11006c3fb27SDimitry Andric getNumberOfRegisters(unsigned ClassID)1118bcb0991SDimitry Andric unsigned getNumberOfRegisters(unsigned ClassID) const { 1128bcb0991SDimitry Andric bool Vector = (ClassID == 1); 1130b57cec5SDimitry Andric if (Vector) { 1140b57cec5SDimitry Andric if (ST->hasNEON()) 1150b57cec5SDimitry Andric return 32; 1160b57cec5SDimitry Andric return 0; 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric return 31; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 121fe6060f1SDimitry Andric InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, 122e8d8bef9SDimitry Andric TTI::TargetCostKind CostKind); 123e8d8bef9SDimitry Andric 124bdd1243dSDimitry Andric std::optional<Instruction *> instCombineIntrinsic(InstCombiner &IC, 125fe6060f1SDimitry Andric IntrinsicInst &II) const; 126fe6060f1SDimitry Andric 127bdd1243dSDimitry Andric std::optional<Value *> simplifyDemandedVectorEltsIntrinsic( 12804eeddc0SDimitry Andric InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, 12904eeddc0SDimitry Andric APInt &UndefElts2, APInt &UndefElts3, 13004eeddc0SDimitry Andric std::function<void(Instruction *, unsigned, APInt, APInt &)> 13104eeddc0SDimitry Andric SimplifyAndSetOp) const; 13204eeddc0SDimitry Andric 133bdd1243dSDimitry Andric TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const; 1340b57cec5SDimitry Andric getMinVectorRegisterBitWidth()135fe6060f1SDimitry Andric unsigned getMinVectorRegisterBitWidth() const { 1360b57cec5SDimitry Andric return ST->getMinVectorRegisterBitWidth(); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric getVScaleForTuning()139bdd1243dSDimitry Andric std::optional<unsigned> getVScaleForTuning() const { 140349cc55cSDimitry Andric return ST->getVScaleForTuning(); 141e8d8bef9SDimitry Andric } 142e8d8bef9SDimitry Andric isVScaleKnownToBeAPowerOfTwo()14306c3fb27SDimitry Andric bool isVScaleKnownToBeAPowerOfTwo() const { return true; } 14406c3fb27SDimitry Andric 14581ad6265SDimitry Andric bool shouldMaximizeVectorBandwidth(TargetTransformInfo::RegisterKind K) const; 14681ad6265SDimitry Andric 147fe6060f1SDimitry Andric /// Try to return an estimate cost factor that can be used as a multiplier 148fe6060f1SDimitry Andric /// when scalarizing an operation for a vector with ElementCount \p VF. 149fe6060f1SDimitry Andric /// For scalable vectors this currently takes the most pessimistic view based 150fe6060f1SDimitry Andric /// upon the maximum possible value for vscale. getMaxNumElements(ElementCount VF)151fe6060f1SDimitry Andric unsigned getMaxNumElements(ElementCount VF) const { 152fe6060f1SDimitry Andric if (!VF.isScalable()) 153fe6060f1SDimitry Andric return VF.getFixedValue(); 154349cc55cSDimitry Andric 155349cc55cSDimitry Andric return VF.getKnownMinValue() * ST->getVScaleForTuning(); 156fe6060f1SDimitry Andric } 157fe6060f1SDimitry Andric 15806c3fb27SDimitry Andric unsigned getMaxInterleaveFactor(ElementCount VF); 1590b57cec5SDimitry Andric 16081ad6265SDimitry Andric bool prefersVectorizedAddressing() const; 16181ad6265SDimitry Andric 162fe6060f1SDimitry Andric InstructionCost getMaskedMemoryOpCost(unsigned Opcode, Type *Src, 163fe6060f1SDimitry Andric Align Alignment, unsigned AddressSpace, 164fe6060f1SDimitry Andric TTI::TargetCostKind CostKind); 165fe6060f1SDimitry Andric 166fe6060f1SDimitry Andric InstructionCost getGatherScatterOpCost(unsigned Opcode, Type *DataTy, 167e8d8bef9SDimitry Andric const Value *Ptr, bool VariableMask, 168fe6060f1SDimitry Andric Align Alignment, 169fe6060f1SDimitry Andric TTI::TargetCostKind CostKind, 170e8d8bef9SDimitry Andric const Instruction *I = nullptr); 171e8d8bef9SDimitry Andric 1725f757f3fSDimitry Andric bool isExtPartOfAvgExpr(const Instruction *ExtUser, Type *Dst, Type *Src); 1735f757f3fSDimitry Andric 174fe6060f1SDimitry Andric InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, 175fe6060f1SDimitry Andric TTI::CastContextHint CCH, 176fe6060f1SDimitry Andric TTI::TargetCostKind CostKind, 1770b57cec5SDimitry Andric const Instruction *I = nullptr); 1780b57cec5SDimitry Andric 179fe6060f1SDimitry Andric InstructionCost getExtractWithExtendCost(unsigned Opcode, Type *Dst, 180fe6060f1SDimitry Andric VectorType *VecTy, unsigned Index); 181fe6060f1SDimitry Andric 182fe6060f1SDimitry Andric InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, 183fe6060f1SDimitry Andric const Instruction *I = nullptr); 184fe6060f1SDimitry Andric 185fe6060f1SDimitry Andric InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, 186bdd1243dSDimitry Andric TTI::TargetCostKind CostKind, 187bdd1243dSDimitry Andric unsigned Index, Value *Op0, Value *Op1); 188bdd1243dSDimitry Andric InstructionCost getVectorInstrCost(const Instruction &I, Type *Val, 189bdd1243dSDimitry Andric TTI::TargetCostKind CostKind, 1900b57cec5SDimitry Andric unsigned Index); 1910b57cec5SDimitry Andric 19206c3fb27SDimitry Andric InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, 19306c3fb27SDimitry Andric FastMathFlags FMF, 194e8d8bef9SDimitry Andric TTI::TargetCostKind CostKind); 195e8d8bef9SDimitry Andric 196fe6060f1SDimitry Andric InstructionCost getArithmeticReductionCostSVE(unsigned Opcode, 197fe6060f1SDimitry Andric VectorType *ValTy, 198e8d8bef9SDimitry Andric TTI::TargetCostKind CostKind); 199e8d8bef9SDimitry Andric 200fe6060f1SDimitry Andric InstructionCost getSpliceCost(VectorType *Tp, int Index); 201fe6060f1SDimitry Andric 202fe6060f1SDimitry Andric InstructionCost getArithmeticInstrCost( 203349cc55cSDimitry Andric unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, 204bdd1243dSDimitry Andric TTI::OperandValueInfo Op1Info = {TTI::OK_AnyValue, TTI::OP_None}, 205bdd1243dSDimitry Andric TTI::OperandValueInfo Op2Info = {TTI::OK_AnyValue, TTI::OP_None}, 2060fca6ea1SDimitry Andric ArrayRef<const Value *> Args = std::nullopt, 207480093f4SDimitry Andric const Instruction *CxtI = nullptr); 2080b57cec5SDimitry Andric 209fe6060f1SDimitry Andric InstructionCost getAddressComputationCost(Type *Ty, ScalarEvolution *SE, 210fe6060f1SDimitry Andric const SCEV *Ptr); 2110b57cec5SDimitry Andric 212fe6060f1SDimitry Andric InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, 213e8d8bef9SDimitry Andric CmpInst::Predicate VecPred, 2145ffd83dbSDimitry Andric TTI::TargetCostKind CostKind, 2150b57cec5SDimitry Andric const Instruction *I = nullptr); 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, 2180b57cec5SDimitry Andric bool IsZeroCmp) const; 219e8d8bef9SDimitry Andric bool useNeonVector(const Type *Ty) const; 2200b57cec5SDimitry Andric 221bdd1243dSDimitry Andric InstructionCost 222bdd1243dSDimitry Andric getMemoryOpCost(unsigned Opcode, Type *Src, MaybeAlign Alignment, 223bdd1243dSDimitry Andric unsigned AddressSpace, TTI::TargetCostKind CostKind, 224bdd1243dSDimitry Andric TTI::OperandValueInfo OpInfo = {TTI::OK_AnyValue, TTI::OP_None}, 2255ffd83dbSDimitry Andric const Instruction *I = nullptr); 2260b57cec5SDimitry Andric 227fe6060f1SDimitry Andric InstructionCost getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys); 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, 230349cc55cSDimitry Andric TTI::UnrollingPreferences &UP, 231349cc55cSDimitry Andric OptimizationRemarkEmitter *ORE); 2320b57cec5SDimitry Andric 2335ffd83dbSDimitry Andric void getPeelingPreferences(Loop *L, ScalarEvolution &SE, 2345ffd83dbSDimitry Andric TTI::PeelingPreferences &PP); 2355ffd83dbSDimitry Andric 2360b57cec5SDimitry Andric Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, 2370b57cec5SDimitry Andric Type *ExpectedType); 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info); 2400b57cec5SDimitry Andric isElementTypeLegalForScalableVector(Type * Ty)241fe6060f1SDimitry Andric bool isElementTypeLegalForScalableVector(Type *Ty) const { 242e8d8bef9SDimitry Andric if (Ty->isPointerTy()) 243e8d8bef9SDimitry Andric return true; 244e8d8bef9SDimitry Andric 245fe6060f1SDimitry Andric if (Ty->isBFloatTy() && ST->hasBF16()) 246480093f4SDimitry Andric return true; 247480093f4SDimitry Andric 248fe6060f1SDimitry Andric if (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy()) 249fe6060f1SDimitry Andric return true; 250fe6060f1SDimitry Andric 2510fca6ea1SDimitry Andric if (Ty->isIntegerTy(1) || Ty->isIntegerTy(8) || Ty->isIntegerTy(16) || 252480093f4SDimitry Andric Ty->isIntegerTy(32) || Ty->isIntegerTy(64)) 253480093f4SDimitry Andric return true; 254480093f4SDimitry Andric 255480093f4SDimitry Andric return false; 256480093f4SDimitry Andric } 257480093f4SDimitry Andric isLegalMaskedLoadStore(Type * DataType,Align Alignment)258fe6060f1SDimitry Andric bool isLegalMaskedLoadStore(Type *DataType, Align Alignment) { 259fe6060f1SDimitry Andric if (!ST->hasSVE()) 260fe6060f1SDimitry Andric return false; 261fe6060f1SDimitry Andric 262fe6060f1SDimitry Andric // For fixed vectors, avoid scalarization if using SVE for them. 2635f757f3fSDimitry Andric if (isa<FixedVectorType>(DataType) && !ST->useSVEForFixedLengthVectors() && 2645f757f3fSDimitry Andric DataType->getPrimitiveSizeInBits() != 128) 265fe6060f1SDimitry Andric return false; // Fall back to scalarization of masked operations. 266fe6060f1SDimitry Andric 267349cc55cSDimitry Andric return isElementTypeLegalForScalableVector(DataType->getScalarType()); 268fe6060f1SDimitry Andric } 269fe6060f1SDimitry Andric isLegalMaskedLoad(Type * DataType,Align Alignment)2705ffd83dbSDimitry Andric bool isLegalMaskedLoad(Type *DataType, Align Alignment) { 271480093f4SDimitry Andric return isLegalMaskedLoadStore(DataType, Alignment); 272480093f4SDimitry Andric } 273480093f4SDimitry Andric isLegalMaskedStore(Type * DataType,Align Alignment)2745ffd83dbSDimitry Andric bool isLegalMaskedStore(Type *DataType, Align Alignment) { 275480093f4SDimitry Andric return isLegalMaskedLoadStore(DataType, Alignment); 276480093f4SDimitry Andric } 277480093f4SDimitry Andric isLegalMaskedGatherScatter(Type * DataType)278fe6060f1SDimitry Andric bool isLegalMaskedGatherScatter(Type *DataType) const { 2790fca6ea1SDimitry Andric if (!ST->isSVEAvailable()) 280fe6060f1SDimitry Andric return false; 281fe6060f1SDimitry Andric 282fe6060f1SDimitry Andric // For fixed vectors, scalarize if not using SVE for them. 283fe6060f1SDimitry Andric auto *DataTypeFVTy = dyn_cast<FixedVectorType>(DataType); 284fe6060f1SDimitry Andric if (DataTypeFVTy && (!ST->useSVEForFixedLengthVectors() || 285fe6060f1SDimitry Andric DataTypeFVTy->getNumElements() < 2)) 286fe6060f1SDimitry Andric return false; 287fe6060f1SDimitry Andric 288349cc55cSDimitry Andric return isElementTypeLegalForScalableVector(DataType->getScalarType()); 289fe6060f1SDimitry Andric } 290fe6060f1SDimitry Andric isLegalMaskedGather(Type * DataType,Align Alignment)291fe6060f1SDimitry Andric bool isLegalMaskedGather(Type *DataType, Align Alignment) const { 292fe6060f1SDimitry Andric return isLegalMaskedGatherScatter(DataType); 293fe6060f1SDimitry Andric } 2945f757f3fSDimitry Andric isLegalMaskedScatter(Type * DataType,Align Alignment)295fe6060f1SDimitry Andric bool isLegalMaskedScatter(Type *DataType, Align Alignment) const { 296fe6060f1SDimitry Andric return isLegalMaskedGatherScatter(DataType); 297fe6060f1SDimitry Andric } 298fe6060f1SDimitry Andric isLegalBroadcastLoad(Type * ElementTy,ElementCount NumElements)29981ad6265SDimitry Andric bool isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const { 30081ad6265SDimitry Andric // Return true if we can generate a `ld1r` splat load instruction. 30181ad6265SDimitry Andric if (!ST->hasNEON() || NumElements.isScalable()) 30281ad6265SDimitry Andric return false; 30381ad6265SDimitry Andric switch (unsigned ElementBits = ElementTy->getScalarSizeInBits()) { 30481ad6265SDimitry Andric case 8: 30581ad6265SDimitry Andric case 16: 30681ad6265SDimitry Andric case 32: 30781ad6265SDimitry Andric case 64: { 30881ad6265SDimitry Andric // We accept bit-widths >= 64bits and elements {8,16,32,64} bits. 30981ad6265SDimitry Andric unsigned VectorBits = NumElements.getFixedValue() * ElementBits; 31081ad6265SDimitry Andric return VectorBits >= 64; 31181ad6265SDimitry Andric } 31281ad6265SDimitry Andric } 31381ad6265SDimitry Andric return false; 31481ad6265SDimitry Andric } 31581ad6265SDimitry Andric isLegalNTStoreLoad(Type * DataType,Align Alignment)316bdd1243dSDimitry Andric bool isLegalNTStoreLoad(Type *DataType, Align Alignment) { 3175ffd83dbSDimitry Andric // NOTE: The logic below is mostly geared towards LV, which calls it with 3185ffd83dbSDimitry Andric // vectors with 2 elements. We might want to improve that, if other 3195ffd83dbSDimitry Andric // users show up. 320bdd1243dSDimitry Andric // Nontemporal vector loads/stores can be directly lowered to LDNP/STNP, if 321bdd1243dSDimitry Andric // the vector can be halved so that each half fits into a register. That's 322bdd1243dSDimitry Andric // the case if the element type fits into a register and the number of 323bdd1243dSDimitry Andric // elements is a power of 2 > 1. 324bdd1243dSDimitry Andric if (auto *DataTypeTy = dyn_cast<FixedVectorType>(DataType)) { 325bdd1243dSDimitry Andric unsigned NumElements = DataTypeTy->getNumElements(); 326bdd1243dSDimitry Andric unsigned EltSize = DataTypeTy->getElementType()->getScalarSizeInBits(); 3275ffd83dbSDimitry Andric return NumElements > 1 && isPowerOf2_64(NumElements) && EltSize >= 8 && 3285ffd83dbSDimitry Andric EltSize <= 128 && isPowerOf2_64(EltSize); 3295ffd83dbSDimitry Andric } 3305ffd83dbSDimitry Andric return BaseT::isLegalNTStore(DataType, Alignment); 3315ffd83dbSDimitry Andric } 3325ffd83dbSDimitry Andric isLegalNTStore(Type * DataType,Align Alignment)333bdd1243dSDimitry Andric bool isLegalNTStore(Type *DataType, Align Alignment) { 334bdd1243dSDimitry Andric return isLegalNTStoreLoad(DataType, Alignment); 335bdd1243dSDimitry Andric } 336bdd1243dSDimitry Andric isLegalNTLoad(Type * DataType,Align Alignment)337bdd1243dSDimitry Andric bool isLegalNTLoad(Type *DataType, Align Alignment) { 338bdd1243dSDimitry Andric // Only supports little-endian targets. 339bdd1243dSDimitry Andric if (ST->isLittleEndian()) 340bdd1243dSDimitry Andric return isLegalNTStoreLoad(DataType, Alignment); 341bdd1243dSDimitry Andric return BaseT::isLegalNTLoad(DataType, Alignment); 342bdd1243dSDimitry Andric } 343bdd1243dSDimitry Andric enableOrderedReductions()344349cc55cSDimitry Andric bool enableOrderedReductions() const { return true; } 345349cc55cSDimitry Andric 346fe6060f1SDimitry Andric InstructionCost getInterleavedMemoryOpCost( 3475ffd83dbSDimitry Andric unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices, 348349cc55cSDimitry Andric Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, 3495ffd83dbSDimitry Andric bool UseMaskForCond = false, bool UseMaskForGaps = false); 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric bool 3520b57cec5SDimitry Andric shouldConsiderAddressTypePromotion(const Instruction &I, 3530b57cec5SDimitry Andric bool &AllowPromotionWithoutCommonHeader); 3540b57cec5SDimitry Andric shouldExpandReduction(const IntrinsicInst * II)355e8d8bef9SDimitry Andric bool shouldExpandReduction(const IntrinsicInst *II) const { return false; } 3560b57cec5SDimitry Andric getGISelRematGlobalCost()3570b57cec5SDimitry Andric unsigned getGISelRematGlobalCost() const { 3580b57cec5SDimitry Andric return 2; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric getMinTripCountTailFoldingThreshold()36161cfbce3SDimitry Andric unsigned getMinTripCountTailFoldingThreshold() const { 36261cfbce3SDimitry Andric return ST->hasSVE() ? 5 : 0; 36361cfbce3SDimitry Andric } 36461cfbce3SDimitry Andric getPreferredTailFoldingStyle(bool IVUpdateMayOverflow)36506c3fb27SDimitry Andric TailFoldingStyle getPreferredTailFoldingStyle(bool IVUpdateMayOverflow) const { 366753f127fSDimitry Andric if (ST->hasSVE()) 36706c3fb27SDimitry Andric return IVUpdateMayOverflow 36806c3fb27SDimitry Andric ? TailFoldingStyle::DataAndControlFlowWithoutRuntimeCheck 36906c3fb27SDimitry Andric : TailFoldingStyle::DataAndControlFlow; 37006c3fb27SDimitry Andric 37106c3fb27SDimitry Andric return TailFoldingStyle::DataWithoutLaneMask; 37204eeddc0SDimitry Andric } 37304eeddc0SDimitry Andric preferFixedOverScalableIfEqualCost()3740fca6ea1SDimitry Andric bool preferFixedOverScalableIfEqualCost() const { 3750fca6ea1SDimitry Andric return ST->useFixedOverScalableIfEqualCost(); 3760fca6ea1SDimitry Andric } 3770fca6ea1SDimitry Andric 37806c3fb27SDimitry Andric bool preferPredicateOverEpilogue(TailFoldingInfo *TFI); 379fcaf7f86SDimitry Andric supportsScalableVectors()3800fca6ea1SDimitry Andric bool supportsScalableVectors() const { 3810fca6ea1SDimitry Andric return ST->isSVEorStreamingSVEAvailable(); 3820fca6ea1SDimitry Andric } 383e8d8bef9SDimitry Andric 384*62987288SDimitry Andric bool enableScalableVectorization() const; 3850eae32dcSDimitry Andric 386fe6060f1SDimitry Andric bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, 387fe6060f1SDimitry Andric ElementCount VF) const; 3880b57cec5SDimitry Andric preferPredicatedReductionSelect(unsigned Opcode,Type * Ty,TTI::ReductionFlags Flags)389fcaf7f86SDimitry Andric bool preferPredicatedReductionSelect(unsigned Opcode, Type *Ty, 390fcaf7f86SDimitry Andric TTI::ReductionFlags Flags) const { 391fcaf7f86SDimitry Andric return ST->hasSVE(); 392fcaf7f86SDimitry Andric } 393fcaf7f86SDimitry Andric 394349cc55cSDimitry Andric InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, 395bdd1243dSDimitry Andric std::optional<FastMathFlags> FMF, 396349cc55cSDimitry Andric TTI::TargetCostKind CostKind); 3970b57cec5SDimitry Andric 398fe6060f1SDimitry Andric InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *Tp, 399bdd1243dSDimitry Andric ArrayRef<int> Mask, 400bdd1243dSDimitry Andric TTI::TargetCostKind CostKind, int Index, 40181ad6265SDimitry Andric VectorType *SubTp, 4020fca6ea1SDimitry Andric ArrayRef<const Value *> Args = std::nullopt, 4030fca6ea1SDimitry Andric const Instruction *CxtI = nullptr); 404bdd1243dSDimitry Andric 4055f757f3fSDimitry Andric InstructionCost getScalarizationOverhead(VectorType *Ty, 4065f757f3fSDimitry Andric const APInt &DemandedElts, 4075f757f3fSDimitry Andric bool Insert, bool Extract, 4085f757f3fSDimitry Andric TTI::TargetCostKind CostKind); 4095f757f3fSDimitry Andric 410bdd1243dSDimitry Andric /// Return the cost of the scaling factor used in the addressing 411bdd1243dSDimitry Andric /// mode represented by AM for this target, for a load/store 412bdd1243dSDimitry Andric /// of the specified type. 413bdd1243dSDimitry Andric /// If the AM is supported, the return value must be >= 0. 414bdd1243dSDimitry Andric /// If the AM is not supported, it returns a negative value. 415bdd1243dSDimitry Andric InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, 4160fca6ea1SDimitry Andric StackOffset BaseOffset, bool HasBaseReg, 417bdd1243dSDimitry Andric int64_t Scale, unsigned AddrSpace) const; 4180b57cec5SDimitry Andric /// @} 419bdd1243dSDimitry Andric enableSelectOptimize()420bdd1243dSDimitry Andric bool enableSelectOptimize() { return ST->enableSelectOptimize(); } 42106c3fb27SDimitry Andric 4227a6dacacSDimitry Andric bool shouldTreatInstructionLikeSelect(const Instruction *I); 4237a6dacacSDimitry Andric getStoreMinimumVF(unsigned VF,Type * ScalarMemTy,Type * ScalarValTy)42406c3fb27SDimitry Andric unsigned getStoreMinimumVF(unsigned VF, Type *ScalarMemTy, 42506c3fb27SDimitry Andric Type *ScalarValTy) const { 42606c3fb27SDimitry Andric // We can vectorize store v4i8. 42706c3fb27SDimitry Andric if (ScalarMemTy->isIntegerTy(8) && isPowerOf2_32(VF) && VF >= 4) 42806c3fb27SDimitry Andric return 4; 42906c3fb27SDimitry Andric 43006c3fb27SDimitry Andric return BaseT::getStoreMinimumVF(VF, ScalarMemTy, ScalarValTy); 43106c3fb27SDimitry Andric } 4321db9f3b2SDimitry Andric getMinPageSize()4331db9f3b2SDimitry Andric std::optional<unsigned> getMinPageSize() const { return 4096; } 4340fca6ea1SDimitry Andric 4350fca6ea1SDimitry Andric bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, 4360fca6ea1SDimitry Andric const TargetTransformInfo::LSRCost &C2); 4370b57cec5SDimitry Andric }; 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric } // end namespace llvm 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AARCH64_AARCH64TARGETTRANSFORMINFO_H 442