LLVM 24.0.0git
SLPCostAnalysis.cpp
Go to the documentation of this file.
1//===- SLPCostAnalysis.cpp - SLP Vectorizer free cost helpers -------------===//
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 "SLPCostAnalysis.h"
10#include "SLPTypeUtils.h"
11#include "SLPUtils.h"
12
13#include "llvm/ADT/APInt.h"
14#include "llvm/ADT/STLExtras.h"
15#include "llvm/ADT/Sequence.h"
19#include "llvm/IR/Operator.h"
20#include "llvm/IR/Type.h"
21#include "llvm/IR/Value.h"
24
25#include <cassert>
26#include <utility>
27
28using namespace llvm;
29
30namespace llvm::slpvectorizer {
31
35 ArrayRef<int> Mask, int Index, VectorType *SubTp,
37 VectorType *DstTy = Tp;
38 if (!Mask.empty())
39 DstTy = FixedVectorType::get(Tp->getScalarType(), Mask.size());
40
41 if (Kind != TTI::SK_PermuteTwoSrc)
42 return TTI.getShuffleCost(Kind, DstTy, Tp, CostKind, Mask, Index, SubTp,
43 Args);
44 int NumSrcElts = Tp->getElementCount().getKnownMinValue();
45 int NumSubElts;
46 if (Mask.size() > 2 && ShuffleVectorInst::isInsertSubvectorMask(
47 Mask, NumSrcElts, NumSubElts, Index)) {
48 if (Index + NumSubElts > NumSrcElts &&
49 Index + NumSrcElts <= static_cast<int>(Mask.size()))
50 return TTI.getShuffleCost(TTI::SK_InsertSubvector, DstTy, Tp, CostKind,
51 Mask, Index, Tp);
52 }
53 return TTI.getShuffleCost(Kind, DstTy, Tp, CostKind, Mask, Index, SubTp,
54 Args);
55}
56
57std::pair<InstructionCost, InstructionCost>
59 Value *BasePtr, unsigned Opcode, const TTI::TargetCostKind CostKind,
60 Type *ScalarTy, VectorType *VecTy) {
61 InstructionCost ScalarCost = 0;
62 InstructionCost VecCost = 0;
63 // Here we differentiate two cases: (1) when Ptrs represent a regular
64 // vectorization tree node (as they are pointer arguments of scattered
65 // loads) or (2) when Ptrs are the arguments of loads or stores being
66 // vectorized as plane wide unit-stride load/store since all the
67 // loads/stores are known to be from/to adjacent locations.
68 if (Opcode == Instruction::Load || Opcode == Instruction::Store) {
69 // Case 2: estimate costs for pointer related costs when vectorizing to
70 // a wide load/store.
71 // Scalar cost is estimated as a set of pointers with known relationship
72 // between them.
73 // For vector code we will use BasePtr as argument for the wide load/store
74 // but we also need to account all the instructions which are going to
75 // stay in vectorized code due to uses outside of these scalar
76 // loads/stores.
77 ScalarCost = TTI.getPointersChainCost(
78 Ptrs, BasePtr, TTI::PointersChainInfo::getUnitStride(), ScalarTy,
79 CostKind);
80
81 SmallVector<const Value *> PtrsRetainedInVecCode;
82 for (Value *V : Ptrs) {
83 if (V == BasePtr) {
84 PtrsRetainedInVecCode.push_back(V);
85 continue;
86 }
87 auto *Ptr = dyn_cast<GetElementPtrInst>(V);
88 // For simplicity assume Ptr to stay in vectorized code if it's not a
89 // GEP instruction. We don't care since it's cost considered free.
90 // TODO: We should check for any uses outside of vectorizable tree
91 // rather than just single use.
92 if (!Ptr || !Ptr->hasOneUse())
93 PtrsRetainedInVecCode.push_back(V);
94 }
95
96 if (PtrsRetainedInVecCode.size() == Ptrs.size()) {
97 // If all pointers stay in vectorized code then we don't have
98 // any savings on that.
99 return std::make_pair(TTI::TCC_Free, TTI::TCC_Free);
100 }
101 VecCost = TTI.getPointersChainCost(PtrsRetainedInVecCode, BasePtr,
102 TTI::PointersChainInfo::getKnownStride(),
103 VecTy, CostKind);
104 } else {
105 // Case 1: Ptrs are the arguments of loads that we are going to transform
106 // into masked gather load intrinsic.
107 // All the scalar GEPs will be removed as a result of vectorization.
108 // For any external uses of some lanes extract element instructions will
109 // be generated (which cost is estimated separately).
110 TTI::PointersChainInfo PtrsInfo =
111 all_of(Ptrs,
112 [](const Value *V) {
113 auto *Ptr = dyn_cast<GetElementPtrInst>(V);
114 return Ptr && !Ptr->hasAllConstantIndices();
115 })
116 ? TTI::PointersChainInfo::getUnknownStride()
117 : TTI::PointersChainInfo::getKnownStride();
118
119 ScalarCost =
120 TTI.getPointersChainCost(Ptrs, BasePtr, PtrsInfo, ScalarTy, CostKind);
121 auto *BaseGEP = dyn_cast<GEPOperator>(BasePtr);
122 if (!BaseGEP) {
123 auto *It = find_if(Ptrs, IsaPred<GEPOperator>);
124 if (It != Ptrs.end())
125 BaseGEP = cast<GEPOperator>(*It);
126 }
127 if (BaseGEP) {
128 SmallVector<const Value *> Indices(BaseGEP->indices());
129 VecCost = TTI.getGEPCost(BaseGEP->getSourceElementType(),
130 BaseGEP->getPointerOperand(), Indices, CostKind,
131 VecTy);
132 }
133 }
134
135 return std::make_pair(ScalarCost, VecCost);
136}
137
139 Align Alignment, unsigned AddressSpace,
141 Type *CmpTy = CmpInst::makeCmpResultType(VecTy);
142 return 2 * TTI.getMemIntrinsicInstrCost(
143 MemIntrinsicCostAttributes(Intrinsic::masked_load, VecTy,
144 Alignment, AddressSpace),
145 CostKind) +
146 TTI.getArithmeticInstrCost(Instruction::Xor, CmpTy, CostKind) +
147 TTI.getCmpSelInstrCost(Instruction::Select, VecTy, CmpTy,
149}
150
152 unsigned Opcode, Type *ScalarTy,
153 unsigned NumElts,
155 FixedVectorType **PaddedTy) {
156 FixedVectorType *PaddedVecTy =
157 getMaskedDivRemType(TTI, Opcode, ScalarTy, NumElts, ReVec);
158 if (!PaddedVecTy)
160 // One mask bit per element of the padded vector, not per padded lane.
161 auto *MaskTy =
163 PaddedVecTy->getNumElements());
164 InstructionCost DirectCost = TTI.getArithmeticInstrCost(
165 Opcode, getWidenedType(ScalarTy, NumElts), CostKind);
166 IntrinsicCostAttributes ICA(getMaskedDivRemIntrinsic(Opcode), PaddedVecTy,
167 {PaddedVecTy, PaddedVecTy, MaskTy});
168 InstructionCost MaskedCost = TTI.getIntrinsicInstrCost(ICA, CostKind);
169 if (!MaskedCost.isValid() || MaskedCost >= DirectCost)
171 if (PaddedTy)
172 *PaddedTy = PaddedVecTy;
173 return MaskedCost;
174}
175
178 Type *ScalarTy, VectorType *Ty,
179 const APInt &DemandedElts, bool Insert, bool Extract,
180 const TTI::TargetCostKind CostKind, bool ForPoisonSrc,
183 "ScalableVectorType is not supported.");
184 assert(getNumElements(ScalarTy) * DemandedElts.getBitWidth() ==
185 getNumElements(Ty) &&
186 "Incorrect usage.");
187 if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
188 assert(ReVec && "Only supported by REVEC.");
189 // If ScalarTy is FixedVectorType, we should use CreateInsertVector instead
190 // of CreateInsertElement.
191 unsigned ScalarTyNumElements = VecTy->getNumElements();
193 for (unsigned I : seq(DemandedElts.getBitWidth())) {
194 if (!DemandedElts[I])
195 continue;
196 if (Insert)
198 I * ScalarTyNumElements, VecTy);
199 if (Extract)
201 I * ScalarTyNumElements, VecTy);
202 }
203 return Cost;
204 }
205 return TTI.getScalarizationOverhead(Ty, DemandedElts, Insert, Extract,
206 CostKind, ForPoisonSrc, VL, VIC);
207}
208
210 const TargetTransformInfo &TTI, bool ReVec, Type *ScalarTy, unsigned Opcode,
211 Type *Val, const TTI::TargetCostKind CostKind, unsigned Index,
212 Value *Scalar,
213 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx) {
214 if (Opcode == Instruction::ExtractElement) {
215 if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
216 assert(ReVec && "Only supported by REVEC.");
217 assert(isa<VectorType>(Val) && "Val must be a vector type.");
219 cast<VectorType>(Val), CostKind, {},
220 Index * VecTy->getNumElements(), VecTy);
221 }
222 }
223 return TTI.getVectorInstrCost(Opcode, Val, CostKind, Index, Scalar,
224 ScalarUserAndIdx);
225}
226
228 bool ReVec, unsigned Opcode, Type *Dst,
229 VectorType *VecTy, unsigned Index,
231 if (isVectorizedTy(Dst)) {
232 assert(ReVec && "Only supported by REVEC.");
233 auto *SubTp = cast<FixedVectorType>(
236 Index * getNumElements(Dst), SubTp) +
237 TTI.getCastInstrCost(Opcode, Dst, SubTp, TTI::CastContextHint::None,
238 CostKind);
239 }
240 return TTI.getExtractWithExtendCost(Opcode, Dst, VecTy, Index, CostKind);
241}
242
243} // namespace llvm::slpvectorizer
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
#define I(x, y, z)
Definition MD5.cpp:57
This file contains some templates that are useful if you are working with the STL at all.
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallVector class.
Class for arbitrary precision integers.
Definition APInt.h:78
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1509
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:867
static InstructionCost getInvalid(CostType Val=0)
Information for memory intrinsic cost model.
static LLVM_ABI bool isInsertSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &NumSubElts, int &Index)
Return true if this shuffle mask is an insert subvector mask.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
TargetCostKind
The kind of cost model.
llvm::VectorInstrContext VectorInstrContext
@ TCC_Free
Expected to fold away in lowering.
ShuffleKind
The various kinds of shuffle patterns for vector queries.
@ SK_InsertSubvector
InsertSubvector. Index indicates start offset.
@ SK_PermuteTwoSrc
Merge elements from two source vectors into one with any shuffle mask.
@ SK_ExtractSubvector
ExtractSubvector Index indicates start offset.
@ None
The cast is not used with a load/store of any kind.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:368
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
LLVM Value Representation.
Definition Value.h:75
Base class of all SIMD vector types.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
A private "module" namespace for types and utilities used by this pass.
std::pair< InstructionCost, InstructionCost > getGEPCosts(const TargetTransformInfo &TTI, ArrayRef< Value * > Ptrs, Value *BasePtr, unsigned Opcode, const TTI::TargetCostKind CostKind, Type *ScalarTy, VectorType *VecTy)
Calculate the scalar and the vector costs from vectorizing set of GEPs.
Intrinsic::ID getMaskedDivRemIntrinsic(unsigned Opcode)
Definition SLPUtils.cpp:689
unsigned getNumElements(Type *Ty)
Definition SLPUtils.cpp:83
Type * getWidenedType(Type *ScalarTy, unsigned VF)
InstructionCost getShuffleCost(const TargetTransformInfo &TTI, TTI::ShuffleKind Kind, VectorType *Tp, const TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args)
Returns the cost of the shuffle instructions with the given Kind, vector type Tp and optional Mask.
InstructionCost getBlendedLoadCost(const TargetTransformInfo &TTI, Type *VecTy, Align Alignment, unsigned AddressSpace, const TTI::TargetCostKind CostKind)
Returns the cost of a BlendedLoadVectorize node loading VecTy: two masked loads (one per candidate ba...
FixedVectorType * getMaskedDivRemType(const TargetTransformInfo &TTI, unsigned Opcode, Type *ScalarTy, unsigned NumElts, bool ReVec)
For a non-power-of-2 NumElts-wide integer div/rem Opcode, returns the padded full-register vector typ...
InstructionCost getVectorInstrCost(const TargetTransformInfo &TTI, bool ReVec, Type *ScalarTy, unsigned Opcode, Type *Val, const TTI::TargetCostKind CostKind, unsigned Index, Value *Scalar, ArrayRef< std::tuple< Value *, User *, int > > ScalarUserAndIdx)
This is similar to TargetTransformInfo::getVectorInstrCost, but if ScalarTy is a FixedVectorType,...
InstructionCost getScalarizationOverhead(const TargetTransformInfo &TTI, bool ReVec, Type *ScalarTy, VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, const TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef< Value * > VL, TTI::VectorInstrContext VIC)
This is similar to TargetTransformInfo::getScalarizationOverhead, but if ScalarTy is a FixedVectorTyp...
InstructionCost getExtractWithExtendCost(const TargetTransformInfo &TTI, bool ReVec, unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index, const TTI::TargetCostKind CostKind)
This is similar to TargetTransformInfo::getExtractWithExtendCost, but if Dst is a FixedVectorType,...
InstructionCost getMaskedDivRemCost(const TargetTransformInfo &TTI, bool ReVec, unsigned Opcode, Type *ScalarTy, unsigned NumElts, const TTI::TargetCostKind CostKind, FixedVectorType **PaddedTy)
For a non-power-of-2 NumElts-wide integer div/rem Opcode, checks if padding to a full register and us...
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
InstructionCost Cost
Type * toScalarizedTy(Type *Ty)
A helper for converting vectorized types to scalarized (non-vector) types.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isVectorizedTy(Type *Ty)
Returns true if Ty is a vector type or a struct of vector types where all vector types share the same...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
TargetTransformInfo TTI
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Definition Casting.h:866
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Describe known properties for a set of pointers.