507 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// This file defines a TargetTransformInfoImplBase conforming object specific10/// to the RISC-V target machine. It uses the target's detailed information to11/// provide more precise answers to certain TTI queries, while letting the12/// target independent and default TTI implementations handle the rest.13///14//===----------------------------------------------------------------------===//15 16#ifndef LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H17#define LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H18 19#include "RISCVSubtarget.h"20#include "RISCVTargetMachine.h"21#include "llvm/Analysis/TargetTransformInfo.h"22#include "llvm/CodeGen/BasicTTIImpl.h"23#include "llvm/IR/Function.h"24#include <optional>25 26namespace llvm {27 28class RISCVTTIImpl final : 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 /// This function returns an estimate for VL to be used in VL based terms41 /// of the cost model. For fixed length vectors, this is simply the42 /// vector length. For scalable vectors, we return results consistent43 /// with getVScaleForTuning under the assumption that clients are also44 /// using that when comparing costs between scalar and vector representation.45 /// This does unfortunately mean that we can both undershoot and overshot46 /// the true cost significantly if getVScaleForTuning is wildly off for the47 /// actual target hardware.48 unsigned getEstimatedVLFor(VectorType *Ty) const;49 50 /// This function calculates the costs for one or more RVV opcodes based51 /// on the vtype and the cost kind.52 /// \param Opcodes A list of opcodes of the RVV instruction to evaluate.53 /// \param VT The MVT of vtype associated with the RVV instructions.54 /// For widening/narrowing instructions where the result and source types55 /// differ, it is important to check the spec to determine whether the vtype56 /// refers to the result or source type.57 /// \param CostKind The type of cost to compute.58 InstructionCost getRISCVInstructionCost(ArrayRef<unsigned> OpCodes, MVT VT,59 TTI::TargetCostKind CostKind) const;60 61 /// Return the cost of accessing a constant pool entry of the specified62 /// type.63 InstructionCost getConstantPoolLoadCost(Type *Ty,64 TTI::TargetCostKind CostKind) const;65 66 /// If this shuffle can be lowered as a masked slide pair (at worst),67 /// return a cost for it.68 InstructionCost getSlideCost(FixedVectorType *Tp, ArrayRef<int> Mask,69 TTI::TargetCostKind CostKind) const;70 71public:72 explicit RISCVTTIImpl(const RISCVTargetMachine *TM, const Function &F)73 : BaseT(TM, F.getDataLayout()), ST(TM->getSubtargetImpl(F)),74 TLI(ST->getTargetLowering()) {}75 76 /// Return the cost of materializing an immediate for a value operand of77 /// a store instruction.78 InstructionCost getStoreImmCost(Type *VecTy, TTI::OperandValueInfo OpInfo,79 TTI::TargetCostKind CostKind) const;80 81 InstructionCost getIntImmCost(const APInt &Imm, Type *Ty,82 TTI::TargetCostKind CostKind) const override;83 InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx,84 const APInt &Imm, Type *Ty,85 TTI::TargetCostKind CostKind,86 Instruction *Inst = nullptr) const override;87 InstructionCost88 getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,89 Type *Ty, TTI::TargetCostKind CostKind) const override;90 91 /// \name EVL Support for predicated vectorization.92 /// Whether the target supports the %evl parameter of VP intrinsic efficiently93 /// in hardware. (see LLVM Language Reference - "Vector Predication94 /// Intrinsics",95 /// https://llvm.org/docs/LangRef.html#vector-predication-intrinsics and96 /// "IR-level VP intrinsics",97 /// https://llvm.org/docs/Proposals/VectorPredication.html#ir-level-vp-intrinsics).98 bool hasActiveVectorLength() const override;99 100 TargetTransformInfo::PopcntSupportKind101 getPopcntSupport(unsigned TyWidth) const override;102 103 InstructionCost getPartialReductionCost(104 unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,105 ElementCount VF, TTI::PartialReductionExtendKind OpAExtend,106 TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,107 TTI::TargetCostKind CostKind) const override;108 109 bool shouldExpandReduction(const IntrinsicInst *II) const override;110 bool supportsScalableVectors() const override {111 return ST->hasVInstructions();112 }113 bool enableOrderedReductions() const override { return true; }114 bool enableScalableVectorization() const override {115 return ST->hasVInstructions();116 }117 bool preferPredicateOverEpilogue(TailFoldingInfo *TFI) const override {118 return ST->hasVInstructions();119 }120 TailFoldingStyle121 getPreferredTailFoldingStyle(bool IVUpdateMayOverflow) const override {122 return ST->hasVInstructions() ? TailFoldingStyle::DataWithEVL123 : TailFoldingStyle::None;124 }125 std::optional<unsigned> getMaxVScale() const override;126 std::optional<unsigned> getVScaleForTuning() const override;127 128 TypeSize129 getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override;130 131 unsigned getRegUsageForType(Type *Ty) const override;132 133 unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const override;134 135 bool preferAlternateOpcodeVectorization() const override;136 137 bool preferEpilogueVectorization() const override {138 // Epilogue vectorization is usually unprofitable - tail folding or139 // a smaller VF would have been better. This a blunt hammer - we140 // should re-examine this once vectorization is better tuned.141 return false;142 }143 144 bool shouldConsiderVectorizationRegPressure() const override { return true; }145 146 InstructionCost147 getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA,148 TTI::TargetCostKind CostKind) const override;149 150 InstructionCost151 getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA,152 TTI::TargetCostKind CostKind) const override;153 154 InstructionCost155 getPointersChainCost(ArrayRef<const Value *> Ptrs, const Value *Base,156 const TTI::PointersChainInfo &Info, Type *AccessTy,157 TTI::TargetCostKind CostKind) const override;158 159 void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,160 TTI::UnrollingPreferences &UP,161 OptimizationRemarkEmitter *ORE) const override;162 163 void getPeelingPreferences(Loop *L, ScalarEvolution &SE,164 TTI::PeelingPreferences &PP) const override;165 166 bool getTgtMemIntrinsic(IntrinsicInst *Inst,167 MemIntrinsicInfo &Info) const override;168 169 unsigned getMinVectorRegisterBitWidth() const override {170 return ST->useRVVForFixedLengthVectors() ? 16 : 0;171 }172 173 InstructionCost174 getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,175 ArrayRef<int> Mask, TTI::TargetCostKind CostKind, int Index,176 VectorType *SubTp, ArrayRef<const Value *> Args = {},177 const Instruction *CxtI = nullptr) const override;178 179 InstructionCost getScalarizationOverhead(180 VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,181 TTI::TargetCostKind CostKind, bool ForPoisonSrc = true,182 ArrayRef<Value *> VL = {}) const override;183 184 InstructionCost185 getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,186 TTI::TargetCostKind CostKind) const override;187 188 InstructionCost189 getAddressComputationCost(Type *PTy, ScalarEvolution *SE, const SCEV *Ptr,190 TTI::TargetCostKind CostKind) const override;191 192 InstructionCost getInterleavedMemoryOpCost(193 unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,194 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,195 bool UseMaskForCond = false, bool UseMaskForGaps = false) const override;196 197 InstructionCost getGatherScatterOpCost(unsigned Opcode, Type *DataTy,198 const Value *Ptr, bool VariableMask,199 Align Alignment,200 TTI::TargetCostKind CostKind,201 const Instruction *I) const override;202 203 InstructionCost204 getExpandCompressMemoryOpCost(const MemIntrinsicCostAttributes &MICA,205 TTI::TargetCostKind CostKind) const override;206 207 InstructionCost getStridedMemoryOpCost(unsigned Opcode, Type *DataTy,208 const Value *Ptr, bool VariableMask,209 Align Alignment,210 TTI::TargetCostKind CostKind,211 const Instruction *I) const override;212 213 InstructionCost214 getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const override;215 216 InstructionCost217 getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,218 TTI::CastContextHint CCH, TTI::TargetCostKind CostKind,219 const Instruction *I = nullptr) const override;220 221 InstructionCost222 getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF,223 TTI::TargetCostKind CostKind) const override;224 225 InstructionCost226 getArithmeticReductionCost(unsigned Opcode, VectorType *Ty,227 std::optional<FastMathFlags> FMF,228 TTI::TargetCostKind CostKind) const override;229 230 InstructionCost231 getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy,232 VectorType *ValTy, std::optional<FastMathFlags> FMF,233 TTI::TargetCostKind CostKind) const override;234 235 InstructionCost getMemoryOpCost(236 unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace,237 TTI::TargetCostKind CostKind,238 TTI::OperandValueInfo OpdInfo = {TTI::OK_AnyValue, TTI::OP_None},239 const Instruction *I = nullptr) const override;240 241 InstructionCost getCmpSelInstrCost(242 unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,243 TTI::TargetCostKind CostKind,244 TTI::OperandValueInfo Op1Info = {TTI::OK_AnyValue, TTI::OP_None},245 TTI::OperandValueInfo Op2Info = {TTI::OK_AnyValue, TTI::OP_None},246 const Instruction *I = nullptr) const override;247 248 InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind,249 const Instruction *I = nullptr) const override;250 251 using BaseT::getVectorInstrCost;252 InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val,253 TTI::TargetCostKind CostKind,254 unsigned Index, const Value *Op0,255 const Value *Op1) const override;256 257 InstructionCost258 getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val,259 TTI::TargetCostKind CostKind,260 unsigned Index) const override;261 262 InstructionCost getArithmeticInstrCost(263 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,264 TTI::OperandValueInfo Op1Info = {TTI::OK_AnyValue, TTI::OP_None},265 TTI::OperandValueInfo Op2Info = {TTI::OK_AnyValue, TTI::OP_None},266 ArrayRef<const Value *> Args = {},267 const Instruction *CxtI = nullptr) const override;268 269 bool isElementTypeLegalForScalableVector(Type *Ty) const override {270 return TLI->isLegalElementTypeForRVV(TLI->getValueType(DL, Ty));271 }272 273 bool isLegalMaskedLoadStore(Type *DataType, Align Alignment) const {274 if (!ST->hasVInstructions())275 return false;276 277 EVT DataTypeVT = TLI->getValueType(DL, DataType);278 279 // Only support fixed vectors if we know the minimum vector size.280 if (DataTypeVT.isFixedLengthVector() && !ST->useRVVForFixedLengthVectors())281 return false;282 283 EVT ElemType = DataTypeVT.getScalarType();284 if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())285 return false;286 287 return TLI->isLegalElementTypeForRVV(ElemType);288 }289 290 bool isLegalMaskedLoad(Type *DataType, Align Alignment,291 unsigned /*AddressSpace*/,292 TTI::MaskKind /*MaskKind*/) const override {293 return isLegalMaskedLoadStore(DataType, Alignment);294 }295 bool isLegalMaskedStore(Type *DataType, Align Alignment,296 unsigned /*AddressSpace*/,297 TTI::MaskKind /*MaskKind*/) const override {298 return isLegalMaskedLoadStore(DataType, Alignment);299 }300 301 bool isLegalMaskedGatherScatter(Type *DataType, Align Alignment) const {302 if (!ST->hasVInstructions())303 return false;304 305 EVT DataTypeVT = TLI->getValueType(DL, DataType);306 307 // Only support fixed vectors if we know the minimum vector size.308 if (DataTypeVT.isFixedLengthVector() && !ST->useRVVForFixedLengthVectors())309 return false;310 311 // We also need to check if the vector of address is valid.312 EVT PointerTypeVT = EVT(TLI->getPointerTy(DL));313 if (DataTypeVT.isScalableVector() &&314 !TLI->isLegalElementTypeForRVV(PointerTypeVT))315 return false;316 317 EVT ElemType = DataTypeVT.getScalarType();318 if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())319 return false;320 321 return TLI->isLegalElementTypeForRVV(ElemType);322 }323 324 bool isLegalMaskedGather(Type *DataType, Align Alignment) const override {325 return isLegalMaskedGatherScatter(DataType, Alignment);326 }327 bool isLegalMaskedScatter(Type *DataType, Align Alignment) const override {328 return isLegalMaskedGatherScatter(DataType, Alignment);329 }330 331 bool forceScalarizeMaskedGather(VectorType *VTy,332 Align Alignment) const override {333 // Scalarize masked gather for RV64 if EEW=64 indices aren't supported.334 return ST->is64Bit() && !ST->hasVInstructionsI64();335 }336 337 bool forceScalarizeMaskedScatter(VectorType *VTy,338 Align Alignment) const override {339 // Scalarize masked scatter for RV64 if EEW=64 indices aren't supported.340 return ST->is64Bit() && !ST->hasVInstructionsI64();341 }342 343 bool isLegalStridedLoadStore(Type *DataType, Align Alignment) const override {344 EVT DataTypeVT = TLI->getValueType(DL, DataType);345 return TLI->isLegalStridedLoadStore(DataTypeVT, Alignment);346 }347 348 bool isLegalInterleavedAccessType(VectorType *VTy, unsigned Factor,349 Align Alignment,350 unsigned AddrSpace) const override {351 return TLI->isLegalInterleavedAccessType(VTy, Factor, Alignment, AddrSpace,352 DL);353 }354 355 bool isLegalMaskedExpandLoad(Type *DataType, Align Alignment) const override;356 357 bool isLegalMaskedCompressStore(Type *DataTy, Align Alignment) const override;358 359 bool isVScaleKnownToBeAPowerOfTwo() const override {360 return TLI->isVScaleKnownToBeAPowerOfTwo();361 }362 363 /// \returns How the target needs this vector-predicated operation to be364 /// transformed.365 TargetTransformInfo::VPLegalization366 getVPLegalizationStrategy(const VPIntrinsic &PI) const override {367 using VPLegalization = TargetTransformInfo::VPLegalization;368 if (!ST->hasVInstructions() ||369 (PI.getIntrinsicID() == Intrinsic::vp_reduce_mul &&370 cast<VectorType>(PI.getArgOperand(1)->getType())371 ->getElementType()372 ->getIntegerBitWidth() != 1))373 return VPLegalization(VPLegalization::Discard, VPLegalization::Convert);374 return VPLegalization(VPLegalization::Legal, VPLegalization::Legal);375 }376 377 bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc,378 ElementCount VF) const override {379 if (!VF.isScalable())380 return true;381 382 Type *Ty = RdxDesc.getRecurrenceType();383 if (!TLI->isLegalElementTypeForRVV(TLI->getValueType(DL, Ty)))384 return false;385 386 switch (RdxDesc.getRecurrenceKind()) {387 case RecurKind::Add:388 case RecurKind::Sub:389 case RecurKind::AddChainWithSubs:390 case RecurKind::And:391 case RecurKind::Or:392 case RecurKind::Xor:393 case RecurKind::SMin:394 case RecurKind::SMax:395 case RecurKind::UMin:396 case RecurKind::UMax:397 case RecurKind::FMin:398 case RecurKind::FMax:399 return true;400 case RecurKind::AnyOf:401 case RecurKind::FAdd:402 case RecurKind::FMulAdd:403 // We can't promote f16/bf16 fadd reductions and scalable vectors can't be404 // expanded.405 if (Ty->isBFloatTy() || (Ty->isHalfTy() && !ST->hasVInstructionsF16()))406 return false;407 return true;408 default:409 return false;410 }411 }412 413 unsigned getMaxInterleaveFactor(ElementCount VF) const override {414 // Don't interleave if the loop has been vectorized with scalable vectors.415 if (VF.isScalable())416 return 1;417 // If the loop will not be vectorized, don't interleave the loop.418 // Let regular unroll to unroll the loop.419 return VF.isScalar() ? 1 : ST->getMaxInterleaveFactor();420 }421 422 bool enableInterleavedAccessVectorization() const override { return true; }423 424 bool enableMaskedInterleavedAccessVectorization() const override {425 return ST->hasVInstructions();426 }427 428 unsigned getMinTripCountTailFoldingThreshold() const override;429 430 enum RISCVRegisterClass { GPRRC, FPRRC, VRRC };431 unsigned getNumberOfRegisters(unsigned ClassID) const override {432 switch (ClassID) {433 case RISCVRegisterClass::GPRRC:434 // 31 = 32 GPR - x0 (zero register)435 // FIXME: Should we exclude fixed registers like SP, TP or GP?436 return 31;437 case RISCVRegisterClass::FPRRC:438 if (ST->hasStdExtF())439 return 32;440 return 0;441 case RISCVRegisterClass::VRRC:442 // Although there are 32 vector registers, v0 is special in that it is the443 // only register that can be used to hold a mask.444 // FIXME: Should we conservatively return 31 as the number of usable445 // vector registers?446 return ST->hasVInstructions() ? 32 : 0;447 }448 llvm_unreachable("unknown register class");449 }450 451 TTI::AddressingModeKind452 getPreferredAddressingMode(const Loop *L, ScalarEvolution *SE) const override;453 454 unsigned getRegisterClassForType(bool Vector,455 Type *Ty = nullptr) const override {456 if (Vector)457 return RISCVRegisterClass::VRRC;458 if (!Ty)459 return RISCVRegisterClass::GPRRC;460 461 Type *ScalarTy = Ty->getScalarType();462 if ((ScalarTy->isHalfTy() && ST->hasStdExtZfhmin()) ||463 (ScalarTy->isFloatTy() && ST->hasStdExtF()) ||464 (ScalarTy->isDoubleTy() && ST->hasStdExtD())) {465 return RISCVRegisterClass::FPRRC;466 }467 468 return RISCVRegisterClass::GPRRC;469 }470 471 const char *getRegisterClassName(unsigned ClassID) const override {472 switch (ClassID) {473 case RISCVRegisterClass::GPRRC:474 return "RISCV::GPRRC";475 case RISCVRegisterClass::FPRRC:476 return "RISCV::FPRRC";477 case RISCVRegisterClass::VRRC:478 return "RISCV::VRRC";479 }480 llvm_unreachable("unknown register class");481 }482 483 bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1,484 const TargetTransformInfo::LSRCost &C2) const override;485 486 bool shouldConsiderAddressTypePromotion(487 const Instruction &I,488 bool &AllowPromotionWithoutCommonHeader) const override;489 std::optional<unsigned> getMinPageSize() const override { return 4096; }490 /// Return true if the (vector) instruction I will be lowered to an491 /// instruction with a scalar splat operand for the given Operand number.492 bool canSplatOperand(Instruction *I, int Operand) const;493 /// Return true if a vector instruction will lower to a target instruction494 /// able to splat the given operand.495 bool canSplatOperand(unsigned Opcode, int Operand) const;496 497 bool isProfitableToSinkOperands(Instruction *I,498 SmallVectorImpl<Use *> &Ops) const override;499 500 TTI::MemCmpExpansionOptions501 enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override;502};503 504} // end namespace llvm505 506#endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H507