brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.5 KiB · 2a73fe6 Raw
507 lines · c
1//===- RISCVTargetTransformInfo.h - RISC-V 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-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// This file defines a TargetTransformInfoImplBase conforming object specific10/// to the RISC-V target machine. It uses the target's detailed information to11/// provide more precise answers to certain TTI queries, while letting the12/// target independent and default TTI implementations handle the rest.13///14//===----------------------------------------------------------------------===//15 16#ifndef LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H17#define LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H18 19#include "RISCVSubtarget.h"20#include "RISCVTargetMachine.h"21#include "llvm/Analysis/TargetTransformInfo.h"22#include "llvm/CodeGen/BasicTTIImpl.h"23#include "llvm/IR/Function.h"24#include <optional>25 26namespace llvm {27 28class RISCVTTIImpl final : public BasicTTIImplBase<RISCVTTIImpl> {29  using BaseT = BasicTTIImplBase<RISCVTTIImpl>;30  using TTI = TargetTransformInfo;31 32  friend BaseT;33 34  const RISCVSubtarget *ST;35  const RISCVTargetLowering *TLI;36 37  const RISCVSubtarget *getST() const { return ST; }38  const RISCVTargetLowering *getTLI() const { return TLI; }39 40  /// This function returns an estimate for VL to be used in VL based terms41  /// of the cost model.  For fixed length vectors, this is simply the42  /// vector length.  For scalable vectors, we return results consistent43  /// with getVScaleForTuning under the assumption that clients are also44  /// using that when comparing costs between scalar and vector representation.45  /// This does unfortunately mean that we can both undershoot and overshot46  /// the true cost significantly if getVScaleForTuning is wildly off for the47  /// actual target hardware.48  unsigned getEstimatedVLFor(VectorType *Ty) const;49 50  /// This function calculates the costs for one or more RVV opcodes based51  /// on the vtype and the cost kind.52  /// \param Opcodes A list of opcodes of the RVV instruction to evaluate.53  /// \param VT The MVT of vtype associated with the RVV instructions.54  /// For widening/narrowing instructions where the result and source types55  /// differ, it is important to check the spec to determine whether the vtype56  /// refers to the result or source type.57  /// \param CostKind The type of cost to compute.58  InstructionCost getRISCVInstructionCost(ArrayRef<unsigned> OpCodes, MVT VT,59                                          TTI::TargetCostKind CostKind) const;60 61  /// Return the cost of accessing a constant pool entry of the specified62  /// type.63  InstructionCost getConstantPoolLoadCost(Type *Ty,64                                          TTI::TargetCostKind CostKind) const;65 66  /// If this shuffle can be lowered as a masked slide pair (at worst),67  /// return a cost for it.68  InstructionCost getSlideCost(FixedVectorType *Tp, ArrayRef<int> Mask,69                               TTI::TargetCostKind CostKind) const;70 71public:72  explicit RISCVTTIImpl(const RISCVTargetMachine *TM, const Function &F)73      : BaseT(TM, F.getDataLayout()), ST(TM->getSubtargetImpl(F)),74        TLI(ST->getTargetLowering()) {}75 76  /// Return the cost of materializing an immediate for a value operand of77  /// a store instruction.78  InstructionCost getStoreImmCost(Type *VecTy, TTI::OperandValueInfo OpInfo,79                                  TTI::TargetCostKind CostKind) const;80 81  InstructionCost getIntImmCost(const APInt &Imm, Type *Ty,82                                TTI::TargetCostKind CostKind) const override;83  InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx,84                                    const APInt &Imm, Type *Ty,85                                    TTI::TargetCostKind CostKind,86                                    Instruction *Inst = nullptr) const override;87  InstructionCost88  getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,89                      Type *Ty, TTI::TargetCostKind CostKind) const override;90 91  /// \name EVL Support for predicated vectorization.92  /// Whether the target supports the %evl parameter of VP intrinsic efficiently93  /// in hardware. (see LLVM Language Reference - "Vector Predication94  /// Intrinsics",95  /// https://llvm.org/docs/LangRef.html#vector-predication-intrinsics and96  /// "IR-level VP intrinsics",97  /// https://llvm.org/docs/Proposals/VectorPredication.html#ir-level-vp-intrinsics).98  bool hasActiveVectorLength() const override;99 100  TargetTransformInfo::PopcntSupportKind101  getPopcntSupport(unsigned TyWidth) const override;102 103  InstructionCost getPartialReductionCost(104      unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,105      ElementCount VF, TTI::PartialReductionExtendKind OpAExtend,106      TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,107      TTI::TargetCostKind CostKind) const override;108 109  bool shouldExpandReduction(const IntrinsicInst *II) const override;110  bool supportsScalableVectors() const override {111    return ST->hasVInstructions();112  }113  bool enableOrderedReductions() const override { return true; }114  bool enableScalableVectorization() const override {115    return ST->hasVInstructions();116  }117  bool preferPredicateOverEpilogue(TailFoldingInfo *TFI) const override {118    return ST->hasVInstructions();119  }120  TailFoldingStyle121  getPreferredTailFoldingStyle(bool IVUpdateMayOverflow) const override {122    return ST->hasVInstructions() ? TailFoldingStyle::DataWithEVL123                                  : TailFoldingStyle::None;124  }125  std::optional<unsigned> getMaxVScale() const override;126  std::optional<unsigned> getVScaleForTuning() const override;127 128  TypeSize129  getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override;130 131  unsigned getRegUsageForType(Type *Ty) const override;132 133  unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const override;134 135  bool preferAlternateOpcodeVectorization() const override;136 137  bool preferEpilogueVectorization() const override {138    // Epilogue vectorization is usually unprofitable - tail folding or139    // a smaller VF would have been better.  This a blunt hammer - we140    // should re-examine this once vectorization is better tuned.141    return false;142  }143 144  bool shouldConsiderVectorizationRegPressure() const override { return true; }145 146  InstructionCost147  getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA,148                           TTI::TargetCostKind CostKind) const override;149 150  InstructionCost151  getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA,152                        TTI::TargetCostKind CostKind) const override;153 154  InstructionCost155  getPointersChainCost(ArrayRef<const Value *> Ptrs, const Value *Base,156                       const TTI::PointersChainInfo &Info, Type *AccessTy,157                       TTI::TargetCostKind CostKind) const override;158 159  void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,160                               TTI::UnrollingPreferences &UP,161                               OptimizationRemarkEmitter *ORE) const override;162 163  void getPeelingPreferences(Loop *L, ScalarEvolution &SE,164                             TTI::PeelingPreferences &PP) const override;165 166  bool getTgtMemIntrinsic(IntrinsicInst *Inst,167                          MemIntrinsicInfo &Info) const override;168 169  unsigned getMinVectorRegisterBitWidth() const override {170    return ST->useRVVForFixedLengthVectors() ? 16 : 0;171  }172 173  InstructionCost174  getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,175                 ArrayRef<int> Mask, TTI::TargetCostKind CostKind, int Index,176                 VectorType *SubTp, ArrayRef<const Value *> Args = {},177                 const Instruction *CxtI = nullptr) const override;178 179  InstructionCost getScalarizationOverhead(180      VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,181      TTI::TargetCostKind CostKind, bool ForPoisonSrc = true,182      ArrayRef<Value *> VL = {}) const override;183 184  InstructionCost185  getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,186                        TTI::TargetCostKind CostKind) const override;187 188  InstructionCost189  getAddressComputationCost(Type *PTy, ScalarEvolution *SE, const SCEV *Ptr,190                            TTI::TargetCostKind CostKind) const override;191 192  InstructionCost getInterleavedMemoryOpCost(193      unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,194      Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,195      bool UseMaskForCond = false, bool UseMaskForGaps = false) const override;196 197  InstructionCost getGatherScatterOpCost(unsigned Opcode, Type *DataTy,198                                         const Value *Ptr, bool VariableMask,199                                         Align Alignment,200                                         TTI::TargetCostKind CostKind,201                                         const Instruction *I) const override;202 203  InstructionCost204  getExpandCompressMemoryOpCost(const MemIntrinsicCostAttributes &MICA,205                                TTI::TargetCostKind CostKind) const override;206 207  InstructionCost getStridedMemoryOpCost(unsigned Opcode, Type *DataTy,208                                         const Value *Ptr, bool VariableMask,209                                         Align Alignment,210                                         TTI::TargetCostKind CostKind,211                                         const Instruction *I) const override;212 213  InstructionCost214  getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const override;215 216  InstructionCost217  getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,218                   TTI::CastContextHint CCH, TTI::TargetCostKind CostKind,219                   const Instruction *I = nullptr) const override;220 221  InstructionCost222  getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF,223                         TTI::TargetCostKind CostKind) const override;224 225  InstructionCost226  getArithmeticReductionCost(unsigned Opcode, VectorType *Ty,227                             std::optional<FastMathFlags> FMF,228                             TTI::TargetCostKind CostKind) const override;229 230  InstructionCost231  getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy,232                           VectorType *ValTy, std::optional<FastMathFlags> FMF,233                           TTI::TargetCostKind CostKind) const override;234 235  InstructionCost getMemoryOpCost(236      unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace,237      TTI::TargetCostKind CostKind,238      TTI::OperandValueInfo OpdInfo = {TTI::OK_AnyValue, TTI::OP_None},239      const Instruction *I = nullptr) const override;240 241  InstructionCost getCmpSelInstrCost(242      unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,243      TTI::TargetCostKind CostKind,244      TTI::OperandValueInfo Op1Info = {TTI::OK_AnyValue, TTI::OP_None},245      TTI::OperandValueInfo Op2Info = {TTI::OK_AnyValue, TTI::OP_None},246      const Instruction *I = nullptr) const override;247 248  InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind,249                                 const Instruction *I = nullptr) const override;250 251  using BaseT::getVectorInstrCost;252  InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val,253                                     TTI::TargetCostKind CostKind,254                                     unsigned Index, const Value *Op0,255                                     const Value *Op1) const override;256 257  InstructionCost258  getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val,259                                   TTI::TargetCostKind CostKind,260                                   unsigned Index) const override;261 262  InstructionCost getArithmeticInstrCost(263      unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,264      TTI::OperandValueInfo Op1Info = {TTI::OK_AnyValue, TTI::OP_None},265      TTI::OperandValueInfo Op2Info = {TTI::OK_AnyValue, TTI::OP_None},266      ArrayRef<const Value *> Args = {},267      const Instruction *CxtI = nullptr) const override;268 269  bool isElementTypeLegalForScalableVector(Type *Ty) const override {270    return TLI->isLegalElementTypeForRVV(TLI->getValueType(DL, Ty));271  }272 273  bool isLegalMaskedLoadStore(Type *DataType, Align Alignment) const {274    if (!ST->hasVInstructions())275      return false;276 277    EVT DataTypeVT = TLI->getValueType(DL, DataType);278 279    // Only support fixed vectors if we know the minimum vector size.280    if (DataTypeVT.isFixedLengthVector() && !ST->useRVVForFixedLengthVectors())281      return false;282 283    EVT ElemType = DataTypeVT.getScalarType();284    if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())285      return false;286 287    return TLI->isLegalElementTypeForRVV(ElemType);288  }289 290  bool isLegalMaskedLoad(Type *DataType, Align Alignment,291                         unsigned /*AddressSpace*/,292                         TTI::MaskKind /*MaskKind*/) const override {293    return isLegalMaskedLoadStore(DataType, Alignment);294  }295  bool isLegalMaskedStore(Type *DataType, Align Alignment,296                          unsigned /*AddressSpace*/,297                          TTI::MaskKind /*MaskKind*/) const override {298    return isLegalMaskedLoadStore(DataType, Alignment);299  }300 301  bool isLegalMaskedGatherScatter(Type *DataType, Align Alignment) const {302    if (!ST->hasVInstructions())303      return false;304 305    EVT DataTypeVT = TLI->getValueType(DL, DataType);306 307    // Only support fixed vectors if we know the minimum vector size.308    if (DataTypeVT.isFixedLengthVector() && !ST->useRVVForFixedLengthVectors())309      return false;310 311    // We also need to check if the vector of address is valid.312    EVT PointerTypeVT = EVT(TLI->getPointerTy(DL));313    if (DataTypeVT.isScalableVector() &&314        !TLI->isLegalElementTypeForRVV(PointerTypeVT))315      return false;316 317    EVT ElemType = DataTypeVT.getScalarType();318    if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())319      return false;320 321    return TLI->isLegalElementTypeForRVV(ElemType);322  }323 324  bool isLegalMaskedGather(Type *DataType, Align Alignment) const override {325    return isLegalMaskedGatherScatter(DataType, Alignment);326  }327  bool isLegalMaskedScatter(Type *DataType, Align Alignment) const override {328    return isLegalMaskedGatherScatter(DataType, Alignment);329  }330 331  bool forceScalarizeMaskedGather(VectorType *VTy,332                                  Align Alignment) const override {333    // Scalarize masked gather for RV64 if EEW=64 indices aren't supported.334    return ST->is64Bit() && !ST->hasVInstructionsI64();335  }336 337  bool forceScalarizeMaskedScatter(VectorType *VTy,338                                   Align Alignment) const override {339    // Scalarize masked scatter for RV64 if EEW=64 indices aren't supported.340    return ST->is64Bit() && !ST->hasVInstructionsI64();341  }342 343  bool isLegalStridedLoadStore(Type *DataType, Align Alignment) const override {344    EVT DataTypeVT = TLI->getValueType(DL, DataType);345    return TLI->isLegalStridedLoadStore(DataTypeVT, Alignment);346  }347 348  bool isLegalInterleavedAccessType(VectorType *VTy, unsigned Factor,349                                    Align Alignment,350                                    unsigned AddrSpace) const override {351    return TLI->isLegalInterleavedAccessType(VTy, Factor, Alignment, AddrSpace,352                                             DL);353  }354 355  bool isLegalMaskedExpandLoad(Type *DataType, Align Alignment) const override;356 357  bool isLegalMaskedCompressStore(Type *DataTy, Align Alignment) const override;358 359  bool isVScaleKnownToBeAPowerOfTwo() const override {360    return TLI->isVScaleKnownToBeAPowerOfTwo();361  }362 363  /// \returns How the target needs this vector-predicated operation to be364  /// transformed.365  TargetTransformInfo::VPLegalization366  getVPLegalizationStrategy(const VPIntrinsic &PI) const override {367    using VPLegalization = TargetTransformInfo::VPLegalization;368    if (!ST->hasVInstructions() ||369        (PI.getIntrinsicID() == Intrinsic::vp_reduce_mul &&370         cast<VectorType>(PI.getArgOperand(1)->getType())371                 ->getElementType()372                 ->getIntegerBitWidth() != 1))373      return VPLegalization(VPLegalization::Discard, VPLegalization::Convert);374    return VPLegalization(VPLegalization::Legal, VPLegalization::Legal);375  }376 377  bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc,378                                   ElementCount VF) const override {379    if (!VF.isScalable())380      return true;381 382    Type *Ty = RdxDesc.getRecurrenceType();383    if (!TLI->isLegalElementTypeForRVV(TLI->getValueType(DL, Ty)))384      return false;385 386    switch (RdxDesc.getRecurrenceKind()) {387    case RecurKind::Add:388    case RecurKind::Sub:389    case RecurKind::AddChainWithSubs:390    case RecurKind::And:391    case RecurKind::Or:392    case RecurKind::Xor:393    case RecurKind::SMin:394    case RecurKind::SMax:395    case RecurKind::UMin:396    case RecurKind::UMax:397    case RecurKind::FMin:398    case RecurKind::FMax:399      return true;400    case RecurKind::AnyOf:401    case RecurKind::FAdd:402    case RecurKind::FMulAdd:403      // We can't promote f16/bf16 fadd reductions and scalable vectors can't be404      // expanded.405      if (Ty->isBFloatTy() || (Ty->isHalfTy() && !ST->hasVInstructionsF16()))406        return false;407      return true;408    default:409      return false;410    }411  }412 413  unsigned getMaxInterleaveFactor(ElementCount VF) const override {414    // Don't interleave if the loop has been vectorized with scalable vectors.415    if (VF.isScalable())416      return 1;417    // If the loop will not be vectorized, don't interleave the loop.418    // Let regular unroll to unroll the loop.419    return VF.isScalar() ? 1 : ST->getMaxInterleaveFactor();420  }421 422  bool enableInterleavedAccessVectorization() const override { return true; }423 424  bool enableMaskedInterleavedAccessVectorization() const override {425    return ST->hasVInstructions();426  }427 428  unsigned getMinTripCountTailFoldingThreshold() const override;429 430  enum RISCVRegisterClass { GPRRC, FPRRC, VRRC };431  unsigned getNumberOfRegisters(unsigned ClassID) const override {432    switch (ClassID) {433    case RISCVRegisterClass::GPRRC:434      // 31 = 32 GPR - x0 (zero register)435      // FIXME: Should we exclude fixed registers like SP, TP or GP?436      return 31;437    case RISCVRegisterClass::FPRRC:438      if (ST->hasStdExtF())439        return 32;440      return 0;441    case RISCVRegisterClass::VRRC:442      // Although there are 32 vector registers, v0 is special in that it is the443      // only register that can be used to hold a mask.444      // FIXME: Should we conservatively return 31 as the number of usable445      // vector registers?446      return ST->hasVInstructions() ? 32 : 0;447    }448    llvm_unreachable("unknown register class");449  }450 451  TTI::AddressingModeKind452  getPreferredAddressingMode(const Loop *L, ScalarEvolution *SE) const override;453 454  unsigned getRegisterClassForType(bool Vector,455                                   Type *Ty = nullptr) const override {456    if (Vector)457      return RISCVRegisterClass::VRRC;458    if (!Ty)459      return RISCVRegisterClass::GPRRC;460 461    Type *ScalarTy = Ty->getScalarType();462    if ((ScalarTy->isHalfTy() && ST->hasStdExtZfhmin()) ||463        (ScalarTy->isFloatTy() && ST->hasStdExtF()) ||464        (ScalarTy->isDoubleTy() && ST->hasStdExtD())) {465      return RISCVRegisterClass::FPRRC;466    }467 468    return RISCVRegisterClass::GPRRC;469  }470 471  const char *getRegisterClassName(unsigned ClassID) const override {472    switch (ClassID) {473    case RISCVRegisterClass::GPRRC:474      return "RISCV::GPRRC";475    case RISCVRegisterClass::FPRRC:476      return "RISCV::FPRRC";477    case RISCVRegisterClass::VRRC:478      return "RISCV::VRRC";479    }480    llvm_unreachable("unknown register class");481  }482 483  bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1,484                     const TargetTransformInfo::LSRCost &C2) const override;485 486  bool shouldConsiderAddressTypePromotion(487      const Instruction &I,488      bool &AllowPromotionWithoutCommonHeader) const override;489  std::optional<unsigned> getMinPageSize() const override { return 4096; }490  /// Return true if the (vector) instruction I will be lowered to an491  /// instruction with a scalar splat operand for the given Operand number.492  bool canSplatOperand(Instruction *I, int Operand) const;493  /// Return true if a vector instruction will lower to a target instruction494  /// able to splat the given operand.495  bool canSplatOperand(unsigned Opcode, int Operand) const;496 497  bool isProfitableToSinkOperands(Instruction *I,498                                  SmallVectorImpl<Use *> &Ops) const override;499 500  TTI::MemCmpExpansionOptions501  enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override;502};503 504} // end namespace llvm505 506#endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H507