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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file defines a TargetTransformInfo::Concept conforming object specific 10 /// to the RISC-V 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_RISCV_RISCVTARGETTRANSFORMINFO_H 17 #define LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H 18 19 #include "RISCVSubtarget.h" 20 #include "RISCVTargetMachine.h" 21 #include "llvm/Analysis/IVDescriptors.h" 22 #include "llvm/Analysis/TargetTransformInfo.h" 23 #include "llvm/CodeGen/BasicTTIImpl.h" 24 #include "llvm/IR/Function.h" 25 26 namespace llvm { 27 28 class RISCVTTIImpl : 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 public: 41 explicit RISCVTTIImpl(const RISCVTargetMachine *TM, const Function &F) 42 : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), 43 TLI(ST->getTargetLowering()) {} 44 45 InstructionCost getIntImmCost(const APInt &Imm, Type *Ty, 46 TTI::TargetCostKind CostKind); 47 InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, 48 const APInt &Imm, Type *Ty, 49 TTI::TargetCostKind CostKind, 50 Instruction *Inst = nullptr); 51 InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, 52 const APInt &Imm, Type *Ty, 53 TTI::TargetCostKind CostKind); 54 55 TargetTransformInfo::PopcntSupportKind getPopcntSupport(unsigned TyWidth); 56 57 bool shouldExpandReduction(const IntrinsicInst *II) const; 58 bool supportsScalableVectors() const { return ST->hasVInstructions(); } 59 Optional<unsigned> getMaxVScale() const; 60 61 TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const; 62 63 InstructionCost getRegUsageForType(Type *Ty); 64 65 InstructionCost getMaskedMemoryOpCost(unsigned Opcode, Type *Src, 66 Align Alignment, unsigned AddressSpace, 67 TTI::TargetCostKind CostKind); 68 69 void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, 70 TTI::UnrollingPreferences &UP, 71 OptimizationRemarkEmitter *ORE); 72 73 void getPeelingPreferences(Loop *L, ScalarEvolution &SE, 74 TTI::PeelingPreferences &PP); 75 76 unsigned getMinVectorRegisterBitWidth() const { 77 return ST->useRVVForFixedLengthVectors() ? 16 : 0; 78 } 79 80 InstructionCost getSpliceCost(VectorType *Tp, int Index); 81 InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *Tp, 82 ArrayRef<int> Mask, int Index, 83 VectorType *SubTp); 84 85 InstructionCost getGatherScatterOpCost(unsigned Opcode, Type *DataTy, 86 const Value *Ptr, bool VariableMask, 87 Align Alignment, 88 TTI::TargetCostKind CostKind, 89 const Instruction *I); 90 91 InstructionCost getMinMaxReductionCost(VectorType *Ty, VectorType *CondTy, 92 bool IsUnsigned, 93 TTI::TargetCostKind CostKind); 94 95 InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, 96 Optional<FastMathFlags> FMF, 97 TTI::TargetCostKind CostKind); 98 99 bool isLegalMaskedLoadStore(Type *DataType, Align Alignment) { 100 if (!ST->hasVInstructions()) 101 return false; 102 103 // Only support fixed vectors if we know the minimum vector size. 104 if (isa<FixedVectorType>(DataType) && ST->getMinRVVVectorSizeInBits() == 0) 105 return false; 106 107 // Don't allow elements larger than the ELEN. 108 // FIXME: How to limit for scalable vectors? 109 if (isa<FixedVectorType>(DataType) && 110 DataType->getScalarSizeInBits() > ST->getMaxELENForFixedLengthVectors()) 111 return false; 112 113 if (Alignment < 114 DL.getTypeStoreSize(DataType->getScalarType()).getFixedSize()) 115 return false; 116 117 return TLI->isLegalElementTypeForRVV(DataType->getScalarType()); 118 } 119 120 bool isLegalMaskedLoad(Type *DataType, Align Alignment) { 121 return isLegalMaskedLoadStore(DataType, Alignment); 122 } 123 bool isLegalMaskedStore(Type *DataType, Align Alignment) { 124 return isLegalMaskedLoadStore(DataType, Alignment); 125 } 126 127 bool isLegalMaskedGatherScatter(Type *DataType, Align Alignment) { 128 if (!ST->hasVInstructions()) 129 return false; 130 131 // Only support fixed vectors if we know the minimum vector size. 132 if (isa<FixedVectorType>(DataType) && ST->getMinRVVVectorSizeInBits() == 0) 133 return false; 134 135 // Don't allow elements larger than the ELEN. 136 // FIXME: How to limit for scalable vectors? 137 if (isa<FixedVectorType>(DataType) && 138 DataType->getScalarSizeInBits() > ST->getMaxELENForFixedLengthVectors()) 139 return false; 140 141 if (Alignment < 142 DL.getTypeStoreSize(DataType->getScalarType()).getFixedSize()) 143 return false; 144 145 return TLI->isLegalElementTypeForRVV(DataType->getScalarType()); 146 } 147 148 bool isLegalMaskedGather(Type *DataType, Align Alignment) { 149 return isLegalMaskedGatherScatter(DataType, Alignment); 150 } 151 bool isLegalMaskedScatter(Type *DataType, Align Alignment) { 152 return isLegalMaskedGatherScatter(DataType, Alignment); 153 } 154 155 /// \returns How the target needs this vector-predicated operation to be 156 /// transformed. 157 TargetTransformInfo::VPLegalization 158 getVPLegalizationStrategy(const VPIntrinsic &PI) const { 159 using VPLegalization = TargetTransformInfo::VPLegalization; 160 return VPLegalization(VPLegalization::Legal, VPLegalization::Legal); 161 } 162 163 bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, 164 ElementCount VF) const { 165 if (!ST->hasVInstructions()) 166 return false; 167 168 if (!VF.isScalable()) 169 return true; 170 171 Type *Ty = RdxDesc.getRecurrenceType(); 172 if (!TLI->isLegalElementTypeForRVV(Ty)) 173 return false; 174 175 switch (RdxDesc.getRecurrenceKind()) { 176 case RecurKind::Add: 177 case RecurKind::FAdd: 178 case RecurKind::And: 179 case RecurKind::Or: 180 case RecurKind::Xor: 181 case RecurKind::SMin: 182 case RecurKind::SMax: 183 case RecurKind::UMin: 184 case RecurKind::UMax: 185 case RecurKind::FMin: 186 case RecurKind::FMax: 187 return true; 188 default: 189 return false; 190 } 191 } 192 193 unsigned getMaxInterleaveFactor(unsigned VF) { 194 // If the loop will not be vectorized, don't interleave the loop. 195 // Let regular unroll to unroll the loop. 196 return VF == 1 ? 1 : ST->getMaxInterleaveFactor(); 197 } 198 199 // TODO: We should define RISC-V's own register classes. 200 // e.g. register class for FPR. 201 unsigned getNumberOfRegisters(unsigned ClassID) const { 202 bool Vector = (ClassID == 1); 203 if (Vector) { 204 if (ST->hasVInstructions()) 205 return 32; 206 return 0; 207 } 208 // 31 = 32 GPR - x0 (zero register) 209 // FIXME: Should we exclude fixed registers like SP, TP or GP? 210 return 31; 211 } 212 }; 213 214 } // end namespace llvm 215 216 #endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H 217