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
getIntImmCost(const APInt & Imm,Type * Ty,TTI::TargetCostKind CostKind)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()->getFeatureBits());
31 }
32
getIntImmCostInst(unsigned Opcode,unsigned Idx,const APInt & Imm,Type * Ty,TTI::TargetCostKind CostKind,Instruction * Inst)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
getIntImmCostIntrin(Intrinsic::ID IID,unsigned Idx,const APInt & Imm,Type * Ty,TTI::TargetCostKind CostKind)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
getPopcntSupport(unsigned TyWidth)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
shouldExpandReduction(const IntrinsicInst * II) const105 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 return true;
116 }
117 }
118
getMaxVScale() const119 Optional<unsigned> RISCVTTIImpl::getMaxVScale() const {
120 // There is no assumption of the maximum vector length in V specification.
121 // We use the value specified by users as the maximum vector length.
122 // This function will use the assumed maximum vector length to get the
123 // maximum vscale for LoopVectorizer.
124 // If users do not specify the maximum vector length, we have no way to
125 // know whether the LoopVectorizer is safe to do or not.
126 // We only consider to use single vector register (LMUL = 1) to vectorize.
127 unsigned MaxVectorSizeInBits = ST->getMaxRVVVectorSizeInBits();
128 if (ST->hasStdExtV() && MaxVectorSizeInBits != 0)
129 return MaxVectorSizeInBits / RISCV::RVVBitsPerBlock;
130 return BaseT::getMaxVScale();
131 }
132
getGatherScatterOpCost(unsigned Opcode,Type * DataTy,const Value * Ptr,bool VariableMask,Align Alignment,TTI::TargetCostKind CostKind,const Instruction * I)133 InstructionCost RISCVTTIImpl::getGatherScatterOpCost(
134 unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask,
135 Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) {
136 if (CostKind != TTI::TCK_RecipThroughput)
137 return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask,
138 Alignment, CostKind, I);
139
140 if ((Opcode == Instruction::Load &&
141 !isLegalMaskedGather(DataTy, Align(Alignment))) ||
142 (Opcode == Instruction::Store &&
143 !isLegalMaskedScatter(DataTy, Align(Alignment))))
144 return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask,
145 Alignment, CostKind, I);
146
147 // FIXME: Only supporting fixed vectors for now.
148 if (!isa<FixedVectorType>(DataTy))
149 return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask,
150 Alignment, CostKind, I);
151
152 auto *VTy = cast<FixedVectorType>(DataTy);
153 unsigned NumLoads = VTy->getNumElements();
154 InstructionCost MemOpCost =
155 getMemoryOpCost(Opcode, VTy->getElementType(), Alignment, 0, CostKind, I);
156 return NumLoads * MemOpCost;
157 }
158