Skip to content

Commit 8ad14b6

Browse files
[TTI]Add support for strided loads/stores.
Added basic legality check and cost estimation functions for strided loads and stores. These interfaces will be built upon in #80310. Reviewers: preames Reviewed By: preames Pull Request: #80329
1 parent 243bfed commit 8ad14b6

File tree

5 files changed

+95
-0
lines changed

5 files changed

+95
-0
lines changed

llvm/include/llvm/Analysis/TargetTransformInfo.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,9 @@ class TargetTransformInfo {
781781
/// Return true if the target supports masked expand load.
782782
bool isLegalMaskedExpandLoad(Type *DataType) const;
783783

784+
/// Return true if the target supports strided load.
785+
bool isLegalStridedLoadStore(Type *DataType, Align Alignment) const;
786+
784787
/// Return true if this is an alternating opcode pattern that can be lowered
785788
/// to a single instruction on the target. In X86 this is for the addsub
786789
/// instruction which corrsponds to a Shuffle + Fadd + FSub pattern in IR.
@@ -1412,6 +1415,20 @@ class TargetTransformInfo {
14121415
Align Alignment, TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput,
14131416
const Instruction *I = nullptr) const;
14141417

1418+
/// \return The cost of strided memory operations.
1419+
/// \p Opcode - is a type of memory access Load or Store
1420+
/// \p DataTy - a vector type of the data to be loaded or stored
1421+
/// \p Ptr - pointer [or vector of pointers] - address[es] in memory
1422+
/// \p VariableMask - true when the memory access is predicated with a mask
1423+
/// that is not a compile-time constant
1424+
/// \p Alignment - alignment of single element
1425+
/// \p I - the optional original context instruction, if one exists, e.g. the
1426+
/// load/store to transform or the call to the gather/scatter intrinsic
1427+
InstructionCost getStridedMemoryOpCost(
1428+
unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask,
1429+
Align Alignment, TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput,
1430+
const Instruction *I = nullptr) const;
1431+
14151432
/// \return The cost of the interleaved memory operation.
14161433
/// \p Opcode is the memory operation code
14171434
/// \p VecTy is the vector type of the interleaved access.
@@ -1848,6 +1865,7 @@ class TargetTransformInfo::Concept {
18481865
Align Alignment) = 0;
18491866
virtual bool isLegalMaskedCompressStore(Type *DataType) = 0;
18501867
virtual bool isLegalMaskedExpandLoad(Type *DataType) = 0;
1868+
virtual bool isLegalStridedLoadStore(Type *DataType, Align Alignment) = 0;
18511869
virtual bool isLegalAltInstr(VectorType *VecTy, unsigned Opcode0,
18521870
unsigned Opcode1,
18531871
const SmallBitVector &OpcodeMask) const = 0;
@@ -2023,6 +2041,11 @@ class TargetTransformInfo::Concept {
20232041
bool VariableMask, Align Alignment,
20242042
TTI::TargetCostKind CostKind,
20252043
const Instruction *I = nullptr) = 0;
2044+
virtual InstructionCost
2045+
getStridedMemoryOpCost(unsigned Opcode, Type *DataTy, const Value *Ptr,
2046+
bool VariableMask, Align Alignment,
2047+
TTI::TargetCostKind CostKind,
2048+
const Instruction *I = nullptr) = 0;
20262049

20272050
virtual InstructionCost getInterleavedMemoryOpCost(
20282051
unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
@@ -2341,6 +2364,9 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
23412364
bool isLegalMaskedExpandLoad(Type *DataType) override {
23422365
return Impl.isLegalMaskedExpandLoad(DataType);
23432366
}
2367+
bool isLegalStridedLoadStore(Type *DataType, Align Alignment) override {
2368+
return Impl.isLegalStridedLoadStore(DataType, Alignment);
2369+
}
23442370
bool isLegalAltInstr(VectorType *VecTy, unsigned Opcode0, unsigned Opcode1,
23452371
const SmallBitVector &OpcodeMask) const override {
23462372
return Impl.isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask);
@@ -2671,6 +2697,14 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
26712697
return Impl.getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask,
26722698
Alignment, CostKind, I);
26732699
}
2700+
InstructionCost
2701+
getStridedMemoryOpCost(unsigned Opcode, Type *DataTy, const Value *Ptr,
2702+
bool VariableMask, Align Alignment,
2703+
TTI::TargetCostKind CostKind,
2704+
const Instruction *I = nullptr) override {
2705+
return Impl.getStridedMemoryOpCost(Opcode, DataTy, Ptr, VariableMask,
2706+
Alignment, CostKind, I);
2707+
}
26742708
InstructionCost getInterleavedMemoryOpCost(
26752709
unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
26762710
Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,

llvm/include/llvm/Analysis/TargetTransformInfoImpl.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ class TargetTransformInfoImplBase {
304304

305305
bool isLegalMaskedExpandLoad(Type *DataType) const { return false; }
306306

307+
bool isLegalStridedLoadStore(Type *DataType, Align Alignment) const {
308+
return false;
309+
}
310+
307311
bool enableOrderedReductions() const { return false; }
308312

309313
bool hasDivRemOp(Type *DataType, bool IsSigned) const { return false; }
@@ -687,6 +691,14 @@ class TargetTransformInfoImplBase {
687691
return 1;
688692
}
689693

694+
InstructionCost getStridedMemoryOpCost(unsigned Opcode, Type *DataTy,
695+
const Value *Ptr, bool VariableMask,
696+
Align Alignment,
697+
TTI::TargetCostKind CostKind,
698+
const Instruction *I = nullptr) const {
699+
return InstructionCost::getInvalid();
700+
}
701+
690702
unsigned getInterleavedMemoryOpCost(
691703
unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
692704
Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,

llvm/lib/Analysis/TargetTransformInfo.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,11 @@ bool TargetTransformInfo::isLegalMaskedExpandLoad(Type *DataType) const {
500500
return TTIImpl->isLegalMaskedExpandLoad(DataType);
501501
}
502502

503+
bool TargetTransformInfo::isLegalStridedLoadStore(Type *DataType,
504+
Align Alignment) const {
505+
return TTIImpl->isLegalStridedLoadStore(DataType, Alignment);
506+
}
507+
503508
bool TargetTransformInfo::enableOrderedReductions() const {
504509
return TTIImpl->enableOrderedReductions();
505510
}
@@ -1037,6 +1042,16 @@ InstructionCost TargetTransformInfo::getGatherScatterOpCost(
10371042
Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) const {
10381043
InstructionCost Cost = TTIImpl->getGatherScatterOpCost(
10391044
Opcode, DataTy, Ptr, VariableMask, Alignment, CostKind, I);
1045+
assert((!Cost.isValid() || Cost >= 0) &&
1046+
"TTI should not produce negative costs!");
1047+
return Cost;
1048+
}
1049+
1050+
InstructionCost TargetTransformInfo::getStridedMemoryOpCost(
1051+
unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask,
1052+
Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) const {
1053+
InstructionCost Cost = TTIImpl->getStridedMemoryOpCost(
1054+
Opcode, DataTy, Ptr, VariableMask, Alignment, CostKind, I);
10401055
assert(Cost >= 0 && "TTI should not produce negative costs!");
10411056
return Cost;
10421057
}

llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,29 @@ InstructionCost RISCVTTIImpl::getGatherScatterOpCost(
658658
return NumLoads * MemOpCost;
659659
}
660660

661+
InstructionCost RISCVTTIImpl::getStridedMemoryOpCost(
662+
unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask,
663+
Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) {
664+
if (((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
665+
!isLegalStridedLoadStore(DataTy, Alignment)) ||
666+
(Opcode != Instruction::Load && Opcode != Instruction::Store))
667+
return BaseT::getStridedMemoryOpCost(Opcode, DataTy, Ptr, VariableMask,
668+
Alignment, CostKind, I);
669+
670+
if (CostKind == TTI::TCK_CodeSize)
671+
return TTI::TCC_Basic;
672+
673+
// Cost is proportional to the number of memory operations implied. For
674+
// scalable vectors, we use an estimate on that number since we don't
675+
// know exactly what VL will be.
676+
auto &VTy = *cast<VectorType>(DataTy);
677+
InstructionCost MemOpCost =
678+
getMemoryOpCost(Opcode, VTy.getElementType(), Alignment, 0, CostKind,
679+
{TTI::OK_AnyValue, TTI::OP_None}, I);
680+
unsigned NumLoads = getEstimatedVLFor(&VTy);
681+
return NumLoads * MemOpCost;
682+
}
683+
661684
// Currently, these represent both throughput and codesize costs
662685
// for the respective intrinsics. The costs in this table are simply
663686
// instruction counts with the following adjustments made:

llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
143143
TTI::TargetCostKind CostKind,
144144
const Instruction *I);
145145

146+
InstructionCost getStridedMemoryOpCost(unsigned Opcode, Type *DataTy,
147+
const Value *Ptr, bool VariableMask,
148+
Align Alignment,
149+
TTI::TargetCostKind CostKind,
150+
const Instruction *I);
151+
146152
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
147153
TTI::CastContextHint CCH,
148154
TTI::TargetCostKind CostKind,
@@ -250,6 +256,11 @@ class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
250256
return ST->is64Bit() && !ST->hasVInstructionsI64();
251257
}
252258

259+
bool isLegalStridedLoadStore(Type *DataType, Align Alignment) {
260+
EVT DataTypeVT = TLI->getValueType(DL, DataType);
261+
return TLI->isLegalStridedLoadStore(DataTypeVT, Alignment);
262+
}
263+
253264
bool isVScaleKnownToBeAPowerOfTwo() const {
254265
return TLI->isVScaleKnownToBeAPowerOfTwo();
255266
}

0 commit comments

Comments
 (0)