1 //===-- RISCVTargetTransformInfo.cpp - RISC-V specific TTI ----------------===// 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 9 #include "RISCVTargetTransformInfo.h" 10 #include "MCTargetDesc/RISCVMatInt.h" 11 #include "llvm/Analysis/TargetTransformInfo.h" 12 #include "llvm/CodeGen/BasicTTIImpl.h" 13 #include "llvm/CodeGen/TargetLowering.h" 14 using namespace llvm; 15 16 #define DEBUG_TYPE "riscvtti" 17 18 InstructionCost RISCVTTIImpl::getIntImmCost(const APInt &Imm, Type *Ty, 19 TTI::TargetCostKind CostKind) { 20 assert(Ty->isIntegerTy() && 21 "getIntImmCost can only estimate cost of materialising integers"); 22 23 // We have a Zero register, so 0 is always free. 24 if (Imm == 0) 25 return TTI::TCC_Free; 26 27 // Otherwise, we check how many instructions it will take to materialise. 28 const DataLayout &DL = getDataLayout(); 29 return RISCVMatInt::getIntMatCost(Imm, DL.getTypeSizeInBits(Ty), 30 getST()->is64Bit()); 31 } 32 33 InstructionCost RISCVTTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx, 34 const APInt &Imm, Type *Ty, 35 TTI::TargetCostKind CostKind, 36 Instruction *Inst) { 37 assert(Ty->isIntegerTy() && 38 "getIntImmCost can only estimate cost of materialising integers"); 39 40 // We have a Zero register, so 0 is always free. 41 if (Imm == 0) 42 return TTI::TCC_Free; 43 44 // Some instructions in RISC-V can take a 12-bit immediate. Some of these are 45 // commutative, in others the immediate comes from a specific argument index. 46 bool Takes12BitImm = false; 47 unsigned ImmArgIdx = ~0U; 48 49 switch (Opcode) { 50 case Instruction::GetElementPtr: 51 // Never hoist any arguments to a GetElementPtr. CodeGenPrepare will 52 // split up large offsets in GEP into better parts than ConstantHoisting 53 // can. 54 return TTI::TCC_Free; 55 case Instruction::Add: 56 case Instruction::And: 57 case Instruction::Or: 58 case Instruction::Xor: 59 case Instruction::Mul: 60 Takes12BitImm = true; 61 break; 62 case Instruction::Sub: 63 case Instruction::Shl: 64 case Instruction::LShr: 65 case Instruction::AShr: 66 Takes12BitImm = true; 67 ImmArgIdx = 1; 68 break; 69 default: 70 break; 71 } 72 73 if (Takes12BitImm) { 74 // Check immediate is the correct argument... 75 if (Instruction::isCommutative(Opcode) || Idx == ImmArgIdx) { 76 // ... and fits into the 12-bit immediate. 77 if (Imm.getMinSignedBits() <= 64 && 78 getTLI()->isLegalAddImmediate(Imm.getSExtValue())) { 79 return TTI::TCC_Free; 80 } 81 } 82 83 // Otherwise, use the full materialisation cost. 84 return getIntImmCost(Imm, Ty, CostKind); 85 } 86 87 // By default, prevent hoisting. 88 return TTI::TCC_Free; 89 } 90 91 InstructionCost 92 RISCVTTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, 93 const APInt &Imm, Type *Ty, 94 TTI::TargetCostKind CostKind) { 95 // Prevent hoisting in unknown cases. 96 return TTI::TCC_Free; 97 } 98 99 TargetTransformInfo::PopcntSupportKind 100 RISCVTTIImpl::getPopcntSupport(unsigned TyWidth) { 101 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2"); 102 return ST->hasStdExtZbb() ? TTI::PSK_FastHardware : TTI::PSK_Software; 103 } 104 105 bool RISCVTTIImpl::shouldExpandReduction(const IntrinsicInst *II) const { 106 // Currently, the ExpandReductions pass can't expand scalable-vector 107 // reductions, but we still request expansion as RVV doesn't support certain 108 // reductions and the SelectionDAG can't legalize them either. 109 switch (II->getIntrinsicID()) { 110 default: 111 return false; 112 // These reductions have no equivalent in RVV 113 case Intrinsic::vector_reduce_mul: 114 case Intrinsic::vector_reduce_fmul: 115 // The fmin and fmax intrinsics are not currently supported due to a 116 // discrepancy between the LLVM semantics and the RVV 0.10 ISA behaviour with 117 // regards to signaling NaNs: the vector fmin/fmax reduction intrinsics match 118 // the behaviour minnum/maxnum intrinsics, whereas the vfredmin/vfredmax 119 // instructions match the vfmin/vfmax instructions which match the equivalent 120 // scalar fmin/fmax instructions as defined in 2.2 F/D/Q extension (see 121 // https://bugs.llvm.org/show_bug.cgi?id=27363). 122 // This behaviour is likely fixed in version 2.3 of the RISC-V F/D/Q 123 // extension, where fmin/fmax behave like minnum/maxnum, but until then the 124 // intrinsics are left unsupported. 125 case Intrinsic::vector_reduce_fmax: 126 case Intrinsic::vector_reduce_fmin: 127 return true; 128 } 129 } 130 131 Optional<unsigned> RISCVTTIImpl::getMaxVScale() const { 132 // There is no assumption of the maximum vector length in V specification. 133 // We use the value specified by users as the maximum vector length. 134 // This function will use the assumed maximum vector length to get the 135 // maximum vscale for LoopVectorizer. 136 // If users do not specify the maximum vector length, we have no way to 137 // know whether the LoopVectorizer is safe to do or not. 138 // We only consider to use single vector register (LMUL = 1) to vectorize. 139 unsigned MaxVectorSizeInBits = ST->getMaxRVVVectorSizeInBits(); 140 if (ST->hasStdExtV() && MaxVectorSizeInBits != 0) 141 return MaxVectorSizeInBits / RISCV::RVVBitsPerBlock; 142 return BaseT::getMaxVScale(); 143 } 144 145 InstructionCost RISCVTTIImpl::getGatherScatterOpCost( 146 unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask, 147 Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) { 148 if (CostKind != TTI::TCK_RecipThroughput) 149 return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask, 150 Alignment, CostKind, I); 151 152 if ((Opcode == Instruction::Load && 153 !isLegalMaskedGather(DataTy, Align(Alignment))) || 154 (Opcode == Instruction::Store && 155 !isLegalMaskedScatter(DataTy, Align(Alignment)))) 156 return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask, 157 Alignment, CostKind, I); 158 159 // FIXME: Only supporting fixed vectors for now. 160 if (!isa<FixedVectorType>(DataTy)) 161 return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask, 162 Alignment, CostKind, I); 163 164 auto *VTy = cast<FixedVectorType>(DataTy); 165 unsigned NumLoads = VTy->getNumElements(); 166 InstructionCost MemOpCost = 167 getMemoryOpCost(Opcode, VTy->getElementType(), Alignment, 0, CostKind, I); 168 return NumLoads * MemOpCost; 169 } 170