xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
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