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