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 unsigned getMaxVLFor(VectorType *Ty); 41 public: 42 explicit RISCVTTIImpl(const RISCVTargetMachine *TM, const Function &F) 43 : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), 44 TLI(ST->getTargetLowering()) {} 45 46 InstructionCost getIntImmCost(const APInt &Imm, Type *Ty, 47 TTI::TargetCostKind CostKind); 48 InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, 49 const APInt &Imm, Type *Ty, 50 TTI::TargetCostKind CostKind, 51 Instruction *Inst = nullptr); 52 InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, 53 const APInt &Imm, Type *Ty, 54 TTI::TargetCostKind CostKind); 55 56 TargetTransformInfo::PopcntSupportKind getPopcntSupport(unsigned TyWidth); 57 58 bool shouldExpandReduction(const IntrinsicInst *II) const; 59 bool supportsScalableVectors() const { return ST->hasVInstructions(); } 60 Optional<unsigned> getMaxVScale() const; 61 Optional<unsigned> getVScaleForTuning() const; 62 63 TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const; 64 65 unsigned getRegUsageForType(Type *Ty); 66 67 InstructionCost getMaskedMemoryOpCost(unsigned Opcode, Type *Src, 68 Align Alignment, unsigned AddressSpace, 69 TTI::TargetCostKind CostKind); 70 71 void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, 72 TTI::UnrollingPreferences &UP, 73 OptimizationRemarkEmitter *ORE); 74 75 void getPeelingPreferences(Loop *L, ScalarEvolution &SE, 76 TTI::PeelingPreferences &PP); 77 78 unsigned getMinVectorRegisterBitWidth() const { 79 return ST->useRVVForFixedLengthVectors() ? 16 : 0; 80 } 81 82 InstructionCost getSpliceCost(VectorType *Tp, int Index); 83 InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *Tp, 84 ArrayRef<int> Mask, int Index, 85 VectorType *SubTp, 86 ArrayRef<const Value *> Args = None); 87 88 InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, 89 TTI::TargetCostKind CostKind); 90 91 InstructionCost getGatherScatterOpCost(unsigned Opcode, Type *DataTy, 92 const Value *Ptr, bool VariableMask, 93 Align Alignment, 94 TTI::TargetCostKind CostKind, 95 const Instruction *I); 96 97 InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, 98 TTI::CastContextHint CCH, 99 TTI::TargetCostKind CostKind, 100 const Instruction *I = nullptr); 101 102 InstructionCost getMinMaxReductionCost(VectorType *Ty, VectorType *CondTy, 103 bool IsUnsigned, 104 TTI::TargetCostKind CostKind); 105 106 InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, 107 Optional<FastMathFlags> FMF, 108 TTI::TargetCostKind CostKind); 109 110 bool isElementTypeLegalForScalableVector(Type *Ty) const { 111 return TLI->isLegalElementTypeForRVV(Ty); 112 } 113 114 bool isLegalMaskedLoadStore(Type *DataType, Align Alignment) { 115 if (!ST->hasVInstructions()) 116 return false; 117 118 // Only support fixed vectors if we know the minimum vector size. 119 if (isa<FixedVectorType>(DataType) && !ST->useRVVForFixedLengthVectors()) 120 return false; 121 122 // Don't allow elements larger than the ELEN. 123 // FIXME: How to limit for scalable vectors? 124 if (isa<FixedVectorType>(DataType) && 125 DataType->getScalarSizeInBits() > ST->getELEN()) 126 return false; 127 128 if (Alignment < 129 DL.getTypeStoreSize(DataType->getScalarType()).getFixedSize()) 130 return false; 131 132 return TLI->isLegalElementTypeForRVV(DataType->getScalarType()); 133 } 134 135 bool isLegalMaskedLoad(Type *DataType, Align Alignment) { 136 return isLegalMaskedLoadStore(DataType, Alignment); 137 } 138 bool isLegalMaskedStore(Type *DataType, Align Alignment) { 139 return isLegalMaskedLoadStore(DataType, Alignment); 140 } 141 142 bool isLegalMaskedGatherScatter(Type *DataType, Align Alignment) { 143 if (!ST->hasVInstructions()) 144 return false; 145 146 // Only support fixed vectors if we know the minimum vector size. 147 if (isa<FixedVectorType>(DataType) && !ST->useRVVForFixedLengthVectors()) 148 return false; 149 150 // Don't allow elements larger than the ELEN. 151 // FIXME: How to limit for scalable vectors? 152 if (isa<FixedVectorType>(DataType) && 153 DataType->getScalarSizeInBits() > ST->getELEN()) 154 return false; 155 156 if (Alignment < 157 DL.getTypeStoreSize(DataType->getScalarType()).getFixedSize()) 158 return false; 159 160 return TLI->isLegalElementTypeForRVV(DataType->getScalarType()); 161 } 162 163 bool isLegalMaskedGather(Type *DataType, Align Alignment) { 164 return isLegalMaskedGatherScatter(DataType, Alignment); 165 } 166 bool isLegalMaskedScatter(Type *DataType, Align Alignment) { 167 return isLegalMaskedGatherScatter(DataType, Alignment); 168 } 169 170 bool forceScalarizeMaskedGather(VectorType *VTy, Align Alignment) { 171 // Scalarize masked gather for RV64 if EEW=64 indices aren't supported. 172 return ST->is64Bit() && !ST->hasVInstructionsI64(); 173 } 174 175 bool forceScalarizeMaskedScatter(VectorType *VTy, Align Alignment) { 176 // Scalarize masked scatter for RV64 if EEW=64 indices aren't supported. 177 return ST->is64Bit() && !ST->hasVInstructionsI64(); 178 } 179 180 /// \returns How the target needs this vector-predicated operation to be 181 /// transformed. 182 TargetTransformInfo::VPLegalization 183 getVPLegalizationStrategy(const VPIntrinsic &PI) const { 184 using VPLegalization = TargetTransformInfo::VPLegalization; 185 return VPLegalization(VPLegalization::Legal, VPLegalization::Legal); 186 } 187 188 bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, 189 ElementCount VF) const { 190 if (!VF.isScalable()) 191 return true; 192 193 Type *Ty = RdxDesc.getRecurrenceType(); 194 if (!TLI->isLegalElementTypeForRVV(Ty)) 195 return false; 196 197 switch (RdxDesc.getRecurrenceKind()) { 198 case RecurKind::Add: 199 case RecurKind::FAdd: 200 case RecurKind::And: 201 case RecurKind::Or: 202 case RecurKind::Xor: 203 case RecurKind::SMin: 204 case RecurKind::SMax: 205 case RecurKind::UMin: 206 case RecurKind::UMax: 207 case RecurKind::FMin: 208 case RecurKind::FMax: 209 return true; 210 default: 211 return false; 212 } 213 } 214 215 unsigned getMaxInterleaveFactor(unsigned VF) { 216 // If the loop will not be vectorized, don't interleave the loop. 217 // Let regular unroll to unroll the loop. 218 return VF == 1 ? 1 : ST->getMaxInterleaveFactor(); 219 } 220 221 enum RISCVRegisterClass { GPRRC, FPRRC, VRRC }; 222 unsigned getNumberOfRegisters(unsigned ClassID) const { 223 switch (ClassID) { 224 case RISCVRegisterClass::GPRRC: 225 // 31 = 32 GPR - x0 (zero register) 226 // FIXME: Should we exclude fixed registers like SP, TP or GP? 227 return 31; 228 case RISCVRegisterClass::FPRRC: 229 if (ST->hasStdExtF()) 230 return 32; 231 return 0; 232 case RISCVRegisterClass::VRRC: 233 // Although there are 32 vector registers, v0 is special in that it is the 234 // only register that can be used to hold a mask. 235 // FIXME: Should we conservatively return 31 as the number of usable 236 // vector registers? 237 return ST->hasVInstructions() ? 32 : 0; 238 } 239 llvm_unreachable("unknown register class"); 240 } 241 242 unsigned getRegisterClassForType(bool Vector, Type *Ty = nullptr) const { 243 if (Vector) 244 return RISCVRegisterClass::VRRC; 245 if (!Ty) 246 return RISCVRegisterClass::GPRRC; 247 248 Type *ScalarTy = Ty->getScalarType(); 249 if ((ScalarTy->isHalfTy() && ST->hasStdExtZfh()) || 250 (ScalarTy->isFloatTy() && ST->hasStdExtF()) || 251 (ScalarTy->isDoubleTy() && ST->hasStdExtD())) { 252 return RISCVRegisterClass::FPRRC; 253 } 254 255 return RISCVRegisterClass::GPRRC; 256 } 257 258 const char *getRegisterClassName(unsigned ClassID) const { 259 switch (ClassID) { 260 case RISCVRegisterClass::GPRRC: 261 return "RISCV::GPRRC"; 262 case RISCVRegisterClass::FPRRC: 263 return "RISCV::FPRRC"; 264 case RISCVRegisterClass::VRRC: 265 return "RISCV::VRRC"; 266 } 267 llvm_unreachable("unknown register class"); 268 } 269 }; 270 271 } // end namespace llvm 272 273 #endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H 274