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 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 isLegalMaskedLoadStore(Type *DataType, Align Alignment) { 109 if (!ST->hasVInstructions()) 110 return false; 111 112 // Only support fixed vectors if we know the minimum vector size. 113 if (isa<FixedVectorType>(DataType) && ST->getMinRVVVectorSizeInBits() == 0) 114 return false; 115 116 // Don't allow elements larger than the ELEN. 117 // FIXME: How to limit for scalable vectors? 118 if (isa<FixedVectorType>(DataType) && 119 DataType->getScalarSizeInBits() > ST->getELEN()) 120 return false; 121 122 if (Alignment < 123 DL.getTypeStoreSize(DataType->getScalarType()).getFixedSize()) 124 return false; 125 126 return TLI->isLegalElementTypeForRVV(DataType->getScalarType()); 127 } 128 129 bool isLegalMaskedLoad(Type *DataType, Align Alignment) { 130 return isLegalMaskedLoadStore(DataType, Alignment); 131 } 132 bool isLegalMaskedStore(Type *DataType, Align Alignment) { 133 return isLegalMaskedLoadStore(DataType, Alignment); 134 } 135 136 bool isLegalMaskedGatherScatter(Type *DataType, Align Alignment) { 137 if (!ST->hasVInstructions()) 138 return false; 139 140 // Only support fixed vectors if we know the minimum vector size. 141 if (isa<FixedVectorType>(DataType) && ST->getMinRVVVectorSizeInBits() == 0) 142 return false; 143 144 // Don't allow elements larger than the ELEN. 145 // FIXME: How to limit for scalable vectors? 146 if (isa<FixedVectorType>(DataType) && 147 DataType->getScalarSizeInBits() > ST->getELEN()) 148 return false; 149 150 if (Alignment < 151 DL.getTypeStoreSize(DataType->getScalarType()).getFixedSize()) 152 return false; 153 154 return TLI->isLegalElementTypeForRVV(DataType->getScalarType()); 155 } 156 157 bool isLegalMaskedGather(Type *DataType, Align Alignment) { 158 return isLegalMaskedGatherScatter(DataType, Alignment); 159 } 160 bool isLegalMaskedScatter(Type *DataType, Align Alignment) { 161 return isLegalMaskedGatherScatter(DataType, Alignment); 162 } 163 164 /// \returns How the target needs this vector-predicated operation to be 165 /// transformed. 166 TargetTransformInfo::VPLegalization 167 getVPLegalizationStrategy(const VPIntrinsic &PI) const { 168 using VPLegalization = TargetTransformInfo::VPLegalization; 169 return VPLegalization(VPLegalization::Legal, VPLegalization::Legal); 170 } 171 172 bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, 173 ElementCount VF) const { 174 if (!ST->hasVInstructions()) 175 return false; 176 177 if (!VF.isScalable()) 178 return true; 179 180 Type *Ty = RdxDesc.getRecurrenceType(); 181 if (!TLI->isLegalElementTypeForRVV(Ty)) 182 return false; 183 184 switch (RdxDesc.getRecurrenceKind()) { 185 case RecurKind::Add: 186 case RecurKind::FAdd: 187 case RecurKind::And: 188 case RecurKind::Or: 189 case RecurKind::Xor: 190 case RecurKind::SMin: 191 case RecurKind::SMax: 192 case RecurKind::UMin: 193 case RecurKind::UMax: 194 case RecurKind::FMin: 195 case RecurKind::FMax: 196 return true; 197 default: 198 return false; 199 } 200 } 201 202 unsigned getMaxInterleaveFactor(unsigned VF) { 203 // If the loop will not be vectorized, don't interleave the loop. 204 // Let regular unroll to unroll the loop. 205 return VF == 1 ? 1 : ST->getMaxInterleaveFactor(); 206 } 207 208 // TODO: We should define RISC-V's own register classes. 209 // e.g. register class for FPR. 210 unsigned getNumberOfRegisters(unsigned ClassID) const { 211 bool Vector = (ClassID == 1); 212 if (Vector) { 213 if (ST->hasVInstructions()) 214 return 32; 215 return 0; 216 } 217 // 31 = 32 GPR - x0 (zero register) 218 // FIXME: Should we exclude fixed registers like SP, TP or GP? 219 return 31; 220 } 221 }; 222 223 } // end namespace llvm 224 225 #endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H 226