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