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