1//===- AArch64TargetTransformInfo.h - AArch64 specific TTI ------*- C++ -*-===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file a TargetTransformInfo::Concept conforming object specific to the
10/// AArch64 target machine. It uses the target's detailed information to
11/// provide more precise answers to certain TTI queries, while letting the
12/// target independent and default TTI implementations handle the rest.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64TARGETTRANSFORMINFO_H
17#define LLVM_LIB_TARGET_AARCH64_AARCH64TARGETTRANSFORMINFO_H
18
19#include "AArch64.h"
20#include "AArch64Subtarget.h"
21#include "AArch64TargetMachine.h"
22#include "llvm/ADT/ArrayRef.h"
23#include "llvm/Analysis/TargetTransformInfo.h"
24#include "llvm/CodeGen/BasicTTIImpl.h"
25#include "llvm/IR/Function.h"
26#include "llvm/IR/Intrinsics.h"
27#include <cstdint>
28
29namespace llvm {
30
31class APInt;
32class Instruction;
33class IntrinsicInst;
34class Loop;
35class SCEV;
36class ScalarEvolution;
37class Type;
38class Value;
39class VectorType;
40
41class AArch64TTIImpl : public BasicTTIImplBase<AArch64TTIImpl> {
42  using BaseT = BasicTTIImplBase<AArch64TTIImpl>;
43  using TTI = TargetTransformInfo;
44
45  friend BaseT;
46
47  const AArch64Subtarget *ST;
48  const AArch64TargetLowering *TLI;
49
50  const AArch64Subtarget *getST() const { return ST; }
51  const AArch64TargetLowering *getTLI() const { return TLI; }
52
53  enum MemIntrinsicType {
54    VECTOR_LDST_TWO_ELEMENTS,
55    VECTOR_LDST_THREE_ELEMENTS,
56    VECTOR_LDST_FOUR_ELEMENTS
57  };
58
59  bool isWideningInstruction(Type *Ty, unsigned Opcode,
60                             ArrayRef<const Value *> Args);
61
62public:
63  explicit AArch64TTIImpl(const AArch64TargetMachine *TM, const Function &F)
64      : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)),
65        TLI(ST->getTargetLowering()) {}
66
67  bool areInlineCompatible(const Function *Caller,
68                           const Function *Callee) const;
69
70  /// \name Scalar TTI Implementations
71  /// @{
72
73  using BaseT::getIntImmCost;
74  int getIntImmCost(int64_t Val);
75  int getIntImmCost(const APInt &Imm, Type *Ty);
76  int getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm,
77                        Type *Ty);
78  int getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
79                          Type *Ty);
80  TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth);
81
82  /// @}
83
84  /// \name Vector TTI Implementations
85  /// @{
86
87  bool enableInterleavedAccessVectorization() { return true; }
88
89  unsigned getNumberOfRegisters(unsigned ClassID) const {
90    bool Vector = (ClassID == 1);
91    if (Vector) {
92      if (ST->hasNEON())
93        return 32;
94      return 0;
95    }
96    return 31;
97  }
98
99  unsigned getRegisterBitWidth(bool Vector) const {
100    if (Vector) {
101      if (ST->hasNEON())
102        return 128;
103      return 0;
104    }
105    return 64;
106  }
107
108  unsigned getMinVectorRegisterBitWidth() {
109    return ST->getMinVectorRegisterBitWidth();
110  }
111
112  unsigned getMaxInterleaveFactor(unsigned VF);
113
114  int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
115                       const Instruction *I = nullptr);
116
117  int getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy,
118                               unsigned Index);
119
120  int getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index);
121
122  int getArithmeticInstrCost(
123      unsigned Opcode, Type *Ty,
124      TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue,
125      TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue,
126      TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None,
127      TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None,
128      ArrayRef<const Value *> Args = ArrayRef<const Value *>(),
129      const Instruction *CxtI = nullptr);
130
131  int getAddressComputationCost(Type *Ty, ScalarEvolution *SE, const SCEV *Ptr);
132
133  int getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy,
134                         const Instruction *I = nullptr);
135
136  TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize,
137                                                    bool IsZeroCmp) const;
138
139  int getMemoryOpCost(unsigned Opcode, Type *Src, MaybeAlign Alignment,
140                      unsigned AddressSpace, const Instruction *I = nullptr);
141
142  int getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys);
143
144  void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,
145                               TTI::UnrollingPreferences &UP);
146
147  Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
148                                           Type *ExpectedType);
149
150  bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info);
151
152  bool isLegalMaskedLoadStore(Type *DataType, MaybeAlign Alignment) {
153    if (!isa<VectorType>(DataType) || !ST->hasSVE())
154      return false;
155
156    Type *Ty = DataType->getVectorElementType();
157    if (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy())
158      return true;
159
160    if (Ty->isIntegerTy(8) || Ty->isIntegerTy(16) ||
161        Ty->isIntegerTy(32) || Ty->isIntegerTy(64))
162      return true;
163
164    return false;
165  }
166
167  bool isLegalMaskedLoad(Type *DataType, MaybeAlign Alignment) {
168    return isLegalMaskedLoadStore(DataType, Alignment);
169  }
170
171  bool isLegalMaskedStore(Type *DataType, MaybeAlign Alignment) {
172    return isLegalMaskedLoadStore(DataType, Alignment);
173  }
174
175  int getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor,
176                                 ArrayRef<unsigned> Indices, unsigned Alignment,
177                                 unsigned AddressSpace,
178                                 bool UseMaskForCond = false,
179                                 bool UseMaskForGaps = false);
180
181  bool
182  shouldConsiderAddressTypePromotion(const Instruction &I,
183                                     bool &AllowPromotionWithoutCommonHeader);
184
185  bool shouldExpandReduction(const IntrinsicInst *II) const {
186    switch (II->getIntrinsicID()) {
187    case Intrinsic::experimental_vector_reduce_v2_fadd:
188    case Intrinsic::experimental_vector_reduce_v2_fmul:
189      // We don't have legalization support for ordered FP reductions.
190      return !II->getFastMathFlags().allowReassoc();
191
192    case Intrinsic::experimental_vector_reduce_fmax:
193    case Intrinsic::experimental_vector_reduce_fmin:
194      // Lowering asserts that there are no NaNs.
195      return !II->getFastMathFlags().noNaNs();
196
197    default:
198      // Don't expand anything else, let legalization deal with it.
199      return false;
200    }
201  }
202
203  unsigned getGISelRematGlobalCost() const {
204    return 2;
205  }
206
207  bool useReductionIntrinsic(unsigned Opcode, Type *Ty,
208                             TTI::ReductionFlags Flags) const;
209
210  int getArithmeticReductionCost(unsigned Opcode, Type *Ty,
211                                 bool IsPairwiseForm);
212
213  int getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index, Type *SubTp);
214  /// @}
215};
216
217} // end namespace llvm
218
219#endif // LLVM_LIB_TARGET_AARCH64_AARCH64TARGETTRANSFORMINFO_H
220