LLVM: lib/Target/RISCV/RISCVInterleavedAccess.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
21#include "llvm/IR/IntrinsicsRISCV.h"
24
25using namespace llvm;
26
28 VectorType *VTy, unsigned Factor, Align Alignment, unsigned AddrSpace,
31
33 return false;
34
37 Alignment))
38 return false;
39
41
43 if (!Subtarget.useRVVForFixedLengthVectors())
44 return false;
45
46
47 if (FVTy->getNumElements() < 2)
48 return false;
49
51 }
52
53
55 if (Fractional)
56 return true;
57 return Factor * LMUL <= 8;
58}
59
61 Intrinsic::riscv_seg2_load_mask, Intrinsic::riscv_seg3_load_mask,
62 Intrinsic::riscv_seg4_load_mask, Intrinsic::riscv_seg5_load_mask,
63 Intrinsic::riscv_seg6_load_mask, Intrinsic::riscv_seg7_load_mask,
64 Intrinsic::riscv_seg8_load_mask};
65
67 Intrinsic::riscv_sseg2_load_mask, Intrinsic::riscv_sseg3_load_mask,
68 Intrinsic::riscv_sseg4_load_mask, Intrinsic::riscv_sseg5_load_mask,
69 Intrinsic::riscv_sseg6_load_mask, Intrinsic::riscv_sseg7_load_mask,
70 Intrinsic::riscv_sseg8_load_mask};
71
73 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
74 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
75 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
76 Intrinsic::riscv_vlseg8_mask};
77
79 Intrinsic::riscv_seg2_store_mask, Intrinsic::riscv_seg3_store_mask,
80 Intrinsic::riscv_seg4_store_mask, Intrinsic::riscv_seg5_store_mask,
81 Intrinsic::riscv_seg6_store_mask, Intrinsic::riscv_seg7_store_mask,
82 Intrinsic::riscv_seg8_store_mask};
83
85 Intrinsic::riscv_sseg2_store_mask, Intrinsic::riscv_sseg3_store_mask,
86 Intrinsic::riscv_sseg4_store_mask, Intrinsic::riscv_sseg5_store_mask,
87 Intrinsic::riscv_sseg6_store_mask, Intrinsic::riscv_sseg7_store_mask,
88 Intrinsic::riscv_sseg8_store_mask};
89
91 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
92 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
93 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
94 Intrinsic::riscv_vsseg8_mask};
95
98 if (N == 1)
99 return true;
100
102
107 return true;
108
112 }
113
114 return false;
115}
116
117
118
122
127 assert(LI->isSimple());
128 Ptr = LI->getPointerOperand();
129 Alignment = LI->getAlign();
130 assert(!Mask && "Unexpected mask on a load");
131 Mask = Builder.getAllOnesMask(EC);
134 return true;
135 }
138 Ptr = SI->getPointerOperand();
139 Alignment = SI->getAlign();
140 assert(!Mask && "Unexpected mask on a store");
141 Mask = Builder.getAllOnesMask(EC);
144 return true;
145 }
146
148 switch (II->getIntrinsicID()) {
149 default:
151 case Intrinsic::vp_load:
152 case Intrinsic::vp_store: {
154 Ptr = VPLdSt->getMemoryPointerParam();
155 Alignment = VPLdSt->getPointerAlignment().value_or(
156 DL.getABITypeAlign(VTy->getElementType()));
157
158 assert(Mask && "vp.load and vp.store needs a mask!");
159
160 Value *WideEVL = VPLdSt->getVectorLengthParam();
161
162
163 if ((WideEVL, I->getDataLayout(), Factor))
164 return false;
165
166 auto *FactorC = ConstantInt::get(WideEVL->getType(), Factor);
167 VL = Builder.CreateZExt(Builder.CreateExactUDiv(WideEVL, FactorC), XLenTy);
168 return true;
169 }
170 case Intrinsic::masked_load: {
171 Ptr = II->getOperand(0);
172 Alignment = II->getParamAlign(0).valueOrOne();
173
175 return false;
176
177 assert(Mask && "masked.load needs a mask!");
178
180 ? Builder.CreateElementCount(XLenTy, VTy->getElementCount())
182 return true;
183 }
184 case Intrinsic::masked_store: {
185 Ptr = II->getOperand(1);
186 Alignment = II->getParamAlign(1).valueOrOne();
187
188 assert(Mask && "masked.store needs a mask!");
189
191 ? Builder.CreateElementCount(XLenTy, VTy->getElementCount())
193 return true;
194 }
195 }
196}
197
198
199
200
201
202
203
204
205
206
207
208
209
215
216
217
218 unsigned MaskFactor = GapMask.popcount();
219 if (MaskFactor < 2 || !GapMask.isMask())
220 return false;
222
223 const DataLayout &DL = Load->getDataLayout();
225 auto *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
226
229 if ((MaskFactor, VTy, XLenTy, Load, Ptr, Mask, VL, Alignment))
230 return false;
231
235 return false;
236
238 if (MaskFactor < Factor) {
239
240 unsigned ScalarSizeInBytes = DL.getTypeStoreSize(VTy->getElementType());
241 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
242 SegLoad = Builder.CreateIntrinsic(FixedVlssegIntrIds[MaskFactor - 2],
243 {VTy, PtrTy, XLenTy, XLenTy},
244 {Ptr, Stride, Mask, VL});
245 } else {
246
248 {VTy, PtrTy, XLenTy}, {Ptr, Mask, VL});
249 }
250
251 for (unsigned i = 0; i < Shuffles.size(); i++) {
252 unsigned FactorIdx = Indices[i];
253 if (FactorIdx >= MaskFactor) {
254
256 } else {
257 Value *SubVec = Builder.CreateExtractValue(SegLoad, FactorIdx);
258 Shuffles[i]->replaceAllUsesWith(SubVec);
259 }
260 }
261
262 return true;
263}
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
284 unsigned Factor,
285 const APInt &GapMask) const {
287
288
289
290 unsigned MaskFactor = GapMask.popcount();
291 if (MaskFactor < 2 || !GapMask.isMask())
292 return false;
293
295 const DataLayout &DL = Store->getDataLayout();
298
300 ShuffleVTy->getNumElements() / Factor);
301 auto *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
302
305 if ((MaskFactor, VTy, XLenTy, Store, Ptr, LaneMask, VL,
306 Alignment))
307 return false;
308
312 return false;
313
315 if (MaskFactor < Factor)
316
319 {VTy, PtrTy, XLenTy, XLenTy});
320 else
321
324 {VTy, PtrTy, XLenTy});
325
328
329 for (unsigned i = 0; i < MaskFactor; i++) {
330
331 for (unsigned j = 0; j < VTy->getNumElements(); j++)
332 NewShuffleMask.push_back(Mask[i + Factor * j]);
333
334 Value *Shuffle = Builder.CreateShuffleVector(
336 Ops.push_back(Shuffle);
337
338 NewShuffleMask.clear();
339 }
340 Ops.push_back(Ptr);
341 if (MaskFactor < Factor) {
342
343 unsigned ScalarSizeInBytes = DL.getTypeStoreSize(VTy->getElementType());
344 Ops.push_back(ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes));
345 }
346 Ops.append({LaneMask, VL});
347 Builder.CreateCall(SegStoreFunc, Ops);
348
349 return true;
350}
351
355 if (Factor > 8)
356 return false;
357
359
361
362 const DataLayout &DL = Load->getDataLayout();
363 auto *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
364
367 if ((Factor, ResVTy, XLenTy, Load, Ptr, Mask, VL, Alignment))
368 return false;
369
373 return false;
374
378 {ResVTy, PtrTy, XLenTy}, {Ptr, Mask, VL});
379 } else {
380 unsigned SEW = DL.getTypeSizeInBits(ResVTy->getElementType());
383 Load->getContext(), "riscv.vector.tuple",
385 Factor);
388 {VecTupTy, PtrTy, Mask->getType(), VL->getType()});
389
390 Value *Operands[] = {
392 Ptr,
393 Mask,
394 VL,
395 ConstantInt::get(XLenTy,
397 ConstantInt::get(XLenTy, Log2_64(SEW))};
398
399 CallInst *Vlseg = Builder.CreateCall(VlsegNFunc, Operands);
400
403 for (unsigned i = 0; i < Factor; ++i) {
404 Value *VecExtract = Builder.CreateIntrinsic(
405 Intrinsic::riscv_tuple_extract, {ResVTy, VecTupTy},
406 {Vlseg, Builder.getInt32(i)});
407 Return = Builder.CreateInsertValue(Return, VecExtract, i);
408 }
409 }
410
412 return true;
413}
414
417 unsigned Factor = InterleaveValues.size();
418 if (Factor > 8)
419 return false;
420
422
424 const DataLayout &DL = Store->getDataLayout();
425 Type *XLenTy = Builder.getIntNTy(Subtarget.getXLen());
426
429 if ((Factor, InVTy, XLenTy, Store, Ptr, Mask, VL, Alignment))
430 return false;
434 return false;
435
439 {InVTy, PtrTy, XLenTy});
441 Ops.append({Ptr, Mask, VL});
442 Builder.CreateCall(VssegNFunc, Ops);
443 return true;
444 }
445 unsigned SEW = DL.getTypeSizeInBits(InVTy->getElementType());
446 unsigned NumElts = InVTy->getElementCount().getKnownMinValue();
448 Store->getContext(), "riscv.vector.tuple",
450
452 for (unsigned i = 0; i < Factor; ++i)
453 StoredVal = Builder.CreateIntrinsic(
454 Intrinsic::riscv_tuple_insert, {VecTupTy, InVTy},
455 {StoredVal, InterleaveValues[i], Builder.getInt32(i)});
456
459 {VecTupTy, PtrTy, Mask->getType(), VL->getType()});
460
461 Value *Operands[] = {StoredVal, Ptr, Mask, VL,
462 ConstantInt::get(XLenTy, Log2_64(SEW))};
463 Builder.CreateCall(VssegNFunc, Operands);
464 return true;
465}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
uint64_t IntrinsicInst * II
static const Intrinsic::ID FixedVlsegIntrIds[]
Definition RISCVInterleavedAccess.cpp:60
static bool isMultipleOfN(const Value *V, const DataLayout &DL, unsigned N)
Definition RISCVInterleavedAccess.cpp:96
static const Intrinsic::ID ScalableVlsegIntrIds[]
Definition RISCVInterleavedAccess.cpp:72
static const Intrinsic::ID ScalableVssegIntrIds[]
Definition RISCVInterleavedAccess.cpp:90
static const Intrinsic::ID FixedVlssegIntrIds[]
Definition RISCVInterleavedAccess.cpp:66
static bool getMemOperands(unsigned Factor, VectorType *VTy, Type *XLenTy, Instruction *I, Value *&Ptr, Value *&Mask, Value *&VL, Align &Alignment)
Do the common operand retrieval and validition required by the routines below.
Definition RISCVInterleavedAccess.cpp:119
static const Intrinsic::ID FixedVsssegIntrIds[]
Definition RISCVInterleavedAccess.cpp:84
static const Intrinsic::ID FixedVssegIntrIds[]
Definition RISCVInterleavedAccess.cpp:78
static SymbolRef::Type getType(const Symbol *Sym)
Class for arbitrary precision integers.
unsigned popcount() const
Count the number of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isMask(unsigned numBits) const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
A parsed version of the target data layout string in and methods for querying it.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
bool lowerDeinterleaveIntrinsicToLoad(Instruction *Load, Value *Mask, IntrinsicInst *DI) const override
Lower a deinterleave intrinsic to a target specific load intrinsic.
Definition RISCVInterleavedAccess.cpp:352
bool lowerInterleavedStore(Instruction *Store, Value *Mask, ShuffleVectorInst *SVI, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved store into a vssegN intrinsic.
Definition RISCVInterleavedAccess.cpp:281
MVT getContainerForFixedLengthVector(MVT VT) const
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vlsegN intrinsic.
Definition RISCVInterleavedAccess.cpp:210
bool lowerInterleaveIntrinsicToStore(Instruction *Store, Value *Mask, ArrayRef< Value * > InterleaveValues) const override
Lower an interleave intrinsic to a target specific store intrinsic.
Definition RISCVInterleavedAccess.cpp:415
bool isLegalElementTypeForRVV(EVT ScalarTy) const
bool isLegalInterleavedAccessType(VectorType *VTy, unsigned Factor, Align Alignment, unsigned AddrSpace, const DataLayout &) const
Returns whether or not generating a interleaved load/store intrinsic for this type will be legal.
Definition RISCVInterleavedAccess.cpp:27
static RISCVVType::VLMUL getLMUL(MVT VT)
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
This instruction constructs a fixed permutation of two input vectors.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static LLVM_ABI TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types={}, ArrayRef< unsigned > Ints={})
Return a target extension type having the specified name and optional type and integer parameters.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
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...
Type * getElementType() const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
bool match(Val *V, const Pattern &P)
class_match< ConstantInt > m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWMul(const LHS &L, const RHS &R)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
match_combine_or< LTy, RTy > m_CombineOr(const LTy &L, const RTy &R)
Combine two pattern matchers matching L || R.
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
LLVM_ABI unsigned getDeinterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.deinterleaveN intrinsics.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI VectorType * getDeinterleavedVectorType(IntrinsicInst *DI)
Given a deinterleaveN intrinsic, return the (narrow) vector type of each factor.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
This struct is a compact representation of a valid (non-zero power of two) alignment.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
unsigned countMinTrailingZeros() const
Returns the minimum number of trailing zero bits.